Inside a process I do some work on UNSIGNED vectors which I need to slice and cast back to a SLV at the end of the process. Is there a nicer/cleaner way than this?
out_O : out STD_LOGIC_VECTOR(15 downto 0)
variable o : UNSIGNED(17 downto 0) := (others => '0');
variable outcast_t : STD_LOGIC_VECTOR(17 downto 0) := (others => '0');
...
o := mod_t - div_t + const;
outcast_t := STD_LOGIC_VECTOR(o);
out_O <= outcast_t(15 downto 0);
With
use ieee.numeric_std_unsigned.all;
slv will be handled as unsigned and you can do your operations on that type directly such that you avoid casting.
You can also do something like this
out_O <= o(out_O'range);
which may save you some changes if the size of out_O is modified. Assuming that you redefined o as slv.
Related
I am receiving a data. For storing that I have declared an array:
type fifo_array is array(0 to 66) of std_logic_vector(7 downto 0);
signal ins_fifo_array: fifo_array := (others => (others => '0'));
During process, this gets filled with different words(bytes). I want to subtract an offset of x30(hex) from all the elements of this array and assign it to another array for further processing. Obviously initializing it like:
type fifo_second_array is array(0 to 66) of std_logic_vector(7 downto 0);
signal ins_fifo_second_array: fifo_second_array := (ins_fifo_array - x"30");
not working. There is another solution like:
type fifo_second_array is array(0 to 66) of std_logic_vector(7 downto 0);
signal ins_fifo_second_array: fifo_second_array := (ins_fifo_array(0) - x"30",....);
Which is also not working. Please suggest.
process(ins_fifo_array)
variable I : natural;
constant C_x30 : unsigned := x"30";
begin
for I in 0 to 66 loop
ins_fifo_second_array(I) <= std_logic_vector(unsigned(ins_fifo_array(I)) - C_x30);
end loop;
end process;
I had an error while working on ones counter inside the process.
I use numeric_std library. Here is the key part of the code.
signal one_buf : unsigned(7 downto 0);
signal out_buf : std_logic_vector(7 downto 0);
counter_one : process(out_buf1)
variable one_buf1 : unsigned(7 downto 0) := (others => '0');
begin
for i in 0 to 7 loop
one_buf1 := one_buf1 + unsigned(out_buf(i));
end loop;
one_buf <= one_buf1;
end process counter_one;
The error message is
Error(10305) cannot convert type "std_ulogic" to type "UNSIGNED".
I do not understand what is wrong here.
Thanks in advance for the answers.
Why would this setup work?
component mux2to1 is
generic (M : integer := 1); -- Number of bits in the inputs and output
port (input0 : in m32_vector(M-1 downto 0) := (others => '0');
input1 : in m32_vector(M-1 downto 0) := (others => '0');
sel : in m32_1bit;
output : out m32_vector(M-1 downto 0));
end component;
The way I understand genric map is (M: integer: 1) would specify the bit of port to be 1 through out but when M-1 downto 0 would just be 0 down 0, which makes no sense.
As #user1155120 said, you can have an array that has 1 element. (0 downto 0) would have 1 element.
There is another important point to make, however:
In VHDL an array of 1 element of a certain type is not the same type as the element type. So, for example, std_logic and std_logic_vector(0 downto 0) are different types. You cannot assign one to the other. std_logic is a scalar whilst std_logic_vector(0 downto 0) is an array type.
To "convert" between these types, you need to index the array type. So, with signals
signal S : std_logic;
signal A : std_logic_vector(0 downto 0);
you cannot assign A to S or visa versa, but you can do this:
A(0) <= S;
or this:
S <= A(0);
You can also index array ports. So, with
entity HAS_ARRAY_PORT
port ( P : in std_logic_vector(0 downto 0));
end;
You can do this:
L: entity work.HAS_ARRAY_PORT port map (P(0) => S);
I am trying to implement a cache memory 16 * 37 in VHDL in DesignWorks 5. The code is given below.
The code runs but when i change values from IO panel or even simulate anyway, the timing diagram shows nothing and basically the code is not running for some reason. Any suggestions would be really helpful.
Code:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
entity Cache is
port(cs, r, clr : in std_logic;
data : in std_logic_vector(31 downto 0);
addr : in std_logic_vector(7 downto 0);
cline : out std_logic_vector(31 downto 0);
ctag: out std_logic_vector(3 downto 0);
v : out std_logic);
end Cache;
architecture behav of Cache is
type RAM is array (0 to 15) of std_logic_vector(36 downto 0);
begin
process is
variable M : RAM;
variable locn : natural;
variable temp_val : std_logic_vector(36 downto 0);
variable cline_val : std_logic_vector(31 downto 0);
variable ctag_val : std_logic_vector(3 downto 0);
variable v_val : std_logic;
begin
if cs = '1' then
locn := to_integer(addr);
if r = '1' then
temp_val := M(locn);
cline_val := temp_val(31 downto 0);
ctag_val := temp_val(35 downto 32);
v_val := temp_val(36);
else
temp_val(31 downto 0) := data;
temp_val(35 downto 32) := addr(3 downto 0);
temp_val(36) := '1';
M(locn) := temp_val;
v_val := 'Z';
ctag_val:= "ZZZZ";
cline_val:= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
end if;
end if;
if clr ='1' then
locn := 0;
while(locn<16) loop
M(locn) := X"000000000" + "0";
locn:=locn+1;
end loop;
end if;
cline <= cline_val;
ctag <= ctag_val;
v <= v_val;
wait on cs;
end process;
end behav;
This line:
M(locn) := X"000000000" + "0";
appears incorrect.
M is your ram array type with an element length of 37. A 36 bit zero added to zero is still 36 bits (it doesn't look like you reached this statement, it would be a run time error).
To make a length 37 vector of '0' values use `(others => '0').
You can also use a for loop for the ram clear, you need to not use an index of 16, it's out of range, which tells us you didn't reach the clear either.
I think you ought to show us your stimulus otherwise your problems can't be reproduced.
Your missing data and addr as sensitivity elements (and ya, you case cs surrounds, but you want to build a hardware model here).
Switch to a sensitivity list (cs, data, addr).
locn is an unconstrained natural and should have a range matching the array type ram (0 to 15). Notice your while loop reaches 16. Really, use a for loop (shown below). The reason for constraining locn is to prevent a bound error when accessing ram(locn).
Note for converting addr to a natural (locn) you need to AND mask addr with a length four run of '1's to prevent a range error for normal ram operations.
The package numeric_std is an affectation, it's easier than passing a couple of command line options to ghdl (ieee=synopsys -fexplict) during analysis and elaboration.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity cache is
port (
cs, r, clr: in std_logic;
data: in std_logic_vector(31 downto 0);
addr: in std_logic_vector(7 downto 0);
cline: out std_logic_vector(31 downto 0);
ctag: out std_logic_vector(3 downto 0);
v: out std_logic
);
end entity;
architecture behav of cache is
type ram is array (0 to 15) of std_logic_vector(36 downto 0);
begin
process (cs, data, addr)
variable m : ram;
variable locn : natural range (ram'range);
variable temp_val : std_logic_vector(36 downto 0);
variable cline_val : std_logic_vector(31 downto 0);
variable ctag_val : std_logic_vector(3 downto 0);
variable v_val : std_logic;
begin
if cs = '1' then
locn := to_integer(unsigned(addr and x"0F"));
if r = '1' then
temp_val := m(locn);
cline_val := temp_val(31 downto 0);
ctag_val := temp_val(35 downto 32);
v_val := temp_val(36);
else
temp_val(31 downto 0) := data;
temp_val(35 downto 32) := addr(3 downto 0);
temp_val(36) := '1';
m(locn) := temp_val;
v_val := 'Z';
ctag_val:= "ZZZZ";
cline_val:= (others => 'Z');
end if;
end if;
if clr ='1' then
for i in ram'range loop
m(i) := (others => '0');
end loop;
end if;
cline <= cline_val;
ctag <= ctag_val;
v <= v_val;
end process;
end architecture;
This code analyzes and elaborates, you could have an error somewhere I didn't mention, and bound (range) errors show up at run time in assignments (expressions can not care).
And one final bit:
temp_val(31 downto 0) := data;
temp_val(35 downto 32) := addr(3 downto 0);
temp_val(36) := '1';
can be expressed:
temp_val:= '1' & addr(3 downto 0) & data;
As well as:
locn := to_integer(addr);
expressed as:
locn := to_integer(addr(3 downto 0));
You can also create an AND mask with a length defined algorithmically from the ram'range should you set the ram size with a generic.
And without seeing your stimulus there are several places that could cause run time errors. Check your console output.
Here is the code: In this the calculation for the parity bit is not done. Parity bit can be calculated using the for loop but is there any other short or better way to calculate the even parity bit in this context.
Is it somehow possible to use arrays instead of 8 TxDataReg std_logic_vector considering that after making arrays I wish to access bit by bit the array of 8 signals of 8 bits, bit by bit for sending the data in the uart_tx port?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Uart_tx is
Port (
tx_clk_in : in STD_LOGIC;
reset : in STD_LOGIC;
tx : out STD_LOGIC;
Rx_Data_in : in STD_LOGIC_VECTOR(63 downto 0)
);
end Uart_tx;
architecture Behavioral of Uart_tx is
signal Tx_Data : STD_LOGIC_VECTOR(63 downto 0) := "00000000";
signal DataByteArray1 : std_logic_vector(7 downto 0) := (others => "00000000");
signal DataByteArray2 : std_logic_vector(7 downto 0) := (others => "00000000");
signal DataByteArray3 : std_logic_vector(7 downto 0) := (others => "00000000");
signal DataByteArray4 : std_logic_vector(7 downto 0) := (others => "00000000");
signal DataByteArray5 : std_logic_vector(7 downto 0) := (others => "00000000");
signal DataByteArray6 : std_logic_vector(7 downto 0) := (others => "00000000");
signal DataByteArray7 : std_logic_vector(7 downto 0) := (others => "00000000");
signal DataByteArray8 : std_logic_vector(7 downto 0) := (others => "00000000");
signal TxDataReg1 : std_logic_vector(10 downto 0) := (others => "00000000");
signal TxDataReg2 : std_logic_vector(10 downto 0) := (others => "00000000");
signal TxDataReg3 : std_logic_vector(10 downto 0) := (others => "00000000");
signal TxDataReg4 : std_logic_vector(10 downto 0) := (others => "00000000");
signal TxDataReg5 : std_logic_vector(10 downto 0) := (others => "00000000");
signal TxDataReg6 : std_logic_vector(10 downto 0) := (others => "00000000");
signal TxDataReg7 : std_logic_vector(10 downto 0) := (others => "00000000");
signal TxDataReg8 : std_logic_vector(10 downto 0) := (others => "00000000");
signal count : unsigned(2 downto 0) := (others => '0');
signal one_bit : std_logic := '0';
begin
Tx_Data <= Rx_Data_in;
DataByteArray1 <= Rx_Data_in(7 downto 0);
DataByteArray2 <= Rx_Data_in(15 downto 8);
DataByteArray3 <= Rx_Data_in(23 downto 16);
DataByteArray4 <= Rx_Data_in(31 downto 24);
DataByteArray5 <= Rx_Data_in(39 downto 32);
DataByteArray6 <= Rx_Data_in(47 downto 40);
DataByteArray7 <= Rx_Data_in(55 downto 48);
DataByteArray8 <= Rx_Data_in(63 downto 56);
Process (tx_clk_in)
begin
-- Calculate the parity bit
for i in 0 to 7 loop
one_bit = DataByteArray1(i);
if one_bit = '1' then
count = count + 1;
end if;
end loop;
-- For all the registers,one even parity & two stop bits I am trying to add in the end
if count mod 2 = 0 then
TxDataReg1 <= DataByteArray1&'0'&'11'; -- I am not so sure that this works or not
count <= "000";
else
TxDataReg1 <= DataByteArray1&'1'&'11';
count <= "000";
end if;
-- Send the uart data from TxDataReg1,TxDataReg2 ...
-- etc.
end process;
end behavioral;
This UART would be much easier to understand if you created a State Machine. State Machines give your code an organized flow. The flow just makes more sense. In VHDL you can create enumerated states which means that you can give them names. I recommend this approach.
It's much harder to keep counters throughout your design to know exactly when to insert the parity bit or when to insert the 2 stop bits in your UART design. If you have a nice state machine it will make much more sense to you I believe. This is especially recommended for anyone new at FPGAs.
When you calculate your parity, just keep a running parity bit that gets an XOR with the outgoing serial data. Create a state to insert your parity bit at the correct time, then insert your two stop bits.
For an example of this, look at this UART VHDL Code
I would second the suggestion to reorganize this to use an FSM that works on just a byte at a time. Then you will have a general purpose async. TX entity that another controller can send bytes to as needed.
As to managing your data. It would be simpler if you created an array of byte arrays:
subtype byte is std_logic_Vector(7 downto 0);
type byte_array is array(natural range <>) of byte;
signal data_byte_array : byte_array(1 to 8);
signal byte_index : unsigned(2 downto 0);
...
-- Select the current byte
cur_byte <= data_byte_array(to_integer(byte_index));
The subtype isn't strictly necessary but it is a good habit to use for common data types to save you from littering your code with so many hard-coded array bounds.
For calculating parity you need to adopt the hardware mindset of implementing logic gates rather than the software approach of counting set bits. Parity calculation boils down to an XOR-reduce operation applied to all the bits in your vector. For even parity, you XOR all bits. For odd parity, you XOR all bits and invert the result. Because XOR is equivalent to a controlled inversion you can select the parity type by setting an initial state and performing one extra XOR to get the optional inversion based on your desire for odd or even.
-- Any VHDL:
variable parity : std_logic;
parity := '0'; -- Set to '1' to get odd parity
for i in cur_byte'range loop
parity := parity xor cur_byte(i);
end loop;
-- VHDL-2002
use ieee.reduce_pack.xor_reduce;
parity := xor_reduce(cur_byte);
-- VHDL-2008
parity := xor cur_byte;
In synthesis these approaches all boil down to the same logic so any of them is fine for all practical purposes. This is an explicitly parallel operation and you don't have to step through the byte bitwise with the unneeded overhead of a counter.
You have committed a cardinal sin of mixing the non-standard Synopsys libraries std_logic_unsigned, _signed, and _arith with the true standard numeric library numeric_std. Never mix them in the same file and, better yet, never use the Synopsys libraries at all. They are a historical aberration best forgotten.