I'm very new in VHDL and having a problem about assigning values I guess.
Let's say that I've a module that get an 16 bit input signal noisein_mono for every positive edge of the clock source. What I want is to construct a 20 Kbit long bit vector from this 16-bit inputs. So I'm gonna perform random number tests on it FIPS_140-2
The code I end up with is shown below:
-- Entity Decleration
entity MonoTestModule is
Port ( clk : in STD_LOGIC;
rst : in STD_LOGIC;
start : in STD_LOGIC;
noisein_mono : in STD_LOGIC_VECTOR (15 downto 0);
running_mono : out STD_LOGIC;
tok_mono : out STD_LOGIC
);
end MonoTestModule;
architecture Behavioral of MonoTestModule is
-- Signal to communication between processes.
signal enable_20k_bit_stream : std_logic;
begin
process (rst, clk, start, noisein_mono)
variable count : integer := 0;
variable twnty_k_bit_stream : bit_vector(19999 to 0);
begin
if(start = '1') then
if (rising_edge(clk)) then
count := count + 1;
twnty_k_bit_stream := twnty_k_bit_stream or to_bitvector(noisein_mono);
twnty_k_bit_stream := twnty_k_bit_stream sll 16;
end if;
if (rst = '1') then
count := 0;
enable_20k_bit_stream <= '0';
end if;
-- if count is reached to 1250, 20kbit is constructed.
if(count = 1250) then
enable_20k_bit_stream <= '1';
else
enable_20k_bit_stream <= '0';
end if;
end if;
end process;
I'm using Xilinx ISE 14.7. The compiler pops up error says Line 52: Unequal length arguments for operator "or".
How can I solve this problem?
My best regards.
In simulation this would be two different run-time errors.
There's actually two bounds mismatch errors, one for the "or" on two array values:
twnty_k_bit_stream := twnty_k_bit_stream or
to_bitvector(noisein_mono);
And one for the assignment to twnty_k_bit_stream where the length doesn't match following an implicit subtype conversion.
And that's because
variable twnty_k_bit_stream : bit_vector(19999 to 0);
that to should be downto. When the direction is wrong you'll end up with a null range (an array with no elements).
See IEEE Std 1076-2008 9.2.2 Logical operators, para 3:
If both operands are one-dimensional arrays, the operands shall be arrays of the same length, the operation is performed on matching elements of the arrays, and the result is an array with the same index range as the left operand. If one operand is a scalar and the other operand is a one-dimensional array, the operation is performed on the scalar operand with each element of the array operand. The result is an array with the same index range as the array operand.
So uneven length arrays don't work.
Also see 10.6.2.1 (Variable assignment), paras 5 and 7:
For the execution of a variable assignment whose target is a variable name, the variable name and the expression are first evaluated. A check is then made that the value of the expression belongs to the subtype of the variable, except in the case of a variable that is of a composite type (in which case the assignment involves a subtype conversion). Finally, each subelement of the variable that is not forced is updated with the corresponding subelement of the expression. A design is erroneous if it depends on the order of evaluation of the target and source expressions of an assignment statement.
...
An error occurs if the aforementioned subtype checks fail.
And that error occurs if there isn't a corresponding element in both the target and right hand side expression of the variable assignment.
5.3.2.2 Index constrains and discrete ranges, para 4:
An array constraint of the first form is compatible with the type if, and only if, the constraint defined by each discrete range is compatible with the corresponding index subtype and the array element constraint, if present, is compatible with the element subtype of the type. If any of the discrete ranges defines a null range, any array thus constrained is a null array, having no elements. An array value satisfies an index constraint if at each index position the array value and the index constraint have the same index range. (Note, however, that assignment and certain other operations on arrays involve an implicit subtype conversion.)
Fix both those things:
begin
process (rst, clk) -- , start, noisein_mono) -- not needed
variable count: integer := 0;
variable twnty_k_bit_stream: bit_vector(19999 downto 0); -- was to
begin
if start = '1' then
if rising_edge(clk) then
count := count + 1;
-- twnty_k_bit_stream := twnty_k_bit_stream or
-- to_bitvector(noisein_mono);
-- twnty_k_bit_stream := twnty_k_bit_stream sll 16;
twnty_k_bit_stream (twnty_k_bit_stream'LEFT downto noisein_mono'LENGTH) :=
twnty_k_bit_stream (twnty_k_bit_stream'LEFT - noisein_mono'LENGTH downto 0);
twnty_k_bit_stream (noisein_mono'RANGE) :=
to_bitvector(noisein_mono);
end if;
noting I also fixed the sensitivity list and we get something that doesn't have a bounds check error. Instead of using an "or" this shifts then writes the lower 16 bits with noisein_mono.
Adding a testbench:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity monoblahblah_tb is
end entity;
architecture foo of monoblahblah_tb is
signal clk: std_logic := '0';
signal rst: std_logic;
signal start: std_logic;
signal noisein_mono: std_logic_vector (15 downto 0);
signal running_mono: std_logic;
signal tok_mono: std_logic;
begin
DUT:
entity work.monotestmodule
port map (
clk => clk,
rst => rst,
start => start,
noisein_mono => noisein_mono,
running_mono => running_mono,
tok_mono => tok_mono
);
CLOCK:
process
begin
wait for 5 ns;
clk <= not clk;
if now > 12680 ns then
wait;
end if;
end process;
STIMULI:
process
begin
wait for 6 ns;
rst <= '0';
start <= '0';
noisein_mono <= (others => '0');
wait for 10 ns;
rst <= '1';
wait for 10 ns;
rst <= '0';
wait for 100 ns;
start <= '1';
for i in 0 to 1249 loop -- 20,000 / 16
noisein_mono <=
std_logic_vector(to_unsigned(i, noisein_mono'length))
xor
x"dead";
wait for 10 ns;
end loop;
wait;
end process;
end architecture;
And we get:
And if I had thought about it I would have XOR'd different values in consecutively, these values are simply unique from 0 to 1249 as binary XOR'd with x"DEAD". (It seemed outré to write a random number generator for a simple testbench, considering the state of twnty_k_bit_stream isn't displayed. The purpose is to show there are no bounds check failures.)
So there were two semantic errors detectable at run time (or synthesis) and an incorrect sensitivity list.
Related
I want to access specific elements of a vector and add their values in one single clock. The cache inputs have been written prior to this calc, so they can be accessed immediately.
type cache_type is array (89 downto 0) of std_logic_vector(14 downto 0);
signal input_cache : cache_type := (others => (others => '0'));
signal cluster_square_sum : integer := 0;
calc: process (clk)
begin
if rising_edge(clk) and cache_ready then
cluster_square_sum <= conv_integer(input_cache(5)) +
conv_integer(input_cache(6)) + conv_integer(input_cache(7)) +
conv_integer(input_cache(12)) + conv_integer(input_cache(13)) +
conv_integer(input_cache(14)) + conv_integer(input_cache(15)) + ...
end if;
end process;
How can I implement this behavior without writing all desired elements explicitly in the addition? I've thought about a variable iterator in the process, but it would not work because of the single clock computation.
Actually, I don't need a process in the first place, I could write my summation directly in the architecture with a "when statement"
cluster_square_sum <= conv_integer(input_cache(5)) +
conv_integer(input_cache(6)) + conv_integer(input_cache(7)) +
conv_integer(input_cache(12)) + conv_integer(input_cache(13)) +
conv_integer(input_cache(14)) + conv_integer(input_cache(15)) + ...
when cache_ready <= '1';
Unfortunately, I don't know a way in implementing my behavior in one of the ways.
Several things about your question are unclear, but one thing about the question is clear : better design would let you use the type system instead of fighting it every line.
One thing that's unclear : what are you storing in the cache? Is it exclusively reserved for numbers, or is this a CPU cache which can store numbers, text, instructions etc?
If it's exclusively for numeric data then
type cache_type is array (89 downto 0) of natural range 0 to 2**14 - 1;
will simplify your sum a lot. Or the equivalent signed integer range, whichever is appropriate for your application. This also makes the design intent clear. Or you can use signed or unsigned from numeric_std.
cluster_square_sum <= input_cache(5) + input_cache(6) + input_cache(7) + ...
when cache_ready <= '1';
It's also unclear what subset of cache you are summing over, especially since this isn't an [MCVE] and appears to cover a non-contiguous range. So I'll just have to guess it's a fixed continuous subset; you could employ a loop.
calc: process (clk)
variable running_total : natural;
begin
if rising_edge(clk) then
if cache_ready then
running_total := 0;
for i in lower_bound to upper_bound loop
running_total := running_total + input_cache(6)(i);
end loop;
cluster_square_sum <= running_total;
end if;
end if;
end process;
The variable allows instant assignment (variable assignment semantics) rather than postponed assignment (signal assignment semantics) so you get a running total.
If the bounds aren't constant (or generics), or the range isn't contiguous, this strategy needs some modification.
Another unclear thing is your speed (latency and throughput) and logic size goals. This will perform every addition in a single cycle, but that cycle is likely to be rather slow. If you potentially need an output every clock cycle, with a realistic clock rate, you'll have to pipeline it.
Or if you have plenty of cycles after cache_ready before you need an output, embed the loop and computation in a state machine triggered by cache_ready. This can perform one addition (and loop iteration) per clock cycle, allowing input_cache to be a Block Ram rather than individually accessible registers, for a very small and fast-clocked design. (And in that case, with only one addition per clock, you can safely use either a variable or a signal for running_total.
In all cases, I would suggest to use a function.
There doesn't seem to be any logic in the elements you want to add, so I made the functions accept a set of element indices.
"Minimal" example:
library IEEE;
use IEEE.std_logic_1164.all;
entity e is
port(clk: in std_logic);
end entity;
architecture a of e is
use IEEE.numeric_std.all;
type cache_type is array(0 to 89) of std_logic_vector(14 downto 0);
signal input_cache : cache_type := (
5 => "000010101010101",
6 => "000001010101010",
7 => "000000101010101",
12 => "000000010101010",
13 => "000000001010101",
14 => "000000000101010",
15 => "000000000010101",
others => (others => '0'));
type integer_array is array(natural range <>) of integer;
constant elements_to_add : integer_array := (5, 6, 7, 12, 13, 14, 15);
signal cluster_square_sum : integer := 0;
function add_elements(input_array : cache_type; element_idxs: integer_array) return integer is
variable output : integer := 0;
begin
for idx in element_idxs'low to element_idxs'high loop
output := output + to_integer(unsigned(input_array(element_idxs(idx))));
end loop;
return output;
end;
begin
calc: process(clk)
begin
if rising_edge(clk) then
cluster_square_sum <= add_elements(input_cache, elements_to_add);
end if;
end process;
end architecture;
Note that you could also do the process-less/direct assignment with this function.
Plus testbench:
entity e_tb is end entity;
library IEEE;
architecture a of e_tb is
use IEEE.std_logic_1164.all;
signal clk : std_logic := '0';
begin
UUT : entity work.e port map (clk => clk);
test: process begin
wait for 1 ns;
clk <= '1';
wait for 1 ns;
clk <= '0';
wait;
end process;
end architecture;
Please note that it if you want to implement this in an FPGA, you will require quite some resources and lose performance. It would then be better to pipeline your design: use multiple clock cycles to add the elements.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity test_adder_vhdl is
end test_adder_vhdl;
architecture Behavioral of test_adder_vhdl is
constant clock_period : time := 1000 ns ;
component adder is
PORT (A: in STD_LOGIC;
B: in STD_LOGIC;
SUM: out STD_LOGIC;
CARRY: out STD_LOGIC);
end component adder;
SIGNAL A: STD_LOGIC : ='0';
SIGNAL B: STD_LOGIC : ='0';
SIGNAL SUM: STD_LOGIC : ='0';
SIGNAL CARRY: STD_LOGIC : ='0';
begin
uut: adder port map(
A=> A;
B=> B;
SUM => SUM;
CARRY => CARRY;
);
clk gena: process
begin
wait for 100 ns;
A <= not A;
end process;
clk genb: process
begin
wait for 50 ns;
B <= not B;
end process;
end Behavioral;
The error in the above code is
[HDL 9-806] Syntax error near ":". ["F:/practiceWorkspace/practice1/practice1.srcs/sim_1/new/test_adder_vhdl.vhd":38]
You are not showing line number correspondence with your design. The error appears to correspond with the signal declaration for A. There are more syntax errors.
Statements are delimited by a semicolon. Interface declarations are separated by semicolons. Other object declarations are delimited by semicolons. Multiple elements (in the association list here) are separated by commas.
There are four signal declarations (A, B, SUM, CARRY) with extraneous spaces between the ':' and '=' in the compound delimiter ":=" used to providing a default value of '0'.
These should be:
SIGNAL A: STD_LOGIC := '0';
SIGNAL B: STD_LOGIC := '0';
SIGNAL SUM: STD_LOGIC := '0';
SIGNAL CARRY: STD_LOGIC := '0';
:= is a used to signify variable assignment, values for constants and default expressions (values) for objects.
In the port map ',' should be used as a separator in the association list instead of ';'.
uut: adder port map (
A=> A,
B=> B,
SUM => SUM,
CARRY => CARRY -- NO TRAILING SEPARATOR
);
The last association does not require a following comma (a delimiter used as a separator).
There's a space instead of an underscore in the labels clk_gena and clk_genb.
clk_gena: process
begin
wait for 100 ns;
A <= not A;
end process;
clk_genb: process
begin
wait for 50 ns;
B <= not B;
end process;
A label is a single identifier consisting of a letter followed by one or more letters or numbers separated by zero or one underscore characters. The processes are labelled (named) clk_gena and clk_genb.
After fixing these your code analyzes (compiles). Without the entity and architecture pair for component adder your code can't be elaborated (linked) or simulated.
Note that the two processes suspend for 50 ns, and a process without an implicit last wait statement waiting on elements of a sensitivity list will merrily start executing the first sequential statement of the process after executing the last.
The expectation would be that you'd either add a trailing wait statement or control simulation by an implementation dependent method (e.g. run for some simulation time interval).
Your constant clock_period is not used (as yet) in your testbench.
I've got this error in the expression "individuos(x):=cout" of the following code. What I'm trying to do is assign to each array of individuos a different random "cout" input sequentially. If I change the expression to "individuos <= cout", it'll asign the same "cout" to all "individuos", the same will happen if i trie to build a sequential statement with the assert function. How do I fix this?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_TEXTIO.ALL;
use ieee.numeric_std.all;
--package genetica_type is
--type genetica is array(0 to 49) of unsigned(7 downto 0);
--type fitness is array(0 to 49) of unsigned (2 downto 0);
--end package genetica_type;
use work.genetica_type.all;
entity conexao is
Port (
clk : in bit;
cout: in unsigned (7 downto 0);
individuos: out genetica
);
end entity;
architecture Behavioral of conexao is
--type genetica is array (0 to 49) of std_logic_vector (7 downto 0);
--signal s_individuos : genetica;
--signal i: genetica;
begin
process (clk)
begin
If (clk 'event and clk = '1') then
for x in 0 to 49 loop
individuos(x) := cout;
end loop;
end if ;
end process;
end Behavioral;
I've got this error in the expression "individuos(x):=cout" of the following code.
That is a syntax error. Use <= exactly as the compiler says.
What I'm trying to do is assign to each array of individuos a different random "cout" input sequentially. If I change the expression to "individuos <= cout", it'll asign the same "cout" to all "individuos"
That is exactly what you ask it to do :
If (clk 'event and clk = '1') then
for x in 0 to 49 loop
individuos(x) <= cout;
end loop;
end if ;
On every rising clock edge, loop 50x performing 50 assignments, each of the same data, to all 50 addresses.
What I think you want to do, is, on every clock, perform ONE assignment, and increment the address to point to the next location.
signal x : natural range 0 to individuos'high;
...
if rising_edge(clk) then
individuos(x) <= cout;
x <= x + 1 mod individuos'length;
end if;
This code has several other differences from yours:
It uses the simpler rising_edge(clk) function
It will still work when you change the size of the input array.
It still has a bug : if you change the array lower bound to something other than 0, it will fail... for example:
type genetica is array(3 to 49) of ...
Easy to catch this with an assert:
Assert individuos'low = 0 report "Array Individuos bound error" severity failure;
It also runs continuously. If you want to start and stop it, or reset the address counter, or stop when it reaches 50, that takes additional logic.
I'm new to this web site and I had a question I was hoping to get help with. I am writing VHDL code for a LFSR which consists of a transmitter and receiver.
The transmitter is supposed to generate a random binary number (preamble,which it does) and this binary number then has to be concatenated, but I first need to put it in a STD_LOGIC_VECTOR and that's what im having trouble with.
Here is my code for testbench in which this assignment must take place,thank for any help in advance:
library ieee;
use ieee.std_logic_1164.all;
entity testbench is --definig the entity
end testbench;
architecture tb1 of testbench is
component transmitter is port(
clk :in std_logic;
reset:in std_logic;
enable:in std_logic;
output :out std_logic);--output is the random generated binary which i need to pass to a vector
end component;
--type bit_vector is array (natural range <>) of bit; --this is so that we can define the whole thing otherwise bit can
--only be 1 or 0 this allows to define them as vectors
constant SOF: std_logic_vector(0 to 15) := "0101010100001010";
constant trailer: std_logic_vector(0 to 7) := "10111110";
constant payload: std_logic_vector(0 to 7) := "01110010";
constant L: std_logic_vector(0 to 7) := "00101110";
signal preamble: std_logic_vector(0 to 95);
signal clk , reset, enable : std_logic;--output signal
signal data_packet: std_logic_vector(0 to 135);
signal output: std_logic;
begin
--problem is here
--my attempt
get_preamble: process
variable i: std_logic;--this will be used to walk through the preamble vector and put the out put values in
--variable j: std_logic;
begin
n1: for i in 0 to 95 loop
if output = '1' then
preamble(i) <= '1';
end if;
end loop;
if output = '0' then
for i in 0 to 95 loop
preamble(i) <= '0';
end loop;
end if;
wait;
end process;--end of get_preamble
concatenation :process
begin
data_packet <= preamble & SOF & L & payload & trailer;
wait;
end process;
END tb1;
Based on your question, you're saying you're trying to concatenate the value output with the rest of the preamble vector. You should change this:
n1: for i in 0 to 95 loop
if output = '1' then
preamble(i) <= '1';
end if;
end loop;
if output = '0' then
for i in 0 to 95 loop
preamble(i) <= '0';
end loop;
end if;
to this:
n1: for i in 0 to 95 loop
wait until clk'EVENT and clk = '1';
preamble(i) <= output
end loop;
Since you have a clock, try to get each value when you have a positive edge in your clock. You do not need to check the value each time, you can just add it to the vector at once.
EDIT: You should either wait for the same things in the other process, or wait for the preamble to finish loading its 96 values, depending on what you want to accomplish.
Are you perhaps looking for something like this?
It will take a stream of 96 bits from "output" and put them in "preamble". Then concatenate preamble to the packet.
for i in 0 to 95 loop
wait until rising_edge(clk);
preamble(i) <= output;
end loop;
data_packet <= preamble & SOF & L & payload & trailer;
I have a system that has a 3 input D_in which is read at every positive clk edge.
If say I want to see if the current input, D_in is greater then the previous D_in by at least 2, then a count will increment. How do I write this in VHDL?
if clk'event and clk = '1' then --read at positive edge
if D_in > (D_in + 010) then <---I am sure this is wrong. How to write the proper code?
Entity ABC is
Port(D_in: in std_logic_vector(2 downto 0);
Count: out std_logic_vector(2 downto 0));
Architecture ABC_1 of ABC is
signal D_last: std_logic_vector(2 downto 0);
Begin
Process(D_in)
D_last <= D_in;
if clk'event and clk = '1' then
if D_last > (D_in + 2) then
count <= count + 1;
end if;
end process;
end ABC_1;
The "good" way to write this process is as follow :
process (clk)
begin
if (rising_edge(clk)) then
-- store the value for the next time the process will be activated
-- Note that D_last value will be changed after the whole process is completed
D_last <= D_in;
-- compare the actual D_in value with the previous one stored in D_last.
-- D_last value is its value at the very beginning of the process activation
if (D_in > D_last + 2) then
-- increment the counter
count <= count + 1;
end if;
end if;
end process;
Note that D_in, D_last and count has to be declared as unsigned and not as std_logic_vector.
I suggest you to read this post which explains how a process actually works : when are signals updated and which signal value is used into the process.
Cheers
[edit] This answer should be fine for your question. But the code you show has other errors :
The signal clk has to be an input for your entity.
The signal count can't be read in your architecture because it's defined as output in the entity. Then the line "count <= count + 1" can't be resolved. You have to use an internal signal and then assign its value to "count" outside of a process :
count <= count_in;
There are several other errors in your design specification as well. This answer attempts to answer all concerns in one place.
VHDL is simulated by executing processes in simulation cycles. Every
concurrent statement can be expresses as either an equivalent process
statement or combination of process statements and block statements.
Signal assignment is to a projected output waveform queue for a specified
time. When no time is specified it's the current time, and the value will be updated
prior to executing processes in the next simulation cycle, a delta cycle, simulation
time is advanced when there are no remaining events scheduled for the
current simulation time.
To avoid confusion over when signal assignments occur, view them as
separate processes (whether you express them that way or not).
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity abc is
port (
clk: in std_logic; -- Note 1
d_in: in std_logic_vector(2 downto 0);
count: out std_logic_vector(2 downto 0)
);
end entity; -- Note 2
architecture foo of abc is
signal d_last: std_logic_vector(2 downto 0);
begin
DLAST: -- Note 3
process (clk)
begin
if rising_edge(clk) then -- Note 4
d_last <= d_in;
end if;
end process;
INC_COUNT:
process (clk)
variable cnt: unsigned(2 downto 0) := "000"; -- Note 5
begin
if rising_edge(clk) and
unsigned(d_last) > unsigned(d_in) + 2 then -- Mote 6,7
cnt := cnt + 1;
end if;
count <= std_logic_vector(cnt);
end process;
end architecture;
Notes
Missing clk from port interface
Missing end statement for entity ABC.
Conceptually view D_last
register separately from Count counter sensitive to clk. (Can be
merged as one process)
rising_edge function expresses clk'event and clk = '1' ('event
and "=" are both functions)
The counter must represent a binary value for "+" to produce a
binary result
"+" is higher priority than ">", which is higher priority than "and"
(you don't need parentheses)
Package numeric_std provide relational and adding operators for
type sign and type unsigned, requiring type conversion for D_last
and D_in.
Alternatively use Synopsys package std_logic_unsigned which
depends on Synopsys package std_logic_arith and treats
std_logic_vector as unsigned. This avoids type conversion, and
allows array types to be declared as type std_logic_vector.
The variable cnt can be done away with if port count were to be declared mode buffer and provided a default value:
count: buffer std_logic_vector(2 downto 0) :="000" -- Note 5
and
INC_COUNT:
process (clk)
begin
if rising_edge(clk) and
unsigned(d_last) > unsigned(d_in) + 2 then -- Note 6,7
count <= std_logic_vector(unsigned(count) + 1);
end if;
end process;
You can't use Count as mode out to algorithmically modify it's own value. The ability to access the value of a mode out port is intended for verification and is a IEEE Std 1076-2008 feature.
And about now you can see the value of Synopsys's std_logic_unsigned package, at least as far avoiding type conversions.
Also, i got another question. If d_in is 0 for 3 consecutive clk cycles, i want to reset count to 0. How do i write the code to represent for 3 clk cycles?
Add another pipeline signal for D_in:
signal d_last: std_logic_vector(2 downto 0) := "000";
signal d_last1: std_logic_vector(2 downto 0) := "000";
Note these also have default values, which FPGA synthesis will generally honor, it's represented by the state of the flip flop in the bistream image used for programming the FPGA.
And modify how the counter is operated:
INC_COUNT:
process (clk)
begin
if rising_edge(clk) then
if d_in = "000" and d_last = "000" and d_last1 = "000" then
count <= "000";
elsif unsigned(d_last) > unsigned(d_in) + 2 then -- Note 6,7
count <= std_logic_vector(unsigned(count) + 1);
end if;
end if;
end process;
The three incarnations of the example all analyze, they haven't been simulation and should be synthesis eligible.