How do I write this verilog testbench? - verilog

I am using Vivado to try to write a testbench for some Verilog code I wrote for an FSM. Here is the timing diagram which I derived from the state diagram:
.
Below is what I have so far:
module testbench();
reg X_tb, clk_tb, rstn_tb;
wire S_tb, V_tb;
statemachine statemachine_tb(X_tb, clk_tb, rstn_tb, S_tb, V_tb);
initial begin
#10 X_tb = 0;
end
endmodule
If X_tb and clk_tb are inputs and S_tb and V_tb are outputs, how do I include timing for S_tb and V_tb? I keep getting an error saying I can't use wire variables.

S_tb and V_tb are the expected outputs which are asserted by the design module which in this case is "statemachine".
The test bench encompasses the design, it acts as a stimulus for your design. In this case you will apply inputs like
initial
begin
rstn_tb = 0; //assuming an active low reset
clk_tb = 0;
#10 X_tb = 0;
end
always
#5 clk_tb = ~clk_tb; //generates a clock having a frequency of 100MHz
The above inputs are passed on-to the statemachine module and in response to that the statemachine module generates some result which is received at the ports S_tb & V_tb.
Also while instantiating the module its better to use the dot-name convention like
module half_add(a,b,sum,carry); //half adder, partially written
input a,b;
output sum,carry;
//logic
endmodule
module full_add(a,b,cin,sum,carry)
input a,b,cin;
output sum,carry;
//wires are not declared
//instantiating half_add
half_add h1(.a(w1),
.b(w2),
.sum(sum1),
.carry(carry1)
);
half_add h2(
//similar call as h1 instance
);
endmodule
The above type of instance avoids errors now if I instantiate the module like the one below
half_add h1(w1,
w2,
sum1,
carry1
);
Here the ports are connected based on the position and one may make mistakes while writing this like accidentally one may write
half_add h1(w1,
w2,
carry1,
sum1
);
This will cause carry1 to be connected to the sum port of the half adder module resulting in erroneous output. Hence I suggest you to avoid such type of instance calling. I guess that could be the reason for the error.

You don't need to provide timing delays for your state machine outputs. You are building a synchronous design; therefore the outputs should simply be sampled on the relevant clock edges (falling edge from your instructions). You can do this by embedding the following line in your testbench everytime you want to wait for a clock edge:
# (negedge clk_tb)
You can then capture the outputs or directly perform comparisons to expected values. Then change your input stimulus and wait for another clock edge and repeat for your next comparison.

Related

What is best way to call another module?

