I have created a two dimensional array.
type dataout is array (12 downto 0, 12 downto 0) of std_logic_vector(7 downto 0);
signal a : dataout;
The values are passing through the array and operation like addition and subtraction are also performing but i am not getting the way to pass this value of array to pass through another signal or output port.
Suggest me how to pass these values to another array, signal and output port.
Simply create an output port of type dataout and assign a to it.
To do this, the declaration of dataout must be in a package
package my_types is
type dataout is array (12 downto 0, 12 downto 0) of std_logic_vector(7 downto 0);
end package my_types;
which you use both in this entity/arch and any outer layer that instantiates it.
use work.my_types.all;
entity test is
port(
clock : in std_logic;
a_out : out dataout
);
end test;
architecture t of test is
signal a : dataout;
begin
a_out <= a;
end t;
Related
Suppose I have defined a record with fields of std_ulogic_vector to represent a larger std_ulogic_vector. It's straightforward to convert this record to the large vector using a concatenation (without knowledge of the size for each field).
How do I do the reverse, e.g. convert the large std_ulogic_vector back to the record ?
Example :
architecture RTL of record_conversion is
type data_t is record
top : std_ulogic_vector(4 downto 0);
bottom : std_ulogic_vector(2 downto 0);
end record data_t;
signal record_s : data_t;
signal vector_s : std_ulogic_vector(7 downto 0);
begin
-- vector to record works
--vector_s <= record_s.top & record_s.bottom;
-- record to vector does not work
(record_s.top, record_s.bottom) <= vector_s;
-- tedious solution with knowledge of the field size
record_s.top <= vector_s(7 downto 3);
record_s.bottom <= vector_s(2 downto 0);
end architecture;
It is usually a good idea to wrap such conversion in functions, and with a subtype for resulting vector, like:
...
constant LEN : integer := 8; -- Number of bits in data_t
type data_t is record
top : std_ulogic_vector(4 downto 0);
bottom : std_ulogic_vector(2 downto 0);
end record data_t;
subtype vector_t is std_ulogic_vector(LEN - 1 downto 0);
function data_to_vector(data : data_t) return std_ulogic_vector is
variable res_v : vector_t;
begin
res_v := data.top & data.bottom;
return res_v;
end function;
function vector_to_data(vector : vector_t) return data_t is
variable res_v : data_t;
begin
res_v.top := vector(LEN - 1 downto LEN - res_v.top'length);
res_v.bottom := vector(res_v.bottom'length - 1 downto 0);
return res_v;
end function;
signal record_s : data_t;
signal vector_s : vector_t;
begin
record_s <= vector_to_data(vector_s);
vector_s <= data_to_vector(record_s);
...
Maybe another constant should be added to define the split between top and bottom.
There are a couple of other methods besides using subprogram calls to assign elements of one type to elements of another type.
You can use a qualified expression:
record_s <= data_t'(vector_s(7 downto 3), vector_s (2 downto 0));
Where the aggregate comprised of two slices of vector_s with an explicit type matching the record. See IEEE Std 1076-2008 9.3.6 Qualified expressions.
During simulation new values for signals are validated. See 14.7.3.4 Signal update:
b) If S is a composite signal (including a slice of an array), the effective value of S is implicitly converted to the subtype of S. The subtype conversion checks that for each element of S there is a matching element in the effective value and vice versa. An error occurs if this check fails. The result of this subtype conversion is then assigned to the variable representing the current value of S.
Besides having a matching element (subelement,...) subtype conversion changes the index ranges to match the target.
You can specify the slice index ranges with subtype index ranges:
library ieee;
use ieee.std_logic_1164.all;
entity record_conversion is
end entity;
architecture subtypes of record_conversion is
type data_t is record
top : std_ulogic_vector(4 downto 0);
bottom : std_ulogic_vector(2 downto 0);
end record data_t;
signal record_s : data_t;
signal vector_s : std_ulogic_vector(7 downto 0);
subtype t is std_logic_vector (
vector_s'LEFT downto vector_s'LEFT - record_s.top'length + 1
);
subtype b is std_logic_vector (
vector_s'LEFT - record_s.top'length downto 0
);
begin
record_s <= data_t'(vector_s(t'range), vector_s(b'range));
end architecture;
Here the subtypes index range slices of the right hand side expression elements.
You can describe the slices with aliases:
architecture aliases of record_conversion is
type data_t is record
top: std_ulogic_vector(4 downto 0);
bottom: std_ulogic_vector(2 downto 0);
end record data_t;
signal record_s: data_t;
signal vector_s: std_ulogic_vector(7 downto 0);
alias vector_s_top: std_ulogic_vector(record_s.top'range) is
vector_s(7 downto 3);
alias vector_s_bottom: std_ulogic_vector(record_s.bottom'range) is
vector_s (2 downto 0);
begin
record_s <= data_t'(vector_s_top, vector_s_bottom);
end architecture;
Here the two aliases describe fields of vector_s. If you were guaranteed to always assign the record composite object you could actually do away with records and simply use aliases. The closest VHDL comes to unions.
The above examples analyze, elaborate and simulate without error, demonstrating there are no slice boundary issues.
Qualified expressions, subtype declarations and aliases incur no additional simulation overhead while subprogram calls do.
We wrote a school project with entity symbol that outputs 1 or 0 and are supposed to write testbench on our own with assert. We were told that it can be in a loop or not, but it has to be throught assert. I'm quite new to VHDL, so it is a little difficult for me to write the test bench properly. ADDRESS is value from 0 to 15, ROW and COLUMN are values from 0 to 7 and I should check one symbol completely (all rows and columns) and then random values in other addresses as well.
ENTITY symbol IS
END symbol_tb;
ARCHITECTURE behavior OF symbol_tb IS
COMPONENT symbol
PORT(
ADDRESS : IN std_logic_vector(3 downto 0);
COLUMN : IN std_logic_vector(2 downto 0);
ROW : IN std_logic_vector(2 downto 0);
DATA : OUT std_logic
);
END COMPONENT;
signal DATA : std_logic
signal ADDRESS : std_logic_vector(3 downto 0) := "0011";
signal COLUMN : std_logic_vector(2 downto 0) := "011";
signal ROW: std_logic_vector(2 downto 0) := "001";
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: symbol PORT MAP (
ADDRESS => ADDRESS,
COLUMN => COLUMN,
ROW => ROW,
DATA => DATA
);
-- Stimulus process
stim_proc: process
begin
wait for 5 ns;
end process;
END;
My question is, how to put assert in a loop? I would be grateful for any advice regarding testbenches in VHDL.
Suppose I have an alias for a a single bit or number of bits in a std_logic_vector declared such as this:
signal CR : std_logic_vector(7 downto 0);
alias CR_ARM : std_logic is CR(0);
alias CR_PS : std_logic_vector(3 downto 0) is CR(7 downto 4);
How can I access the range or position of the alias such as:
singal tmp : std_logic_vector(7 downto 0); -- output bus vector
tmp(CR_ARM'range) <= CR_ARM; -- does not compile
Range is only defined for array types. Even when VHDL-2017 will add ranges for scalar types, it won't solve your problem, because you want to know for which bit the alias was created.
Aliases are transparent in VHDL. There is no mechanism to reflect about aliases.
You could use this workaround, which doesn't look very nice:
signal CR : std_logic_vector(7 downto 0);
alias CR_ARM : std_logic_vector is CR(0 downto 0);
signal tmp : std_logic_vector(7 downto 0); -- output bus vector
-- now a slice name works
tmp(CR_ARM'range) <= CR_ARM;
Your second example won't work as expected. You should declare the alias with the same range constraints otherwise you will assign other bits when you use CR_PS'range.
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);
This has me bugging for quite some time, but is it possible to describe entities in VHDL similar to how templates work in C++ (or to lesser extend generics?). Simply leaving the actual port types to be only decided during synthesize/compilation?
An example would be a multiplexer, say I have a 4 input multiplexer, now I have several bus sizes I use this multiplexer for, -4,6,7,8-. Currently I wrote a different multiplexer for each different bus size; however the output is simply one of the chosen inputs forwarded, and is thus of the same type as the bus.
This seems overly redundant and error prone (choose correct multiplexer at correct times, keep them all in line, update them as I change the bus size). Is there no way to parameterize this?
non generic version below to show the idea.
entity mux_6bit_4input is
port ( input_0 : in std_logic_vector (5 downto 0);
input_1 : in std_logic_vector (5 downto 0);
input_2 : in std_logic_vector (5 downto 0);
input_3 : in std_logic_vector (5 downto 0);
sel : in std_logic_vector (1 downto 0);
output : out std_logic_vector (5 downto 0)
);
end entity mux_6bit_4input;
Maybe I misunderstood the question, but doesn't the common solution using generics solve your problem?
library ieee;
use ieee.std_logic_1164.all;
entity mux_4x1 is
generic (
DATA_WIDTH: integer := 8
);
port (
input_0: in std_logic_vector(DATA_WIDTH-1 downto 0);
input_1: in std_logic_vector(DATA_WIDTH-1 downto 0);
input_2: in std_logic_vector(DATA_WIDTH-1 downto 0);
input_3: in std_logic_vector(DATA_WIDTH-1 downto 0);
sel: in std_logic_vector (1 downto 0);
output: out std_logic_vector(DATA_WIDTH-1 downto 0)
);
end;
architecture behavior of mux_4x1 is
begin
output <=
input_0 when sel = "00" else
input_1 when sel = "01" else
input_2 when sel = "10" else
input_3;
end;
Another solution, if you want to keep things really generic, is to use the cool generic types in VHDL-2008. My simulator doesn't yet support this feature, so here's an example from the excellent book VHDL 2008: Just the New Stuff:
entity generic_mux2 is
generic (type data_type);
port (
sel: in bit;
a, b: in data_type;
z: out data_type
);
end;
architecture rtl of mux2 is
begin
z <= a when sel = '0' else b;
end;
Another option is to use unconstrained arrays:
entity mux_4input is
port (
input_0 : in std_logic_vector ;
input_1 : in std_logic_vector ;
input_2 : in std_logic_vector ;
input_3 : in std_logic_vector ;
sel : in std_logic_vector (1 downto 0);
output : out std_logic_vector
);
end entity mux_4input;
They will inherit their width (and direction) from the signals they are conencted to in the instantiating entity.
It's probably not the right thing to do in this particular case of a mux, rick's answer is what I'd go for, but unconstrained arrays don't get mentioned much, so I thought I'd offer them! In this case, you'd probably also want some asserts to ensure that everything you've wired up is the same width.