How to write verilog testbench to loop through a n bit input n times - verilog

I am writing a testbench to loop through a 16 bit Data input I have where it will go through each bit and change the value from a 0 to a 1, for example the first iteration would be 10000...00, second would be 010000...00, 001000...00, and so on. Here is what I have right now.
module testbench();
//inputs
reg [15:0] Data = 0;
//outputs
wire [15:0] Errors;
OLS uut (
.Data (Data),
.Errors (Errors)
);
integer k = 0;
initial
begin
Data = 0;
for(k = 0; k<16; k=k+1)
begin
Data[k] = 1;
if(k>0)
begin
Data[k-1] = 0;
end
end
end
endmodule
I am unsure if I have made a mistake with my testbench or if this is expected behavior, but I can't tell how I am supposed to see the expected output in each iteration. I have tried to use console outputs to keep track of where I am in the loop and if I am resetting the previous bit to 0 after I am done with that one.
I expect to get 0 in the 'Errors' output in every iteration, so basically I need help to verify my code does what I want it to do, and also how to read the graphical output of the simulation.

The loop in the post unrolls in 0 time.
Some delay is needed to create a waveform.
Also need a $finish, otherwise the testbench runs forever.
Like this:
module testbench();
//inputs
reg [15:0] Data = 0;
integer k = 0;
initial
begin
#100;
end
initial
begin
Data = 0;
for(k = 0; k<16; k=k+1)
begin
Data[k] = 1;
if(k>0)
begin
Data[k-1] = 0;
end
#5; // delay here
end
end
initial
begin
$dumpfile("dump.vcd");
$dumpvars;
end
endmodule

Related

verilog testbench(with for loop) for 3-8 decoder signal value not updating

