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

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

Related

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

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

Systemverilog recursion update value for next stage

I am trying to create a recursive logic in Systemverilog but I seem to be missing the right logic to carry the output of one iteration to the next.
Here is an example of the problem:
parameter WIDTH=4;
module test_ckt #(parameter WIDTH = 4)(CK, K, Z);
input CK;
input [WIDTH-1:0] K;
output reg Z;
wire [WIDTH/2-1:0] tt;
wire [WIDTH-1:0] tempin;
assign tempin = K;
genvar i,j;
generate
for (j=$clog2(WIDTH); j>0; j=j-1)
begin: outer
wire [(2**(j-1))-1:0] tt;
for (i=(2**j)-1; i>0; i=i-2)
begin
glitchy_ckt #(.WIDTH(1)) gckt (tempin[i:i], tempin[(i-1):i-1], tt[((i+1)/2)-1]);
end
// How do I save the value for the next iteration?
wire [(2**(j-1))-1:0] tempin;
assign outer[j].tempin = outer[j].tt;
end
endgenerate
always #(posedge CK)
begin
// How do I use the final output here?
Z <= tt[0];
end
endmodule
module glitchy_ckt #(parameter WIDTH = 1)(A1, B1, Z1);
input [WIDTH-1:0] A1,B1;
output Z1;
assign Z1 = ~A1[0] ^ B1[0];
endmodule
Expected topology:
S1 S2
K3--<inv>--|==
|XOR]---<inv>----|
K2---------|== |
|==
<--gckt---> |XOR]
|==
K1--<inv>--|== |
|XOR]------------|
K0---------|== <-----gckt---->
Example input and expected outputs:
Expected output:
A - 1010
----
S1 0 0 <- j=2 and i=3,1.
S2 1 <- j=1 and i=1.
Actual output:
A - 1010
----
S1 0 0 <- j=2 and i=3,1.
S2 0 <- j=1 and i=1. Here, because tempin is not updated, inputs are same as (j=2 & i=1).
Test-bench:
`timescale 1 ps / 1 ps
`include "test_ckt.v"
module mytb;
reg CK;
reg [WIDTH-1:0] A;
wire Z;
test_ckt #(.WIDTH(WIDTH)) dut(.CK(CK), .K(A), .Z(Z));
always #200 CK = ~CK;
integer i;
initial begin
$display($time, "Starting simulation");
#0 CK = 0;
A = 4'b1010;
#500 $finish;
end
initial begin
//dump waveform
$dumpfile("test_ckt.vcd");
$dumpvars(0,dut);
end
endmodule
How do I make sure that tempin and tt get updated as I go from one stage to the next.
Your code does not have any recursion in it. You were trying to solve it using loops, but generate blocks are very limited constructs and, for example, you cannot access parameters defined in other generate iterations (but you can access variables or module instances).
So, the idea is to use a real recursive instantiation of the module. In the following implementation the module rec is the one which is instantiated recursively. It actually builds the hierarchy from your example (I hope correctly).
Since you tagged it as system verilog, I used the system verilog syntax.
module rec#(WIDTH=1) (input logic [WIDTH-1:0]source, output logic result);
if (WIDTH <= 2) begin
always_comb
result = source; // << generating the result and exiting recursion.
end
else begin:blk
localparam REC_WDT = WIDTH / 2;
logic [REC_WDT-1:0] newSource;
always_comb // << calculation of your expression
for (int i = 0; i < REC_WDT; i++)
newSource[i] = source[i*2] ^ ~source[(i*2)+1];
rec #(REC_WDT) rec(newSource, result); // << recursive instantiation with WIDTH/2
end // else: !if(WIDTH <= 2)
initial $display("%m: W=%0d", WIDTH); // just my testing leftover
endmodule
The module is instantiated first time from the test_ckt:
module test_ckt #(parameter WIDTH = 4)(input logic CK, input logic [WIDTH-1:0] K, output logic Z);
logic result;
rec#(WIDTH) rec(K, result); // instantiate first time )(top)
always_ff #(posedge CK)
Z <= result; // assign the results
endmodule // test_ckt
And your testbench, a bit changed:
module mytb;
reg CK;
reg [WIDTH-1:0] A;
wire Z;
test_ckt #(.WIDTH(WIDTH)) dut(.CK(CK), .K(A), .Z(Z));
always #200 CK = ~CK;
integer i;
initial begin
$display($time, "Starting simulation");
CK = 0;
A = 4'b1010;
#500
A = 4'b1000;
#500 $finish;
end
initial begin
$monitor("Z=%b", Z);
end
endmodule // mytb
Use of $display/$monitor is more convenient than dumping traces for such small examples.
I did not do much testing of what I created, so there could be issues, but you can get basic ideas from it in any case. I assume it should work with any WIDTH which is power of 2.

How do I add an input called Unsigned / Signed for Verilog comparator testbench code?

