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
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 really beginner in VHDL and I am trying to make a hot-n-cold game. My first goal is generating numbers between -1024 and 1024 so that I can use 10 switches to guess. However, there are a lot of sources about positive integers but I could not find any for negative ones. Here is a sample code of mine. Also, someone says LFSR does this job but I am new and I could not understand the behavior of LFSR.
library ieee;
use ieee.math_real.all;
entity rand_gen is
end rand_gen;
architecture behavior of rand_gen is
signal rand_num : integer := 0;
begin
process
variable seed1, seed2: positive;
variable rand: real;
variable range_of_rand : real := 1024.0;
begin
uniform(seed1, seed2, rand);
rand_num <= integer(rand*range_of_rand);
wait for 10 ns;
end process;
end behavior;
Please have a look at Open Source VHDL Verification Methodology. This framework offers many packages to ease writing of testbenches. For instance there is a RandomPkg VHDL package, that offers lots of randomization procedures, functions and a protected type for constrained random: RandInt(min, max).
process
variable RV : RandomPType;
begin
RV.Init("dkudbcsdkbcfsdbcfdsyc"); -- create a seed value
for in i 0 to 15 loop
rand_num <= RV.RandInt(-1024, 1024);
wait until rising_edge(Clock);
end loop;
end process;
The protected type will take care of handling the two seed integers, that you would need to handle manually if you use ieee.math_real.uniform(...)
I have a problem in synthesis with my VHDL code : I am trying to get the logarithm value of an input signal S_ink:
My code :
entity ....
....
architecture rtl of myEntity is
attribute syn_looplimit : integer;
attribute syn_looplimit of loopabc : label is 16384;
logcalc:process(I_clk)
variable temp : integer;
variable log : integer;
begin
if(I_clk'event and I_clk='1') then
if (IN_rst='0') then
S_klog<=0;
temp:=0;
log:=0;
else
temp := S_ink+1; --S_ink is an input of my entity (integer)
log:=0;
loopabc:while (temp/=0) loop
temp:=temp/2;
log :=log+1;
end loop loopabc;
S_klog<=3*log;
end if;
end if;
end process;
It works very well in simulation but doesn't synthesize.
The error message is : "While loop is not terminating. You can set the maximum of loop iterations with the syn_looplimit attribute"
However, this code synthesize (but that is not what I want)
entity ....
....
architecture rtl of myEntity is
attribute syn_looplimit : integer;
attribute syn_looplimit of loopabc : label is 16384;
logcalc:process(I_clk)
variable temp : integer;
variable log : integer;
begin
if(I_clk'event and I_clk='1') then
if (IN_rst='0') then
S_klog<=0;
temp:=0;
log:=0;
else
temp := 3000; -- a random constant value
log:=0;
loopabc:while (temp/=0) loop
temp:=temp/2;
log :=log+1;
end loop loopabc;
S_klog<=3*log;
end if;
end if;
end process;
When the synthesis tool translates the design, it will make a circuit with a topology that does not depend on the data values, but where the wires carries the data values. The circuit must have a fixed calculation latency between each level of flip-flops, so timing analysis can determine if the amount of logic between flip-flops can fit for the specified frequency. In this process any loops are unrolled, and you can think of this as converting the loop to a long sequence of ordinary (non-loop) statements. To do this unrolling, the synthesis tool must be able to determine the number of iterations in the loops, so it can repeated the loop body this number of times when doing loop unrolling.
In the first code example the number of iterations in the loop depends on the S_ink value, so the synthesis tool can't unroll the loop to a fixed circuit, since the circuit depends on the data value.
In the second code example the synthesis tool can determine the number of iterations in the loop, thus do the unrolling to a fixed circuit.
One way to address this is make the algorithm with a fixed number of iteration, where this number of iterations can handle the worst case input data, and where any superfluous iteration on other input data will not change the result.
Solution :
process(I_clk)
variable temp : integer;
variable log : integer;
begin
if(I_clk'event and I_clk='1') then
if (IN_rst='0') then
S_klog<=0;
temp:=0;
log:=0;
else
temp := S_ink+1;
log:=0;
for I in 1 to 14 loop
temp := temp/2;
if (temp /=0) then
log :=log+1;
end if;
end loop;
S_klog<=3*log; -- 3*log because of my application
end if;
end if;
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.
I'm working on a FIR filter, specifically the delay line. x_delayed is initialized to all zeros.
type slv32_array is array(natural range <>) of std_logic_vector(31 downto 0);
...
signal x_delayed : slv32_array(0 to NTAPS-1) := (others => (others => '0'));
This does not work:
x_delayed(0) <= x; -- Continuous assignment
DELAYS : process(samp_clk)
begin
if rising_edge(samp_clk) then
for i in 1 to NTAPS-1 loop
x_delayed(i) <= x_delayed(i-1);
end loop;
end if; -- rising_edge(samp_clk)
end process;
But this does:
DELAYS : process(samp_clk)
begin
if rising_edge(samp_clk) then
x_delayed(0) <= x; -- Registering input
for i in 1 to NTAPS-1 loop
x_delayed(i) <= x_delayed(i-1);
end loop;
end if; -- rising_edge(samp_clk)
end process;
The problem with this "solution" is that the first element in x_delayed is delayed by one sample, which it should not be. (The rest of the code expects x_delayed(0) to be the current sample).
I'm using Xilinx ISE 13.2, simulating with ISim, but this was also confirmed simulating with ModelSim.
What gives?
Edit:
The problem was essentially that, even though x_delayed(0) didn't appear to be driven inside the process, it was.
After implementing Brian Drummond's idea it works perfectly:
x_delayed(0) <= x;
-- Synchronous delay cycles.
DELAYS : process(samp_clk)
begin
-- Disable the clocked driver, allowing the continuous driver above to function correctly.
-- https://stackoverflow.com/questions/18247955/#comment26779546_18248941
x_delayed(0) <= (others => 'Z');
if rising_edge(samp_clk) then
for i in 1 to NTAPS-1 loop
x_delayed(i) <= x_delayed(i-1);
end loop;
end if; -- rising_edge(samp_clk)
end process;
Edit 2:
I took OllieB's suggestion for getting rid of the for loop. I had to change it, since my x_delayed is indexed from (0 to NTAPS-1), but we end up with this nice looking little process:
x_delayed(0) <= x;
DELAYS : process(samp_clk)
begin
x_delayed(0) <= (others => 'Z');
if rising_edge(samp_clk) then
x_delayed(1 to x_delayed'high) <= x_delayed(0 to x_delayed'high-1);
end if; -- rising_edge(samp_clk)
end process;
Edit 3:
Following OllieB's next suggestion, it turns out the x_delayed(0) <= (others => 'Z') was unnecessary, following his previous change. The following works just fine:
x_delayed(0) <= x;
DELAYS : process(samp_clk)
begin
if rising_edge(samp_clk) then
x_delayed(1 to x_delayed'high) <= x_delayed(0 to x_delayed'high-1);
end if;
end process;
In the first case, the x_delayed(0) actually has two drivers, out outside the
process, being x_delayed(0) <= x, and an implicit one inside the DELAY
process.
The driver inside the process is a consequence of a VHDL standard concept
called "longest static prefix", described in VHDL-2002 standard (IEEE Std
1076-2002) section "6.1 Names", and the loop construction with a loop variable
i, whereby the longest static prefix for x_delayed(i) is x_delayed.
The VHDL standard then further describes drives for processes in section
"12.6.1 Drivers", which says "... There is a single driver for a given scalar
signal S in a process statement, provided that there is at least one signal
assignment statement in that process statement and that the longest static
prefix of the target signal of that signal assignment statement denotes S ...".
So as a (probably surprising) consequence the x_delayed(0) has a driver in
the DELAY process, which drives all std_logic elements to 'U' since unassigned,
whereby the std_logic resolution function causes the resulting value to be 'U',
no matter what value is driven by the external x_delayed(0) <= x.
But in the case of your code, there seems to be more to it, since there actually are some "0" values in the simulation output for x_delayed(0), for what I can see from the figures. However, it is hard to dig further into this when I do not have the entire code.
One way to see that the loop is the reason, is to manually roll out the loop by
replacing the for ... loop with:
x_delayed(1) <= x_delayed(1-1);
x_delayed(2) <= x_delayed(2-1);
...
x_delayed(NTAPS) <= x_delayed(NTAPS-1);
This is of course not a usable solution for configurable modules with NTAPS as
a generic, but it may be interesting to see that the operation then is as
intuitively expected.
EDIT: Multiple solutions are listed in "edit" sections after the question above, based on comments. A solution with variable, which allows for complex expressions if required, is shown below. If complex expression is not required, then as per OllieB's suggestion it is possible to reduce the assign to x_delayed(1 to x_delayed_dir'high) <= x_delayed(0 to x_delayed_dir'high-1):
x_delayed(0) <= x;
DELAYS : process(samp_clk)
variable x_delayed_v : slv32_array(1 to NTAPS-1);
begin
if rising_edge(samp_clk) then
for i in 1 to NTAPS-1 loop
x_delayed_v(i) := x_delayed(i-1); -- More complex operations are also possible
end loop;
x_delayed(1 to x_delayed_dir'high) <= x_delayed_v;
end if; -- rising_edge(samp_clk)
end process;
During elaboration, drivers are created for all elements in x_delayed, regardless of the range of loop iterator. Hence, x_delayed(0) has two drivers associated with it. Std_Logic and Std_Logic_Vector are resoved types(i.e., when multiple drivers are associated with the signal with these types, the resolved function will determine the value of the signal by looking up a table in std package. Please refer to VHDL Coding Styles and Methodologies for more details.
the reason you have a problem is that the logic thinks you have two things assigning into the same signal simultaneously - both the continues assignment and the register assignment loop.
keep with the register implementation.
edit
if you have modelsim, you can use the 'trace x' option and see where it comes from.
might be that the other simulator also have this feature, but for modelsim i'm certain it works
In you not working example
x_delayed(0) <= x;
is aquvalent to
process(x)
begin
x_delayed(0) <= x;
end process;
So the process will assign x_delayed(0) only when x changes. Because this is a signal asignment the x_delayed(0) will not change immediatly, it will change after a delta cycle. Therefore, when process DELAYS is called assignment for x_delayed(0) is not happened yet!
Use a variable for x_delayed in your process, if you could.
x_delayed(0) := x;