I'm confused about connection, I want to use ALU to call RippleCarry module, and I need to do branch without always block and Procedure Assignment.
I don't know what method is best. I see others have written in TestBench.v or ALU.v.
Here's my code.
ALU.v
module ALU( Signal, a, b, Output );
input [31:0] a, b;
input [5:0] Signal;
output [31:0] Output;
// write here ? or write into test bench?
// if Signal is 6'd35, do RippleCarry.
/*RippleCarry RC( .a(a), .b(b), .Sum(Output) ); */
endmodule
RippleCarray.v
module RippleCarry(
input [31:0] a, b,
input Cin,
output Cout,
output [31:0] Sum
);
In verilog, modules are not called, but instantiated. Unlike traditional programming, verilog is a hardware descriptive language; meaning it is code describing hardware, not specifying instructions to be run by a cpu as you do in typically programming languages. Hardware doesn't materialize and dematerialize when signals take on different values; the control signals simply define which of many different data paths is connected between input and output.
In your case, you wouldnt write something like this:
module ALU(...)
if (Signal == 6'd35) begin
RippleCarry RC(...);
end
endmodule
Since Signal is a control line that changes value as the hardware runs, this would imply the ripple carry adder exists when the Signal is 35 and disappears when it's not.
Instead, the adder should be instantiated, it exists in the design and it always there. The problem now is to direct it's output to the output of the ALU only when Signal is 35.
module ALU(input [5:0] Signal,
input [31:0] a, b,
output reg [31:0] Output); // Note, I made Output a reg so I can use always, it doesn't mean it's actually a register
wire [31:0] rcOutput;
// Instantiate the RC adder so it exists in the hardware
RippleCarry RC(.a(a), .b(b), .Sum(rcOutput));
// Direct the output of the RippleCarry adder to the output only when signal is 35, otherwise just leave it at 0.
// Use switch here to make it easy to add more operations later
always #(*) begin
Output = 32'd0; // default
case (Signal)
6'd35: Output = rcOutput; // rc add
endcase
end
endmodule
Edit: I see now you want to do it without using always or assign, which doesn't change the fundamental design but makes it more obscure and less scalable, which is why I'm leaving the above as a reference. In the case we only have one op code for signal, we can simply implement the logic that compares signal to 35 and masks output if not equal in gates:
// Replace the always block with the below, though it's certainly not as nice, it's a possible implementation of that always block in gates
wire [5:0] SignalN;
wire SignalIs35;
not g1[5:0](SignalN, Signal);
// 35 is 100011 in binary, so see if Signal is that value
and g2(SignalIs35, Signal[5], SignalN[4], SignalN[3], SignalN[2], Signal[1], Signal[0]);
and g3[31:0](Output, rcOutput, {32{SignalIs35}});

Seeing X for values in one module

I have two modules 'wired' together. One is a simple sequence detector and one is a counter.
Here are the two signatures of the methods:
module Detector1010 (input [3:0] co_in, input j, clk, rst, output w, output reg init, output reg en);
module counter (input clk, rst, en, init, output reg [3:0] co );
Essentially that output register 'co' in the counter is intended to be readable from the Dector1010 module (hence the co_in) variable. The reason for that is I want to be able to detect when the co reaches a certain value, to perform some sort of action.
Within 'Detector1010' there is always block which checks the value of 'co_in'
$display("sleep! %d", co_in);
if(co_in == 4'b1111) begin
//reached 16!
$display("reached 16!");
end
Here I am just waiting for the counter value to reach 16 and printing what it is each time the always block executes. (How often does that execute? It seems to run just constantly and not on a clock.. I guess the whole point is its always running?). However by display instead prints:
"sleep! x"
As if the actual value of that register does not get passed in. I was using a wire to connect the two modules, so I thought this sort of input is allowed:
wire [3:0] co;
wire init;
wire en;
assign co = 4'b0000;
Detector1010 det(co, j, clk, rst, w, init, en);
counter cnt(clk, rst, en, init, co);
as I figured the 'co' variable would just work as a databus between the detector and the counter modules. I guess I am misunderstanding how that variable works? Not really sure what I am doing wrong here!
I can post the whole code example. I was trying to just keep it concise.
You have contention on the co signal which results in x. Remove this line:
assign co = 4'b0000;
Your counter module drives the co output signal, but your testbench continually drives it to 0, at all times starting at time 0. co would normally be initialized inside the counter module.

call by reference in verilog code

I am trying to change a c++ code into verilog HDL.
I want to write a module that changes one of its inputs. (some how like call by reference in c++)
as I know there is no way to write a call by reference module in verilog (I can't use systemverilog)
Here is a code that I wrote and it works. are there any better ways to do this?!
my problme is that the register I want to be call by reference is a big array. this way duplicates the registers and has a lot of cost.
module testbench();
reg a;
wire b;
reg clk;
initial begin
a = 0;
clk = 0;
#10
clk = 1;
end
test test_instance(
.a(a),
.clk(clk),
.aOut(b)
);
always#(*)begin
a = b;
end
endmodule
module test(
input a,
input clk,
output reg aOut
);
always #(posedge clk) begin
if (a == 0)begin
a = 1;
aOut = a;
end
end
endmodule
Verilog is not a software programming language; it is a hardware description language. The inputs to a module are pieces of metal (wires, tracks, pins); the outputs from a module are pieces of metal. If you want a port that is both an input and an output you can use an inout. However, inout ports are best avoided; it is usually much better to use separate inputs and outputs.
A Verilog module is not a software function. Nothing is copied to the inputs; nothing is copied from the outputs. A Verilog module is a lump of hardware: it has inputs (pieces of metal carrying information in) and outputs (pieces of metal carrying information out).
Your are right to say that you can use either pass-by-copy or pass-by-reference in SystemVerilog. If you wish to pass a large data structure into a function or into/out of a task, then passing by reference may save simulation time.
By reference means by address, so to translate this to hdl directly you would either need to provide a way for the module to get on that bus and perform transactions based on that address.
Or better, if you need this as an input take each of the items in the struct and make individual inputs from them. If it is pass by reference because it is an output or is also an output, then you create individual outputs for each of the items in the struct. The module then distinguishes between the input version of that sub item and output version of that sub item.
my.thing.x = my.thing.x + 1;
becomes something like
my_thing_x_output = my_thing_x_input + 1;

Designing a 3-bit counter using T-flipflop

module tff(t,i,qbprev,q,qb);
input t,i,qbprev;
output q,qb;
wire q,qb,w1;
begin
assign w1=qbprev;
if(w1==1)begin
not n1(i,i);
end
assign q=i;
not n2(qb,i);
end
endmodule
module counter(a,b,c,cin,x0,x1,x2);
input a,b,c,cin;
output x0,x1,x2;
reg a,b,c,x0,x1,x2,temp,q,qb;
always#(posedge cin)
begin
tff t1(.t(1) ,.i(a),.qbprev(1),.q(),.qb());
x0=q;
temp=qb;
tff t2(.t(1) ,.i(b),.qbprev(temp),.q(),.qb());
x1=q;
temp=qb;
tff t3(.t(1) ,.i(c),.qbprev(temp),.q(),.qb());
x2=q;
a=x0;
b=x1;
c=x2;
end
endmodule
This is my code in verilog. My inputs are - the initial state - a,b,c and cin
I get many errors with the first of them being "w1 is not a constant" What doesn this mean?
I also get error "Non-net port a cannot be of mode input" But I want a to be an input!
Thank you.
Modules are instantiated as pieces of hardware. They are not software calls, and you can not create and destroy hardware on the fly therefore:
if(w1==1)begin
not n1(i,i);
end
With that in mind I hope that you can see that unless w1 is a constant parameter, and this is a 'generate if' What your describing does not make sense.
instance n1 is not called or created as required, it must always exist.
Also you have the input and output connected to i. i represent a physical wire it can not be i and not i. these need to be different names to represent different physical wires.
In your second module you have :
input a,b,c,cin;
// ...
reg a,b,c; //...
Inputs can not be regs as the warning says, just do not declare them as regs for this.
input a,b,c,cin;
output x0,x1,x2;
reg x0,x1,x2,temp,q,qb;

What is the difference between these verilog codes?

I'm was following a tutorial to blink a led in my fpga.
These are the codes presented :
1)
module LED (
input [17:0] SW,
output reg [17:0] LEDR
);
assign led = switch;
endmodule
2) --------
module LED (
input [17:0] SW,
output reg [17:0] LEDR
);
always #(*)
led = switch;
endmodule
3) ---------
module LED (
input CLOCK_50,
input [17:0] SW,
output reg [17:0] LEDR
);
always #(posedge CLOCK_50)
LEDR = SW;
endmodule
Your first example uses continuous assignment to set the value of led to the value of switch. It's like connecting led and switch directly with a wire. Whenever switch changes, led also changes.
Your second example does the same thing but uses an always block. always blocks have a sensitivity list, which contains signals that will trigger the block to run. In this case, it's *, meaning that it triggers any time any of the signals in the blocks change. I believe this is identical to your first example.
Your third example uses sequential logic to set LEDR to SW. In this case, the always block triggers only when the CLOCK_50 signal goes high from a non-high state. If CLOCK_50 never rises, LEDR is never set to any value.
By the way, I don't think your first or second examples are synthesizable. I think led and switch should be LEDR and SW.
These articles give a better description of the concepts in your examples:
Assignments : http://verilog.renerta.com/mobile/source/vrg00005.htm
Always Blocks: http://www.asic-world.com/verilog/verilog_one_day3.html

Resources