I'm new to coding verilog.
This is code for a 3-bit Comparator. I need help adding a signal called 'US' (unsigned/signed) to my testbench code. When the signal is High(unsigned mode), the Comparator interprets the numbers as Unsigned numbers. When the signal is Low (Signed Mode), the Comparator interprets the numbers as signed numbers.
module comparator(A,B,G,E,L,US);
input [2:0]A;
input [2:0]B;
input US;
output G,E,L;
reg G,E,L;
always#(*)
begin
if(US==0)
begin
L=$signed(A)<$signed(B);
E=$signed(A)==$signed(B);
G=$signed(A)>$signed(B);
end
else
L = A < B;
E = A==B;
G = A > B;
end
endmodule
TEST BENCH CODE:
`timescale 1ns /1ps
module comparator_tb();
reg [2:0]A=3'b000;
reg [2:0]B=3'b000;
reg US;
wire G,E,L;
integer i,j;
comparator uut(A,B,G,E,L,US);
initial begin
for(i=0;i<8;i=i+1)
begin
for(j=0;j<8;j=j+1)
begin
#50
B=B+1;
end
A = A+1;
B=3'b000;
end
#100
$stop;
end
endmodule
i guess you want to toggle US in your test bench. something like the following?
since US is declared as wire (default), you need the assign statement:
integer us_count;
assign US = us_count;
initial begin
for(us_count = 0; us_count < 1; us_count++) begin
for(i=0;i<8;i=i+1)
begin
for(j=0;j<8;j=j+1)
begin
#50
B=B+1;
end
A = A+1;
B=3'b000;
end
end
#100
$stop;
end
if you declare it as reg, you can use it directly in the loop instead of the us_count and do not need the assign
reg US;
initial begin
for (US = 0; US < 1; US++)
...
The rest depends on how you want to test it.

Verilog : For loop inside an always

I am trying to implement a module that use a for loop inside a always block
We are using an array of 0 & 1 in order to record the number of signal received during a certain time.
Unfortunatly we received that kind of error :
ERROR:Xst:2636 - "Tourniquet.v" line 54: Loop has iterated 10000 times. Use "set -loop_iteration_limit XX" to iterate more.
It seems that the for loop isn't allowed inside a always block (The n doesn't seems to reset).
I have looked at various website and forum but don't have found any solutions.
Here is my code :
module Tourniquet(
input t0,
input mvt,
input clk,
output init
);
reg initialisation;
reg [0:99] memoire;
reg count = 0;
reg compteur = 0;
reg n;
assign init = initialisation;
always #(posedge clk)
begin
if (count==99)
begin
if (mvt)
begin
memoire[count]=1;
count=0;
end
else
begin
memoire[count]=0;
count=0;
end
end
else
begin
if (mvt)
begin
memoire[count]=1;
count = count + 1;
end
else
begin
memoire[count]=0;
count = count + 1;
end
end
end
always #(posedge clk)
begin
initialisation = 0;
for (n=0; n<99; n=n+1) compteur = compteur + memoire[n];
if (compteur>10) initialisation = 1;
compteur = 0;
end
endmodule
I can't find the solution nor be sure of what is the problem, any tips or help is welcomed.
Thank you very much !
You need the loop to iterate 100 times. For that, you need atleast 8 bit counter variable.
But here, n is declared as reg n, a single bit counter variable. So, n+1 gives 1 and doing n+1 again gives 0.
So, the condition of for loop for which n<100 is always satisfied. And the for loop never terminates.
This is the main reason your for loop iterates many many times.
Generally integer datatype is used for these kind of counters. integer is similar to 32 bit reg. Declare n as integer n or reg [7:0] n to have proper increment of counter and proper termination of loop.
Further to #sharvil111's answer, I see all these are single bits:
reg initialisation;
reg count = 0;
reg compteur = 0;
reg n;
An N bit reg in Verilog is normally declared, eg:
reg [N-1:0] n;
where N is some number (constant). And I see this is a 100-bit number:
reg [0:99] memoire;
Obviously, I don't know your design intent, but I suspect you wanted an array of N-bit numbers:
reg [N-1:0] memoire [0:99];
where N is again some number (constant).

verilog debugging

I don't know what is wrong with the code below. Can someone help me debug?
module iloop(z,a);
input [31:0] a;
output z;
reg [4:0] i;
reg s, z;
initial begin
s = 0;
for(i=0; i<32; i=i+1) s = s | a[i];
z = !s;
end
endmodule
Your code has an infinite loop. You have declared i as a 5-bit reg, which means its range of values is (decimal) 0 to 31. But, your for loop checks if i < 32, which is always true.
Once i=31, i is incremented and rolls over to 0.
$display is your friend. If you add it to your for loop, you will see the problem:
for(i=0; i<32; i=i+1) begin $display(i); s = s | a[i]; end
I think you want i<31.
Or, maybe you want to OR all the bits of a together, using the bit-wise OR operator:
s = |a;
You should explain in words what you are trying to achieve.

Resources