How do I print matrix_a(1,1) on the console? The report command I commented does not work.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity ent is
end ent;
architecture Behavioral of ent is
type my_matrix is array(integer range 0 to 3, integer range 0 to 3) of integer;
signal matrix_a : my_matrix;
begin
matrix_a(1,1) <= 4;
--report "signal signal_d is " & integer'image((matrix_a(1,1)));
end Behavioral;
When do you expect that report to run?
You have placed it in the concurrent statement region of your architecture : everything there is effectively a process, scheduled according to specific rules; for example, the concurrent assignment matrix_a(1,1) <= 4; will run once at startup, and whenever any of its values change (i.e. never again as they are all literal constants).
But there is nothing to make the "report" run.
Now if you embed it explicitly in a process, sensitive to changes in matrix_a, then it will run at start and whenever matrix_a changes. So try this in place of the commented line:
process (matrix_a) is -- this list controls the process running
begin
report "signal signal_d is " & integer'image(matrix_a(1,1));
end process;
Related
I would like to add if MyVariable is equal to 1 if will report the device is on
architecture sim of T06_SignalTb is
signal MySignal : integer :=0;
begin
process is
variable MyVariable: integer :=0;
begin
report "***Process begin***";
MyVariable := MyVariable + 1;
MySignal <= MySignal + 1;
report "MyVariable=" & integer 'image(MyVariable) & ", MySignal=" & integer 'image(MySignal);
MyVariable := MyVariable + 1;
MySignal <= MySignal + 1;
report "MyVariable=" & integer 'image(MyVariable) & ", MySignal=" & integer 'image(MySignal);
Wait for 10 ns;
end process;
here is the process that i would like to add
process is
begin
MyVariable = 1;
report " the device is on";
end process;
You add another process by adding the code for your second process somewhere between begin and end architecture;. They will execute concurrently. However...
Variables in VHDL are only in scope within a single process. Notice that you declared MyVariable within (the so-called declarative region of) a single process.
This is for a very good reason. If a variable were to be in scope inside some other process, your code could be non-deterministic. (It is possible to do this in Verilog and consequently it is possible to write non-deterministic code in Verilog.)
So, you will not be able to use the variable MyVariable in your second process if you have declared it in the first process. So, what do do?
i) use a signal instead. Signals are VHDL constructs whose purpose is to allow separate processes to communicate.
ii) Or write the code in one process instead of two.
iii) Or use a special kind of VHDL variable called a shared variable, which you would declare in the same place as a signal. However, shared variables are tricky things. They have to be of a special type called a protected type and if you use them, you code can be non-deterministic (just like Verilog). I would be very surprised if this were the right solution for you.
BTW: this code
MySignal <= MySignal + 1;
report "MyVariable=" & integer 'image(MyVariable) & ", MySignal=" & integer 'image(MySignal);
suggests that you have forgotten that signals are not updated (ie don't get their new values) until all the processes suspend (ie finish executing).
Use variables to store information within a process; use signals to send information to another process.
I am trying to know if the amount of "1" in a std_logic_vector is an odd or even number. For that I am trying to use an "if" statement along with a counter, but I don't get the expected result.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
entity prueba2 is
port (
entrada: in std_logic_vector(0 to 10)
);
end prueba2;
architecture Behavioral of prueba2 is
signal bit1: std_logic_vector(0 to 3):= (others => '0');
begin
prueba: process(entrada)
--variable suma: unsigned(0 to 2):= (others => '0');
begin
for i in 0 to 10 loop
if (entrada(i)= '1') then
bit1 <= bit1+1;
end if;
end loop;
end process;
end Behavioral;
I am not getting errors in the syntax, but for example, by entering a vector "1111111111" I receive as output in the simulation, using ISE design Suite, the value "0001" instead of "1010". I appreciate your corrections and code suggestions.
See IEEE Std 1076-2008 10.5.2.2 Executing a simple assignment statement, 14.7.3.4 Simulation cycle and 14.7.3.4 Signal update.
Signals aren't updated immediately. The current simulation cycle isn't complete until every process sensitive to an event has executed and potentially scheduled signal updates and subsequently suspended. Simulation time is advanced to the time the next signal update is scheduled. Signals are updated at the beginning of a simulation cycle before any suspended processes resume due to a signal event.
Processes both suspend and resume executing wait statements (see 10.2 Wait statement). A process statement (11.3) with a sensitivity list has an implicit wait statement as the last statement with it's sensitivity list having the contents of the process sensitivity list.
The signal bit1 won't update while the loop is executing, there is no implicit or explicit wait statement causing the process to suspend.
To solve the issue use a variable:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all; -- arithmetic for std_logic_vector
entity prueba2 is
port (
entrada: in std_logic_vector(0 to 10) := (others => '1')
);
end entity prueba2;
architecture behavioral of prueba2 is
signal bit1: std_logic_vector(0 to 3):= (others => '0');
function to_string (inp: std_logic_vector) return string is
variable image_str: string (1 to inp'length);
alias input_str: std_logic_vector (1 to inp'length) is inp;
begin
for i in input_str'range loop
image_str(i) := character'VALUE(std_ulogic'IMAGE(input_str(i)));
end loop;
return image_str;
end function;
begin
prueba:
process (entrada) -- sensitivity list implies wait as final statement
-- variable suma: unsigned(0 to 2):= (others => '0');
variable suma: std_logic_vector(0 to 3);
begin
suma := (others => '0'); -- start at 0 every time
for i in entrada'range loop
if entrada(i) = '1' then
-- bit1 <= bit1+1 -- signals don't update until the beginning
-- of the next simulation cycle (at the soonest)
suma := suma + 1; -- variables assignment is immediate
end if;
end loop;
report "bit1 will be assigned " & to_string(suma);
bit1 <= suma; -- both the same length processes communicate with signals
-- wait on entrada; -- implicit wait statement, process suspends
end process;
end architecture behavioral;
You can see the variable has the same length as bit1. That's required, you input entrada has a length of 11 which requires a 4 bit value to accumulate the number of '1's.
There are some embellishments for testing. Some simulators will allow you to simulate a top level with ports as long as inputs have default values or can be forced. Here entrada is supplied with all '1's. The to_string function is provided in revision -2008 of the standard, also provided here for compatibility with earlier revisions. The report statement tells us the value of suma that will be assigned to bit1.
When the design unit is analyzed and elaborated (compiled) then run:
ghdl -a --ieee=synopsys -fexplicit prueba2.vhdl
ghdl -e --ieee=synopsys -fexplicit prueba2
ghdl -r prueba2
prueba2.vhdl:37:9:#0ms:(report note): bit1 will be assigned 1011
The loop has successfully counted all the '1's, and bit1 will have an update scheduled with the same simulation time (here 0 ms). The simulator will execute a follow on simulation cycle (a delta cycle) then without any further schedule signal updates scheduled in any projected output waveform (a queue) the simulation time will advance to TIME'HIGH and simulation will end.
When a simulation starts every process executes at least once following initialization. The event on bit1 will cause a signal value update but there are no processes in the stand alone example sensitive to bit1 and simulation will cease.
The default value on the input entrada, function to_string and the report statement can be removed, they are present for testing, a testbench not having been provided.
The VHDL code below is a simple swap program. But it is not swapping the inputs a and b. I have given the transcript values in the comments.
library ieee;
use ieee.std_logic_1164.all;
entity vhdl_swap is
port(a,b: inout integer);
end vhdl_swap;
architecture ar of vhdl_swap is
signal s : std_logic;
begin
process(s)
variable var : integer:=0;
begin
report "var is" & integer'image(var); -- 0
report "a is " & integer'image(a); -- 10 - (given value when simulated)
report "b is " & integer'image(b); -- 20 - (given value when simulated)
report "---------------------------";
var := a;
report "var is " & integer'image(var);--var = 10 (assigned properly)
a<=b;
report "a is " & integer'image(a);-- a=10(same value but not assigned)
b<=var;
report "b is " & integer'image(b);-- b=20(same value but not assigned)
report "-----------------------------------";
report "a is " & integer'image(a);--a=10
report "b is " & integer'image(b);--b=20
--print()
end process;
end;
There is something which acts in the statement a<=b, but i don't know what prevents itself from assigning it.
The new value assigned with VHDL <= is not available for read until an delta delay has passed.
This is a fundamental property of VHDL, since it reflects the way register update works then the signal that triggers the update is a clock.
This also means that you can actually do the swap without a variable, but simply doing:
a <= b;
b <= a;
There are other issues with the code, e.g. what is the s used for, using a and b for both input and output will give a drive conflict, unless resolution function is added.
If you assign a new value to a signal in VHDL with <= without giving an explicit delay (with after <time>), then the new signal value will be available in the next delta cycle. A new delta cycle starts, when the simulator has suspended all processes which have been scheduled for the current delta cycle. And a process is suspended at a wait statement. Your process has an implicit wait on S; statement at the end, because you described a process with a sensitivity list containing S.
You assigned the inout ports a and b here which behave the same as a signal.
Because, the signal update is visible not until the next delta cycle, all your report statements print out the same value for a and b respectively. That is, they print out the values of a and b when the process has started / resumed.
Assigning a signal is different to assigning a variable, e.g. var in your code, which gets updated immediately.
Your process is executed only once, because the signal S is not changed. Every process is executed once after the simulation starts and then suspended at the wait statement (the implicit one in your code as described above).
You said, that a and b have the initial value of 10 and 20, respectively, but I couldn't reproduce this with ModelSim nor GHDL. I tried it with the following testbench which I think is the only possible way:
library ieee;
use ieee.std_logic_1164.all;
entity vhdl_swap_tb is
end entity vhdl_swap_tb;
architecture sim of vhdl_swap_tb is
-- component ports
signal a : integer := 10;
signal b : integer := 20;
begin -- architecture sim
-- component instantiation
DUT: entity work.vhdl_swap
port map (
a => a,
b => b);
end architecture sim;
I had to use initial values for a and b here, because both ports of mode inout and of an unresolved type. Thus, I cannot add a second driver by assigning a and b in another testbench process.
Because, the signal updates are delayed (at least) until the next delta cycle, you do not need an extra variable. Here is a very short example code demonstrating the swapping of two signals:
library ieee;
use ieee.std_logic_1164.all;
entity swap is
end entity swap;
architecture sim of swap is
signal a : integer := 10;
signal b : integer := 20;
signal clock : std_logic := '1';
begin
-- clock generation
clock <= not clock after 10 ns;
-- swapping
process(clock)
begin
if rising_edge(clock) then
a <= b;
b <= a;
end if;
end process;
end sim;
The swapping is done at every rising edge of the clock, as can be seen in the following waveform:
In some testbench code I use a procedure to do something with a signal. I then use this procedure multiple times in sequence on different signals. This works fine as long as I explicitly define the signal; as soon as I index signals in a loop it fails with
(vcom-1450) Actual (indexed name) for formal "s" is not a static signal name.
Why is this not possible and how can I work around it?
Probably I could move this to a for ... generate, but then I want do_something to be called in a nicely defined sequence.
library ieee;
use ieee.std_logic_1164.all;
entity test is
end test;
architecture tb of test is
signal foo : std_logic_vector(1 downto 0);
begin
dummy: process is
procedure do_something (
signal s : out std_logic
) is begin
s <= '1';
report "tic";
wait for 1 ns;
-- actually we would do something more interesting here
s <= '0';
report "toc";
end procedure;
begin
-- This works well, but requires manual loop-unrolling
do_something(foo(0));
do_something(foo(1));
-- This should do the same
for i in foo'range loop
-- This is the offending line:
do_something(foo(i));
end loop;
wait; -- for ever
end process dummy;
end architecture tb;
I'm using ModelSim 10.4 PE.
Interestingly, if foo is a variable local to the process, (and s is adjusted to suit) ghdl compiles this. Which highlights the problem in the original version. The "for" loop is required to drive the whole of foo all the time because you can't make signal drivers appear or disappear at will - it can't be ambivalent about which bits it's driving, (and as you can see, the procedure tries to drive different bits at different times).
So if you can readjust your application to allow variable update semantics, and make foo a variable local to the process, that will work. (You would have to copy its value to a signal before every "wait" if you wanted to see the effect!)
Alternatively, pass the entire foo signal and the index to the subprogram, so that the latter always drives all of foo as follows...
(I've also added the missing bits and fixed the spurious concurrent "wait" : in future, PLEASE check your code example actually compiles before posting!)
library ieee;
use ieee.std_logic_1164.all;
entity test is
end test;
architecture tb of test is
signal foo : std_logic_vector(1 downto 0);
begin
dummy: process is
procedure do_something (
signal s : out std_logic_vector(1 downto 0);
constant i : in natural
) is begin
s <= (others => '0');
s(i) <= '1';
report "tic";
wait for 1 ns;
-- actually we would do something more interesting here
s(i) <= '0';
report "toc";
end procedure;
begin
-- This works well, but requires manual loop-unrolling
do_something(foo,0);
do_something(foo,1);
-- This should do the same
for i in foo'range loop
-- This is the offending line:
do_something(foo,i);
end loop;
wait; -- for ever
end process dummy;
end architecture tb;
I share your feelings about this being a silly limitation of the language. Minus the wait and report statements your example certainly has a valid hardware implementation, let alone well defined simulation behavior.
I think this situation can be avoided in most cases. For example, in your simple example you could just copy the contents of the procedure into the process body, or pass the whole vector as Brian proposed. If you really need to do it, this is one workaround:
architecture tb of test is
signal foo : std_logic_vector(1 downto 0);
signal t : std_logic;
signal p : integer := 0;
begin
foo(p) <= t;
dummy: process is
procedure do_something (
signal s : out std_logic
) is begin
s <= '1';
wait for 1 ns;
s <= '0';
end procedure;
begin
for i in foo'range loop
p <= idx;
do_something(t);
wait for 0 ns;
end loop;
wait;
end process dummy;
end architecture tb;
This only works in simulation and will result in one delta cycle delay per iteration, compared to unrolling the loop which finishes in zero time when the procedure contains no wait statements.
If I have the following VHDL-200X architecture:
architecture my_arc of my_entity is
signal test_char : std_logic_vector(7 downto 0);
signal test_char_c : character;
signal test_char_i : integer;
begin
test_char <= "01001010";
test_char_i <= to_integer(unsigned(test_char));
test_char_c <= character'val(test_char_i);
end architecture my_arc;
...and simulate it (in Xilinx iSim 14.1), test_char_c does not change from its initial value of NUL even though test_char_i takes the value 74. If, however, I replace the last line in the architecture with:
process(test_char_i)
begin
test_char_c <= character'val(test_char_i);
end process;
...then test_char_c takes on the value J as I'd expect.
I thought that a bare signal assignment will be updated concurrently if any signal on the right hand side changes. In other words, it's equivalent to a process that is sensitive to all signals involved in the assignment.
Why doesn't test_char_c get updated in the first instance?
Edit: Changing test_char_i to a natural doesn't change the result.
At initialisation time, test_char_i has the value integer'low, which doesn't map to a character - Modelsim 10.0 reports:
# ** Fatal: (vsim-3390) Result ?(-2147483648) of attribute 'VAL is out of range NUL (0) to 'ΓΏ' (255).
# Time: 0 ns Iteration: 0 Process: /my_entity/line__15 File: attr.vhd
# Fatal error in Architecture my_arc at attr.vhd line 15
#
If I make test_char_i a natural, so that it initialises to 0, things work as you expect (in Modelsim at least, haven't tried iSim)
I thought that a bare signal assignment will be updated concurrently if any signal on the right hand side changes. In other words, it's equivalent to a process that is sensitive to all signals involved in the assignment.
That's correct.
Why doesn't test_char_c get updated in the first instance?
It does.
A Minimal, Complete, and Verifiable example with a monitor process that will report all value updates on test_char_c:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity my_entity is
end entity;
architecture my_arc of my_entity is
signal test_char : std_logic_vector(7 downto 0);
signal test_char_c : character;
signal test_char_i : natural; -- integer;
begin
test_char <= "01001010";
test_char_i <= to_integer(unsigned(test_char));
test_char_c <= character'val(test_char_i);
process (test_char_c)
begin
report "test_char_c = " & character'image(test_char_c);
end process;
end architecture my_arc;
Note the change to the declaration of test_char_i to overcome the default initial value (INTEGER'LOW) causing a bound check failure as reported by Martin Thompson.
This was analyzed, elaborated and simulated using a -1993 compliant VHDL tool:
ghdl -r my_entity
../../src/ieee/numeric_std-body.v93:2098:7:#0ms:(assertion warning): NUMERIC_STD.TO_INTEGER: metavalue detected, returning 0
my_entity.vhdl:19:9:#0ms:(report note): test_char_c = nul
my_entity.vhdl:19:9:#0ms:(report note): test_char_c = 'J'
The assertion warning from package numeric_std is caused by the test_char default intial value of "UUUUUUUU".
The first reported test_char_c value is the NUL you reported and occurs because the initial value of test_char_i is 0 (mapping to NUL).
The second is in response to the concurrent simple signal assignment to test_char resulting in an update of test_char_i in turn resulting in an update of test_char_c(and resuming the monitor process). It reflects the assigned bit string to test_char with a value x"4A" (corresponding to the character 'J').
If instead of the shown monitor process you were to have an assertion statement of the form:
assert test_char_c /= NUL
report "test_char_c = " & character'image(test_char_c);
You'd find that only the first report statement is displayed because an assertion statement condition is evaluated and when found false asserts.
Likewise if the "/=" in the condition were changed to "=" only the second report statement would be displayed (showing 'J').
Without providing a MCVe your problem can't be duplicated (or blamed on the then nascent ISIM).