I am designing a simple LFSR with a variable polynomial for a randomizer. The lfsr length is being defined as a generic. I need to initialize the starting value constant as something other than zeros/ones. I've found the answer to this before, but I can't seem to find the answer again. Here is what I'm trying to do:
entity GaloisLfsr is
generic
(
g_LFSR_LENGTH : integer := 5
);
...
end entity GaloisLfsr;
architecture zGaloisLfsr of GaloisLfsr is
constant c_INITIAL : std_logic_vector((g_LFSR_LENGTH - 1) downto 0) := ((others => '0'), '1');
What is the proper syntax for defining a constant with varying size to something that a pure '(others => '0')' can't capture?
Assuming one would like to initialize the 5-bit constant c_INITIAL to "00001", then the declaration of the constant would be:
constant c_INITIAL : std_logic_vector((g_LFSR_LENGTH - 1) downto 1) := ((others => '0'), 0 => '1');
You may convert natural/integer to vector
use IEEE.NUMERIC_STD.ALL;
...
constant c_INITIAL : std_logic_vector((g_LFSR_LENGTH - 1) downto 0) := std_logic_vector(to_unsigned(g_polynomial , g_LFSR_LENGTH));
Related
I keep forgetting and its difficult to search for the answer in a textbook or the Internet.
Well, <= is assignment.
signal <= A or B;
=> is syntax used for case statements like so:
(Stolen from http://www.cs.umbc.edu/portal/help/VHDL/sequential.html)
case my_val is
when 1 => -- This is kind of like how the : operator is used for switch in many languages
a:=b;
when 3 =>
c:=d;
do_it;
when others =>
null; -- do nothing
end case;
end case;
=> can also be used in array assignments
myVector <= (1=>'1', OTHERS=>'0'); -- assigns ('0','1','0','0') to "myVector"
Source: http://www.eda.org/comp.lang.vhdl/html3/gloss_example.html
A means to memorize when to use => and when to use <= is to think as follow.
<= as an assignment for signal as target (for variable it is :=).
Examples:
y <= a + b + c; --y is a signal
v := a + b +c; --v is a variable
=> as mapping.
Example for component explicit mapping (recommended style IMHO):
my_instance : my_component
port map(
port1 => my_signal1
);
Example for function explicit mapping (useful when parameters are not trivial):
my_signal <= my_function(parameter1 => something1, parameter2 => something2);
Example for array explicit mapping
type array_type is array(0 to 1) of std_logic_vector(7 downto 0);
constant my_array : array_type := (0 => x"AB", 1 => x"CD");
Example for record explicit mapping
type record_type is record
a : natural;
b : std_logic_vector(2 downto 0);
end record;
constant my_record: record_type := (a => 0, b => "101");
The advantage is this style allows you to do the mapping in the order of your choice (not necessarily the order in the definition of the component/function...). Moreover in the particular case of array with only one item, it is required.
Finally, with the =>, the keyword others allows to map all the remaining stuff that hasn't already mapped.
Example to assign array:
type array_type is array(0 to 5) of std_logic_vector(7 downto 0);
constant my_array : array_type := (0 => x"AB", 1 => x"CD", others => (others => '0'));
<= represents the assignment operator while => is used in the case statement, for example:
case sel is
when "01" => line <= "1";
when others => line <= "0";
end case
sets line to "1" in case sel is "01" and to "0" otherwise.
=> is also used in structural code in port maps.
The operator <= is known as a
signal assignment operator to highlight its true purpose. The signal assignment operator specifies a relationship between signals. In other words, the signal on the left side of the signal assignment operator is dependent upon the signals on the right side of the operator.
(Source: Digital_Mclogic_Design by Bryan Mealy, Section: The Signal Assignment Operator: “<=”, page 339)
I couldn't find anything specific on the => operator.
i'd like to assign a std_logic_vector without giving the bounds. Like this:
constant xy: std_logic_vector := "100111";
when i want to access single bits like:
xy(0), xy(1)...xy(5)
i get
1, 0, 0, 1, 1, 1
This is the same, as when i assign the vector like
std_logic_vector(0 to 5).
Is this behaviour standardized, that assigning a unconstrained vector is interpreted like std_logic_vector(0 to x) and not like std_logic_vector(x downto 0), or is this depending on the implementation?
I'm using ghdl right now, but want to use vivado for synthesis.
In short, yes, standardised. When you declare an object of an unconstrained array type you need to supply a constraint to specify the index bounds (so that the compiler can allocate the required memory, and so on). There are several different ways to do this, most of which require you to explicitly specify the array limits and direction.
However, there's an exception for constants (only): the constraint can be inferred from the expression used to initialise the constant. If you initialise from a string literal or an aggregate with positional association (A and B below) then the index value of the first/left element is taken from the leftmost element of the type in the range declaration, and the direction is taken from the direction of that type. For std_logic_vector, the declarations are:
SUBTYPE NATURAL is integer range 0 to integer'high;
...
TYPE std_logic_vector IS ARRAY ( NATURAL RANGE <>) OF std_logic;
NATURAL is ascending, with leftmost index 0, so your xy is the same. OTOH, if the initialiser is an aggregate with named association (C below) then the index range of the constant is simply taken from the aggregate. The code below should show A and B as 111001, and C as 100111.
library IEEE;
use IEEE.std_logic_1164.all;
entity TOP is
end entity TOP;
architecture A of TOP is
begin
process
constant A : std_logic_vector := "100111";
constant B : std_logic_vector := ('1', '0', '0', '1', '1', '1');
constant C : std_logic_vector :=
(5 => '1', 4 => '0', 3 => '0', 2 => '1', 1 => '1', 0 => '1');
begin
report "A is " &
std_logic'image(A(5)) & std_logic'image(A(4)) & std_logic'image(A(3)) &
std_logic'image(A(2)) & std_logic'image(A(1)) & std_logic'image(A(0));
report "B is " &
std_logic'image(B(5)) & std_logic'image(B(4)) & std_logic'image(B(3)) &
std_logic'image(B(2)) & std_logic'image(B(1)) & std_logic'image(B(0));
report "C is " &
std_logic'image(C(5)) & std_logic'image(C(4)) & std_logic'image(C(3)) &
std_logic'image(C(2)) & std_logic'image(C(1)) & std_logic'image(C(0));
wait;
end process;
end architecture A;
EDIT
As pointed out below, the report statements don't show the 'natural' order of these vectors, which was deliberate. You'll notice that this means that the literal value assigned toA is the reverse of the value shown by the report. If you don't like it, swap the indexing in the reports, or use to_string instead (2008-only).
I'm trying to implement an encryption algorithm in VHDL, and I have created a Feedback Shift Register component with generic parameters to improve reusability. It's my first time using generics and arrays, so please bear with me.
This component takes the feedback bits as an input, and it connects some of its bits (taps) to an output port, but this connections can be changed using a generic parameter. Code for the FSR component:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.fsr_taps_type.all;
entity FSR is
generic (
r_WIDTH : integer; -- Register width
r_STEP : integer; -- Update step
r_FWIDTH : integer; -- Feedback output width
r_HWIDTH : integer; -- h-function output width
r_TAPS : TAPS; -- Change the size according to the number of taps
r_STATE : TAPS
);
port (
clk : in std_logic;
rst : in std_logic;
fb_in : in std_logic_vector ((r_STEP-1) downto 0);
init : in std_logic;
ini_data : in std_logic_vector ((r_WIDTH-1) downto 0);
out_data : out std_logic_vector ((r_STEP-1) downto 0);
fb_out : out std_logic_vector ((r_FWIDTH-1) downto 0);
h_out : out std_logic_vector ((r_HWIDTH-1) downto 0)
);
end entity;
architecture behavioural of FSR is
signal shifted,shifted_next : std_logic_vector((r_WIDTH-1) downto 0);
begin
process(clk,rst)
begin
if rst = '1' then
shifted <= (others => '0');
elsif clk'event and clk = '1' then
shifted <= shifted_next;
end if;
end process;
process (fb_in,init,ini_data,shifted)
begin
if init = '1' then
shifted_next <= ini_data;
else
shifted_next <= shifted((r_WIDTH-r_STEP-1) downto 0) & fb_in;
end if;
end process;
out_data <= shifted ((r_WIDTH-1) downto (r_WIDTH-r_STEP));
-- The bits defined in the r_TAPS and r_STATE arrays are connected to the outputs in the same order as they are written (left to right)
-- Example: r_TAPS := (10,6) will create fb_out (1 downto 0) = bit10 & bit 6, in that order
-- Connect taps in the order of r_TAPS
gen_feedback: for I in (r_FWIDTH-1) downto 0 generate
fb_out(I) <= shifted(r_STATE(r_FWIDTH-I-1));
end generate gen_feedback;
-- Connect output bits for h function
gen_h: for I in (r_HWIDTH-1) downto 0 generate
h_out(I) <= shifted(r_STATE(r_HWIDTH-I-1));
end generate gen_h;
end architecture;
My problem comes when instantiating this component twice in the same file, using different generic values. This is the generic map of both instances:
LFSR : FSR
generic map (
r_WIDTH => 128,
r_STEP => STEP,
r_FWIDTH => 6,
r_HWIDTH => 7,
r_TAPS (0 to 5) => (128,121,90,58,47,32),
r_STATE (0 to 6) => (34,49,68,86,108,115,120)
)
NFSR : FSR
generic map (
r_WIDTH => 128,
r_STEP => STEP,
r_FWIDTH => 29,
r_HWIDTH => 2,
r_TAPS (0 to 28) => (40,36,35,33,106,104,103,58,50,46,117,115,111,110,88,80,101,69,67,63,125,61,60,44,128,102,72,37,32),
r_STATE => (33,116)
)
When I only create the first instance, the elaboration works as expected and Vivado gives no error whatsoever. However, when I add the second instance, I get an out of range error:
ERROR: [Synth 8-97] array index 0 out of range (FSR.vhdl:54)
Line 54 is the line inside the first for generate loop:
fb_out(I) <= shifted(r_STATE(r_FWIDTH-I-1));
Only the second instance gives an error. I have tried copying the parameters from the first instance into the second, and I still get the same error.
What am I doing wrong?
EDIT: I added the whole code for the FSR component.
EDIT 2: I changed the type declaration for TAPS, so that the array is constrained:
type TAPS is array (0 to 31) of integer;
This seems to be working, I just have to add an others statement to fill the unused array numbers, so this:
r_TAPS (0 to 5) => (128,121,90,58,47,32)
Becomes this:
r_TAPS (0 to 5) => (128,121,90,58,47,32,others =>0)
As I said before, I'm new to arrays in VHDL, so I would like to know if there is a way to do this for arbitrarily long arrays using an unconstrained array type.
Let var stand for a signed vector (library IEEE.NUMERIC_STD.ALL) of size m.
Let foo be another variable of type std_logic_vector(n-1 downto 0), where n is smaller than m.
I want to concatenate a '0' left of foo, then pad it with zeroes in its right until it size is m and then store the result in var.
I tried
rdsor <= signed('0' & divisor & others=>'0');
But Xilinx complains with the following message on synthesis:
Syntax error near "others".
How do I do what I want?
Assuming rdsor is equivalent to your theoretical var and divisor equivalent to foo you could use two assignments in a process statement:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity jsevillamol is
end entity;
architecture fum of jsevillamol is
constant M: natural := 42;
constant N: natural := 23;
signal rdsor: signed (M - 1 downto 0);
signal divisor: std_logic_vector (N - 1 downto 0);
begin
-- rdsor <= signed('0' & divisor & others=>'0');
process (divisor)
begin
rdsor <= (others => '0');
rdsor (rdsor'LEFT downto rdsor'LEFT - divisor'LENGTH)
<= signed('0' & divisor);
end process;
end architecture;
This works because each element of rdsor is a separate signal and there is only one value for any particular time in a projected output waveform. By not providing an after time_expression in the waveform element of the second assignment the elements of rdsor slice will be assigned the second assignments expression values. (The elements of the first assignment are supplanted by the second). This method of overwriting the projected output waveform is commonly used in providing default values prior to incomplete condition coverage with if statements.
This example analyzes, elaborates and simulates, while doing nothing interesting it demonstrates index ranges are constructed properly.
Notice it avoids the issue of concatenation versus aggregation brought up by Matthew Taylor's answer.
For a single signal assignment in a method not sensitive to tool VHDL revision:
architecture fie of jsevillamol is
constant M: natural := 42;
constant N: natural := 23;
signal rdsor: signed (M - 1 downto 0);
signal divisor: std_logic_vector (N - 1 downto 0);
subtype other is signed (rdsor'LEFT - divisor'LENGTH - 1 downto 0);
begin
-- rdsor <= signed('0' & divisor & others=>'0');
rdsor <= '0' & signed(divisor) & other'(others => '0');
end architecture;
This uses concatenation and subsumes the others into an aggregate. There's a subtype declaration for the trailing '0's portion to allow the aggregate expression to be the target of a qualified expression.
This architecture also analyzes, elaborates and simulates proving index arithmetic is correct.
You would need to use others as part of an aggregate not part of a concatenation. Here's a solution using an aggregate and attributes (which relies on you using VHDL 2008):
rdsor <= (rdsor'LEFT => '0', (rdsor'LEFT-1) downto (rdsor'LEFT-divisor'LENGTH) => signed(divisor), others => '0');
https://www.edaplayground.com/x/5Yuw
Given a bit number, I am trying to set that bit in a std_logic_vector. This is for toggling various clock outputs one at a time.
First of all, I've completely given up on sll, or SHIFT_LEFT which seems to be the obvious way to do it, but which totally doesn't work at all.
variable v_cmd_clk_1: std_logic_vector(11 downto 0);
...
--- set bit number "s_proc_chan", plus 4, in v_cmd_clk_1
v_cmd_clk_1 := "0000" & "0000" & "0000";
v_cmd_clk_1( to_integer ( unsigned(s_proc_chan(2 downto 0))) + 4 ) := '1';
...
-- And then later on in the process assign it to an actual signal
cmd_clk <= v_cmd_clk_0;
Is there a better or cleaner syntax for doing this?
Thanks.
Three suggestions for you. First one uses aggregates:
v_cmd_clk_1 <= (to_integer(unsigned(s_proc_chan(2 downto 0)))+4) => '1', others => '0');
Second one uses integer to unsigned conversion:
v_cmd_clk_1 <= std_logic_vector(to_unsigned(2**(to_integer(unsigned(s_proc_chan(2 downto 0)))+4)); -- No guarantee on parentheses matching
Third one, using shift_left:
v_cmd_clk_1 <= std_logic_vector(shift_left(resize(unsigned'("1"), v_cmd_clk_1'length), to_integer(unsigned(s_proc_chan(2 downto 0)))+4));
The principle of setting a single bit given by index, as you already done, is fine, and it shows the intention of the code, which is setting a bit given by an index.
It would be possible to eliminate the + 4 offset through use of other std_logic_vector ranges, but a decent synthesis tool eliminates the offset, so an add operation is not implemented.
Anyhow, as answer to the comment, the + 4 can be eliminated if a std_logic_vector is addressed directly into 0 to 7, instead of addressing 4 to 11, and the last 4 '0's can just be postpended, like:
variable v_cmd_clk_1 : std_logic_vector(11 downto 0);
variable v_cmd_clk_upper: std_logic_vector( 7 downto 0);
...
v_cmd_clk_upper := (others => '0');
v_cmd_clk_upper(to_integer(unsigned(s_proc_chan(2 downto 0)))) := '1';
v_cmd_clk_1 := v_cmd_clk_upper & "0000";
The aggregate suggested by Jonathan Drolet looks nice, but for example Altera Quartus II won't allow this for synthesis, since it requires constant choice values in aggregates. Using shift or 2** will synthesize.
Note that initial clearing is more general with:
v_cmd_clk_1 := (others => '0');