I'm new to verilog. I write a 3-8 decoder and a testbench for it. This is 38_decoder_tb.v:
module decoder_38(input [2:0] in, output reg [7:0] out);
always #* begin
case (in) //Switch based on concatenation of control signals
3'b000 : out = 8'b00000001;
3'b001 : out = 8'b00000010;
3'b010 : out = 8'b00000100;
3'b011 : out = 8'b00001000;
3'b100 : out = 8'b00010000;
3'b101 : out = 8'b00100000;
3'b110 : out = 8'b01000000;
3'b111 : out = 8'b10000000;
endcase
end
endmodule
This is 38_decoder_tb.v:
`timescale 1ns / 1ns
module tb_decoder_38;
// decoder_38 Parameters
parameter PERIOD = 20;
// decoder_38 Inputs
reg [2:0] in ;
// decoder_38 Outputs
wire [7:0] out ;
reg clk;
integer i;
initial
begin
clk = 0;
forever #(PERIOD/2) clk=~clk;
end
decoder_38 u_decoder_38 (
.in ( in [2:0] ),
.out ( out [7:0] )
);
initial
begin
in = 0;
#(PERIOD*2);
for (i = 3'd0; i < 3'd8; i=i+1) begin
in = i;
#PERIOD;
end
end
endmodule
I stimulate the testbench module with ModelSim 10.5. As you can see, the signal just doesn't update. What's the problem? Does it have something to do with the for loop?
Yes, the issue is with the loop.
Your problem is in definition of 3'd8. 8 is the same as 1000 in binary presentation and requires 4 bits. Therefore, 3-bits of it (as you requested) yield 000. As a result your loop does not run at all, looking like the following: for (i = 3'd0; i < 0; i++).
Variable i is defined as integer. An integer type is a 4-state data type, 32-bit signed integer. So, rewriting loop as for(i = 0; i < 8; i++) will solve your issues. There is absolutely no need to define sizes for the constants in this loop.
And, to avoid infinite loop, you need to use $finish when appropriate, as suggested in the other answer.
The posted testbench has an infinite loop because of the forever loop with nothing to stop it.
I added a #30 delay to see the last clock of data, and $finish to stop it.
After that the code behaves as expected.
All 4 simulators on EDA Playground show the same.
initial
begin
in = 0;
#(PERIOD*2);
for (i = 3'd0; i <= 3'd7; i=i+1) begin
in = i;
#PERIOD;
end
//
#30;
$finish;
end
Here is a link playground I put together https://www.edaplayground.com/x/aZYL

How to implement transition coverage on non-consecutive sampling points?

var_1 changes from value 0 to 1 then from 1 to 2 and so on till 15, but not on consecutive sampling points. I sample on every clock cycle, but the value might change after some arbitrary clk cycles. The transition coverage I write does not work. Can we write transition coverage for this case?
bit [3:0] var_1;
var1: coverpoint var_1
{
bins var_1_trans_bin = (0=>1=>2=>3=>4=>5=>6=>7=>8=>9=>10=>11=>12=>13=>14=>15);
bins var_1_bin[] = {[0:15]};
}
I see that the var_1_bin is getting covered 100% but not the var_1_trans_bin.
Here is the whole code:
module GRG_coverpoint;
bit [3:0] var_1;
bit Running;
bit clk;
// Example showing bins and transitions
covergroup CG1 #(posedge clk);
coverpoint var_1
{
bins var_1_trans_bin = (0=>1=>2=>3=>4=>5=>6=>7=>8=>9=>10=>11=>12=>13=>14=>15);
bins var_1_bin[] = {[0:15]};
}
endgroup
initial begin
automatic CG1 cg1_inst = new;
for (int j = 0; j < 16; j++)
begin
var_1 = j;
#20;
end
$display ("CG1 Coverage = %.2f%%", cg1_inst.get_coverage());
Running = 0;
end
initial begin
clk = 0;
Running = 1;
while (Running) begin
#5 clk = ~clk;
end
$display ("Finished!!");
end
endmodule
As you realized, you do not want to sample coverage on every clock cycle. You want to sample it only when var_1 changes value. You can declare the covergroup without the optional coverage_event (#(posedge clk) in your case), then call the sample method in a separate procedural block every time the variable changes:
module GRG_coverpoint;
bit [3:0] var_1;
bit [3:0] var_2;
bit Running;
bit clk;
// Example showing bins and transitions
covergroup CG1;
coverpoint var_1
{
bins var_1_trans_bin = (0=>1=>2=>3=>4=>5=>6=>7=>8=>9=>10=>11=>12=>13=>14=>15);
bins var_1_bin[] = {[0:15]};
}
endgroup
CG1 cg1_inst = new;
initial begin
cg1_inst.sample(); // Sample the initial 0 value
forever #(var_1) cg1_inst.sample();
end
initial begin
for (int j = 0; j < 16; j++)
begin
var_1 = j;
#20;
end
$display ("CG1 Coverage = %.2f%%", cg1_inst.get_coverage());
Running = 0;
end
initial begin
clk = 0;
Running = 1;
while (Running) begin
#5 clk = ~clk;
end
$display ("Finished!!");
end
endmodule

Verilog test bench for loop(priority, problem with value)

For i=0 and j=0 this code makes my a,b,cin and s signals to be xxxxxxxx.
For i=0 and j=1 my a,b,cin and s are all 00000000.Which should be the result for my adder for i=0 j=0 cin =0. Whats wrong? I am sure my adder module is correct.
http://prntscr.com/lpngel
http://prntscr.com/lpngih (...and so on)
Most of the trouble came at first with the for loops and began when some of the values werent printed and then after i added begin end in each loop i saw the full loop result whith the above problem^^^^^.Still dont know how it worked but it did
module test_cla4_n;
reg [7:0] a,b;
reg cin;
wire [7:0] s;
wire cout;
integer i;
integer j;
integer cv;
cla4_n#(.n(8)) UUT
(.a(a), .b(b),
.cin(cin),
.s(s), .cout(cout));
initial
begin
for(cv=0;cv<=1;cv=cv+1)
begin
for (i=0;i<6;i=i+1)
begin
for (j=0;j<6;j=j+1)
begin
#100 a = j; b = i; cin = cv;
end
end
end
end
initial
begin
$monitor($time, ,"a=%9b, b=%9b, cin=%b, sum=%9b", a, b, cin, s);
end
endmodule
Whether you put the #100 delay before or after the assignments does not matter as long as you understand how the delay works w.r.t. the loop.
The only place begin/end is required anywhere in the code you show is with the innermost for(j=0; ` loop.
All 4-state variables and nets in verilog are initialized with 'x'. Therefore, before you drive something in your simulation, all signals will remain 'x'.
In your test bench you use #100 delay in your loop. In your expression it means that all the assignments which follow #100 will happen only after 100 verilog simulation cycles (or whatever you set with 'timescale'). But before it all your values will remain 'x'.
Now when #100 triggers in you will have the following:
#100
a = j; <-- 0
b = i; <-- 0
cin = cv; <-- 0
j = j + 1; <-- 1 << from the loop
You end up with a = 0, b = 0, c = 0, and j will change to '1'.
Now your simulation will kick in and calculate the results for the above. You can continue this train of thoughts for the rest of simulation.
In order for all those statement to happen in side the loop after #100, yes you need to put begin/end around them. Otherwise only the first statement will be evaluated in the innermost loop. This is similar to any programming language.
for (j=0;j<6;j=j+1)
begin
#100 // wait here for 100 simulation ticks
a = j;
b = i;
cin = cv;
end

