I want to generate an automated input stimulus for my DUT. This input is going to different modules at the same time and working on this data. I want my input to be generated in an increasing manner. Like 0000,0001,0010,0011...1111
I tried using a for loop but it only uses the last data from the loop and works on that.
always_comb begin
for (i=0, i<16; i=i+1)
begin
data <= i;
end
end
When I give inputs individually like,
data = 8'd1;
#2;
data = 8'd2;
#2;
It works smoothly with all input values specified.
always_comb cannot have delays. At least per the IEEE1800 standard.
You can do something like this:
bit [3:0] data; // bit so the initial value is 0, not x
bit clk;
always #1 clk++; // or some other clock model
always_ff #(posedge clk) begin
data <= data+1;
end
or something like this:
logic [3:0] data;
initial begin
for (i=0, i<16; i=i+1) begin
data = i;
#2;
end
end
Or some other similar code with time delay.
Related
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
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 have a problem with the code below. The code is synthesized in ISE 14.2.
input [1:8176] m_d_in;
reg [1:511] m_d [1:16];
integer i;
always # (*)
begin
for (i=0; i<16; i=i+1)
begin
m_d[i+1] = m_d_in[ 1+511*i : 511+511*i];
end
end
after synthesizing, this error shows up:
HDL Compiler:1660_<'Address of CodeName.v> <'Line of Error>: procedural assignment to a non-register i is not permitted, left-hand side should be reg/integer/time/genvar
the line of Error refer to this:
m_d[i+1] = m_d_in[ 1+511*i : 511+511*i];
i also have tested using the:
reg [4:0] i;
and
genvar i;
instead of:
integer i;
and got exactly the same error I wrote above!
I know there is a solution by using a case instead of the code above, but in its not the right solution for me.
Thanks a lot.
Since you are range is consistent, Indexing vectors and arrays with +: is also possible:
always #* begin
for (i=0; i<16; i=i+1)
m_d[i+1] = m_d_in[511*i+1 +: 511];
end
The indexed part select (+:/-:) and generate block (from Morgan's answer) were introduced in IEEE std 1364-2001. Any modern simulator and synthesizer will support them.
If you use wire instead of reg then a single assign line can be wrapped up in a generate.
module tb(
input [1:8176] m_d_in
);
wire [1:511] m_d [1:16];
genvar i;
generate
for (i=0; i<16; i=i+1) begin
assign m_d[i+1] = m_d_in[ 1+511*i : 511+511*i];
end
endgenerate
endmodule
To keep the reg and use generates you would need to do:
module tb(
input [1:8176] m_d_in
);
reg[1:511] m_d [1:16];
genvar i;
generate
for (i=0; i<16; i=i+1) begin
always #* begin
m_d[i+1] = m_d_in[ 1+511*i : 511+511*i];
end
end
endgenerate
endmodule
In a generate loop, you often need to connect the first iteration of wires to your inputs (or some unique set of wires) before the array stuff kicks in. Pasted below is a snippet from my parameterizable OR-Reduce module (my assignment requires structural verilog, so oOUt = |adjA is not legal).
for(i=0; i<depth; i=i+1) begin : lvl
localparam iWidth = p2Width>>i;
localparam oWidth = iWidth>>1;
wire [oWidth-1:0] tmp;
if(i==0) begin
or2$ reduce [oWidth-1:0]
(tmp, adjA[iWidth/2-1:0], adjA[iWidth-1:iWidth/2]);
end else begin
or2$ reduce [oWidth-1:0]
(tmp, lvl[i-1].tmp[iWidth/2-1:0], lvl[i-1].tmp[iWidth-1: iWidth/2]);
end
end
I have to put this nasty if-statement to catch the first iteration and connect it to the inputs. The problem is that I can't just change the initial i value to 1 and declare a lvl[0].tmp outside of the for-loop. Here's what I think would look nicer if it were legal.
wire [p2Width-1] lvl[0].tmp;
or2$ reduce [oWidth-1:0]
(lvl[0].tmp, adjA[iWidth/2-1:0], adjA[iWidth-1:iWidth/2]);
for(i=1; i<depth; i=i+1) begin : lvl
localparam iWidth = p2Width>>i;
localparam oWidth = iWidth>>1;
wire [oWidth-1:0] tmp;
or2$ reduce [oWidth-1:0]
(tmp, lvl[i-1].tmp[iWidth/2-1:0], lvl[i-1].tmp[iWidth-1: iWidth/2]);
end
Is there a way to clean up my generate loop?
You can declare your input array to be one entry wider than required. I find this often results in more readable code:
logic [N_LEVELS:0] block_inputs; // Last entry not used, optimised away
logic [N_LEVELS-1:0] block_outputs;
// Start of pipeline
assign block_inputs[0] = stage1_input;
genvar i;
generate
for (i=0; i<N_LEVELS; i++) begin: levels
some_block i_some_block (
.data (block_inputs[i]),
.result (block_outputs[i])
);
assign block_inputs[i+1] = block_outputs[i];
end
endgenerate
assign final_result = block_outputs[N_LEVELS-1];
I need to randomize a large memory. All of the data is contained inside of latch modules -- 1 per bit.
How do I fix the following?
// Quick mock up of the memory, which I can't change
`define WIDTH 64*144
module latch(
output reg Q);
endmodule
module memory;
wire [`WIDTH-1:0] latchData;
latch latch[`WIDTH-1:0] (.Q(latchData[`WIDTH-1:0]));
endmodule
// My testbench, which I can change
module test;
reg [31:0] index;
memory memory();
initial begin
$display("Initial data: %0d", memory.latchData);
injectRandomData();
$display("Randomized data: %0d", memory.latchData);
end
task injectRandomData();
// Using for loop does not work
//for (index=0; index < `WIDTH; index = index+1) begin
// memory.latch[index].Q = $urandom;
//end
// Doing it this way seems terrible
memory.latch[0].Q = $urandom;
memory.latch[1].Q = $urandom;
memory.latch[2].Q = $urandom;
// ... a bunch more to go; don't wait up
endtask
endmodule
Code on EDA Playground: http://www.edaplayground.com/s/4/235
Quick and dirty solution:
task injectRandomData();
->do_InjectRandomData;
#0; // gen always block a change to finish;
endtask
event do_InjectRandomData;
genvar index;
generate
for(index = 0; index < `WIDTH; index = index +1) begin : gen_loop
always #(do_InjectRandomData) begin : set_rand
memory.latch[index].Q = $urandom;
end
end
endgenerate
Code on EDA Playground: http://www.edaplayground.com/s/6/236
You cannot dynamically index an array of instances. Two ways to fix this:
Do you really need to model a memory at such a low level? Change the memory model to an RTL description. It will be much better for performance anyways.
Use a generate block with a for-loop around the initial block instead of a for-loop inside the initial block. If you need to do this at some time other than time 0 you can use an event to trigger it.
genvar index;
event injectRandomData;
for (index=0; index < `WIDTH; index++) begin
always #injectRandomData
memory.latch[index].Q = $urandom;
end