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.
Related
I am trying to understand the concurrent procedure call with different parameters' class. Assuming I have the procedure test and it is called concurrently like below:
ENTITY tb IS
END ENTITY tb;
ARCHITECTURE sim OF tb IS
SIGNAL cnt : integer RANGE 0 TO 3 := 0;
SIGNAL str : string(1 TO 5) := (OTHERS => ' ');
PROCEDURE test (CONSTANT number : IN integer RANGE 0 TO 3 := 0;
SIGNAL num_str : OUT string(1 TO 5)) IS
BEGIN
REPORT "here";
CASE number IS
WHEN 0 => num_str <= "zero ";
WHEN OTHERS => num_str <= "one ";
END CASE;
END PROCEDURE;
BEGIN
test(cnt, str); -- CONCURRENT CALL TO PROCEDURE TEST
PROCESS
BEGIN
FOR i IN 0 TO 3 LOOP
WAIT FOR 10 ns;
cnt <= i;
END LOOP;
WAIT;
END PROCESS;
END ARCHITECTURE sim;
In THE VHDL DESIGNER GUIED
Another point to note about concurrent procedure calls is that if there are no signals
associated with in-mode or inout-mode parameters, the wait statement in the equivalent
process does not have a sensitivity clause. If the procedure ever returns, the process suspends indefinitely. This may be useful if we want the procedure to be called only once at
startup time.
As procedure test has no signals associated with in-mode or inout-mode, it supposes to be executed once and then suspends indefinitely. But with this example, the procedure is executed 4 times.
Can someone explain to me what is happening or what I am missing?
Section 11.4 of the 2008 LRM (IEEE Std 1076-2008):
For any concurrent procedure call statement, there is an equivalent
process statement [...] The equivalent process statement also has no
sensitivity list, an empty declarative part, and a statement part that
consists of a procedure call statement followed by a wait statement.
The procedure call statement consists of the same procedure name and
actual parameter part that appear in the concurrent procedure call
statement.
If there exists a name that denotes a signal in the actual part of any
association element in the concurrent procedure call statement, and
that actual is associated with a formal parameter of mode in or inout,
then the equivalent process statement includes a final wait statement
with a sensitivity clause that is constructed by taking the union of
the sets constructed by applying the rule of 10.2 to each actual part
associated with a formal parameter.
Forget about the last part, in your case things are super simple and your equivalent process is:
process
begin
test(cnt, str);
wait on cnt;
end process;
The CONSTANT class declaration of your procedure's declaration only indicates that (section 4.2.2.2):
For parameters of class constant or variable, only the values of the
actual or formal are transferred into or out of the subprogram call.
It somehow forces you to manipulate this value as if it was a constant and nothing else... inside the procedure's body. It forbids you, for instance, to use signal attributes (e.g. number'EVENT). But it doesn't say anything about the actual parameter that you will associate to this formal parameter when instantiating the procedure.
And the result is, logically, what you observe: your procedure is called 4 times in the equivalent process. Each time the value of the actual parameter, that is, the signal cnt is passed through the formal parameter number.
And your book is right:
[...] if there are no signals associated with in-mode or inout-mode
parameters, the wait statement in the equivalent process does not have
a sensitivity clause.
Indeed, you have a signal (cnt) associated with an in-mode parameter (number).
I'm designing a test bench and I need to create a random sequence of bits for one of the system's inputs which is normally controlled by the user.
I also want this sequence of bits not being in the same order every time I run the simulation.
I cannot use a PRNG since its initial state will be predefined meaning it while produce the same numbers every time. I also used the uniform function but I had the same issue.
RAND_GEN : process(clk) is
variable seed1, seed2 : positive := 1;
variable re : real;
begin
if rising_edge(clk) then
uniform(seed1, seed2, re);
if (re < 0.5) then
rand_bit <= '0';
else
rand_bit <= '1';
end if;
end if;
end process;
Is there any alternatives for this problem?
Testing with randomly generated inputs is a powerful tehnique and is the technique commonly used to verify ICs these days. Normally, you would run a test with a known, per-determined seed, whereas you want to be able to generate a varying seed. So, you absolutely MUST record this seed when you run the test and provide a mechanism to run a test using this seed. Otherwise, when you find a bug, you will not be able to test whether you've fixed it. You might find it more useful to a a fixed set of tests with a smaller number of manually-generated seeds.
You could use the linux date command with the %s format specifier, which outputs the number of seconds since 1/1/1970 and redirect that to a file.
date +%s >! seed.txt
Then read the file, eg:
RAND_GEN : process(clk) is
variable seed1, seed2 : positive := 1;
variable re : real;
file F: TEXT;
variable L: LINE;
variable seed_RNG : boolean := false;
begin
if not seed_RNG then
file_open(F, "seed.txt", READ_MODE);
readline (F, L);
read (L, seed1); -- or seed2
file_close(F);
report "seed1 = " & integer'image(seed1);
seed_RNG := true;
end if;
if rising_edge(clk) then
uniform(seed1, seed2, re);
if (re < 0.5) then
rand_bit <= '0';
else
rand_bit <= '1';
end if;
end if;
end process;
I don't know anything of VHDL, but in general I try to avoid randomness in tests. Flaky unit tests, for example, are bad. What's the value of a test that fails only sometimes?
Anyway, supposed you really want to do it, do you have access to a timer? You can initialize the PRNG with the current time as seed. Not cryptographically safe, but probably for this use case good enough.
Just for the record, in case anyone needs something similar, I used the above ideas by creating a do file which first writes the date in a file and then runs the do file of the actual test bench which reads this number as suggested before.
set t [clock seconds]
set outputFile [open date.txt w]
puts $outputFile $t
close $outputFile
do testbench.do
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:
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;
Hi I'm trying to implement a mealy machine using VHDL, but I'll need to debounce the button press. My problem is I'm not sure where should I implement the debouncing. My current work is like this:
process(clk)
begin
if(clk' event and clk = '1') then
if rst = '1' then
curr_state <= state0;
else
curr_state <= next_state;
end if;
end if;
end process;
process(curr_state, op1,op0,rst) --here op1,op0 and rst are all physical buttons and I need to debounce op1 and op0
begin
if rst = '1' then
...some implementation
else
...implement the debounce logic first
...process some input
case curr_state is
when state0=>...implementation
...similar stuff
end case;
end process;
I'm not sure whether I'm doing in the right way or not. In the second process, should I put the rst processing like this, or should I put it inside when state0 block? Also, as the processing of debounce requires counting, do I put it outside the case block like this? Thank you!
I would use a completely separate block of code to debounce any button signals, allowing your state machine process to focus on just the state machine, without having to worry about anything else.
You could use a process like this to debounce the input. You could of course exchange variables for signals in this example (with associated assignment operator replacements).
process (clk)
constant DEBOUNCE_CLK_PERIODS : integer := 256; -- Or whatever provides enough debouncing
variable next_button_state : std_logic := '0'; -- Or whatever your 'unpressed' state is
variable debounce_count : integer range 0 to DEBOUNCE_CLK_PERIODS-1 := 0;
begin
if (rising_edge(clk)) then
if (bouncy_button_in /= next_button_state) then
next_button_state := bouncy_button_in;
debounce_count := 0;
else
if (debounce_count /= DEBOUNCE_CLK_PERIODS-1) then
debounce_count := debounce_count + 1;
else
debounced_button_out <= next_button_state;
end if;
end if;
end if;
end process;
Another option would be to sample the bouncy_button_in at a slow rate:
process (clk)
constant DEBOUNCE_CLK_DIVIDER : integer := 256;
variable debounce_count : integer range 0 to DEBOUNCE_CLK_DIVIDER-1 := 0;
begin
if (rising_edge(clk)) then
if (debounce_count /= DEBOUNCE_CLK_DIVIDER-1) then
debounce_count := debounce_count + 1;
else
debounce_count := 0;
debounced_button_out <= bouncy_button_in;
end if;
end if;
end process;
The advantage of the first method is that it will reject glitches in the input. In either case, you would use the debounced_button_out (or whatever you want to call it, perhaps rst) in your state machine, whose code then contains only the core state machine functionality.
If you wanted even more debouncing, you could use another counter to create an enable signal for the processes above, to effectively divide down the clock rate. This could be better than setting the division constant to a very high number, because you may not be able to meet timing if the counter gets beyond a certain size.
You could even create a debounce entity in a separate file, which could be instantiated for each button. It could have a generic for the constant in the above process.
There's also hardware debouncing, but I suppose that's outside the scope of this question.
In the second process, should I put the rst processing like this, or
should I put it inside when state0 block?
Only put it in the State0 block
Also, as the processing of
debounce requires counting, do I put it outside the case block like
this?
Counting needs to be done in a clocked process. Since you are doing a two process statemachine, you cannot do it in the case block. I typically put these sort of resources in a separate clocked process anyway.
For states, you need: IS_0, TO_1, IS_1, TO_0.
The TO_1 and TO_0 are your transition states. I transition from TO_1 to IS_1 when I see a 1 for 16 ms. I transition from TO_0 to IS_0 when I see a 0 for 16 ms. Run your counter when you are in the TO_1 or TO_0 state. Clear your counter when you are in the IS_1 or IS_0 state.
This should get you stated.