Verilog: wait for module logic evaluation in an always block

I want to use the output of another module inside an always block.
Currently the only way to make this code work is by adding #1 after the pi_in assignment so that enough time has passed to allow Pi to finish.
Relevant part from module pLayer.v:
Pi pi(pi_in,pi_out);
always #(*)
begin
for(i=0; i<constants.nSBox; i++) begin
for(j=0; j<8; j++) begin
x = (state_value[(constants.nSBox-1)-i]>>j) & 1'b1;
pi_in = 8*i+j;#1; /* wait for pi to finish */
PermutedBitNo = pi_out;
y = PermutedBitNo>>3;
tmp[(constants.nSBox-1)-y] ^= x<<(PermutedBitNo-8*y);
end
end
state_out = tmp;
end
Modllue Pi.v
`include "constants.v"
module Pi(in, out);
input [31:0] in;
output [31:0] out;
reg [31:0] out;
always #* begin
if (in != constants.nBits-1) begin
out = (in*constants.nBits/4)%(constants.nBits-1);
end else begin
out = constants.nBits-1;
end
end
endmodule
Delays should not be used in the final implementation, so is there another way without using #1?
In essence i want PermutedBitNo = pi_out to be evaluated only after the Pi module has finished its job with pi_in (=8*i+j) as input.
How can i block this line until Pi has finished?
Do i have to use a clock? If that's the case, please give me a hint.
update:
Based on Krouitch suggestions i modified my modules. Here is the updated version:
From pLayer.v:
Pi pi(.clk (clk),
.rst (rst),
.in (pi_in),
.out (pi_out));
counter c_i (clk, rst, stp_i, lmt_i, i);
counter c_j (clk, rst, stp_j, lmt_j, j);
always #(posedge clk)
begin
if (rst) begin
state_out = 0;
end else begin
if (c_j.count == lmt_j) begin
stp_i = 1;
end else begin
stp_i = 0;
end
// here, the logic starts
x = (state_value[(constants.nSBox-1)-i]>>j) & 1'b1;
pi_in = 8*i+j;
PermutedBitNo = pi_out;
y = PermutedBitNo>>3;
tmp[(constants.nSBox-1)-y] ^= x<<(PermutedBitNo-8*y);
// at end
if (i == lmt_i-1)
if (j == lmt_j) begin
state_out = tmp;
end
end
end
endmodule
module counter(
input wire clk,
input wire rst,
input wire stp,
input wire [32:0] lmt,
output reg [32:0] count
);
always#(posedge clk or posedge rst)
if(rst)
count <= 0;
else if (count >= lmt)
count <= 0;
else if (stp)
count <= count + 1;
endmodule
From Pi.v:
always #* begin
if (rst == 1'b1) begin
out_comb = 0;
end
if (in != constants.nBits-1) begin
out_comb = (in*constants.nBits/4)%(constants.nBits-1);
end else begin
out_comb = constants.nBits-1;
end
end
always#(posedge clk) begin
if (rst)
out <= 0;
else
out <= out_comb;
end
That's a nice piece of software you have here...
The fact that this language describes hardware is not helping then.
In verilog, what you write will simulate in zero time. it means that your loop on i and j will be completely done in zero time too. That is why you see something when you force the loop to wait for 1 time unit with #1.
So yes, you have to use a clock.
For your system to work you will have to implement counters for i and j as I see things.
A counter synchronous counter with reset can be written like this:
`define SIZE 10
module counter(
input wire clk,
input wire rst_n,
output reg [`SIZE-1:0] count
);
always#(posedge clk or negedge rst_n)
if(~rst_n)
count <= `SIZE'd0;
else
count <= count + `SIZE'd1;
endmodule
You specify that you want to sample pi_out only when pi_in is processed.
In a digital design it means that you want to wait one clock cycle between the moment when you are sending pi_in and the moment when you are reading pi_out.
The best solution, in my opinion, is to make your pi module sequential and then consider pi_out as a register.
To do that I would do the following:
module Pi(in, out);
input clk;
input [31:0] in;
output [31:0] out;
reg [31:0] out;
wire clk;
wire [31:0] out_comb;
always #* begin
if (in != constants.nBits-1) begin
out_comb = (in*constants.nBits/4)%(constants.nBits-1);
end else begin
out_comb = constants.nBits-1;
end
end
always#(posedge clk)
out <= out_comb;
endmodule
Quickly if you use counters for i and j and this last pi module this is what will happen:
at a new clock cycle, i and j will change --> pi_in will change accordingly at the same time(in simulation)
at the next clock cycle out_comb will be stored in out and then you will have the new value of pi_out one clock cycle later than pi_in
EDIT
First of all, when writing (synchronous) processes, I would advise you to deal only with 1 register by process. It will make your code clearer and easier to understand/debug.
Another tip would be to separate combinatorial circuitry from sequential. It will also make you code clearer and understandable.
If I take the example of the counter I wrote previously it would look like :
`define SIZE 10
module counter(
input wire clk,
input wire rst_n,
output reg [`SIZE-1:0] count
);
//Two way to do the combinatorial function
//First one
wire [`SIZE-1:0] count_next;
assign count_next = count + `SIZE'd1;
//Second one
reg [`SIZE-1:0] count_next;
always#*
count_next = count + `SIZE'1d1;
always#(posedge clk or negedge rst_n)
if(~rst_n)
count <= `SIZE'd0;
else
count <= count_next;
endmodule
Here I see why you have one more cycle than expected, it is because you put the combinatorial circuitry that controls your pi module in you synchronous process. It means that the following will happen :
first clk positive edge i and j will be evaluated
next cycle, the pi_in is evaluated
next cycle, pi_out is captured
So it makes sense that it takes 2 cycles.
To correct that you should take out of the synchronous process the 'logic' part. As you stated in your commentaries it is logic, so it should not be in the synchronous process.
Hope it helps

Verilog : syntax error : unexpected SYSTEM_IDENTIFIER on using $display

My aim is to write a test fixture that reads hex values from an input file and displays it to the screen. I am using the below code but i am getting a syntax error at line " $display ("%d:%h",j,srcPacketIn[j]);". The exact error is :
** Error: C:\altera\13.0\test.v(32): near "$display": syntax error, unexpected SYSTEM_IDENTIFIER
Could anybody please help me out?
module test_fixtures;
parameter TestCycles = 12;
parameter ClockPeriod = 10;
reg [7:0] srcPacketIn [0:(5*TestCycles)-1];
reg clock, reset;
genvar j;
initial
begin
$readmemh("input.h",srcPacketIn);
end
initial
begin
reset = 0;
clock = 1;
end
always #ClockPeriod clock = ~clock;
for (j=0; j < 59; j=j+1)
begin
$display ("%d:%h",j,srcPacketIn[j]);
end
endmodule
The code works in Icarus Verilog 0.9.6 with the changes below.
Compile/sim results here: EDA Playground
module test_fixtures;
parameter TestCycles = 12;
parameter ClockPeriod = 10;
reg [7:0] srcPacketIn [0:(5*TestCycles)-1];
reg clock, reset;
integer j; // <-- CHANGED
initial
begin
$readmemh("input.h",srcPacketIn);
end
initial
begin
reset = 0;
clock = 1;
end
always #ClockPeriod clock = ~clock;
initial begin // <-- ADDED
for (j=0; j < 59; j=j+1)
begin
$display ("%d:%h",j,srcPacketIn[j]);
end
end // <-- ADDED
endmodule

Resources