Connections between sub modules wrong - system-verilog

My codes for Alu and Mux:
module alu(input logic [31:0]srca, srcb,
input logic [2:0] alucontrol,
output logic zero,
output logic [31:0]aluout);
logic [31:0] addr, subr, sltr, Andr, Orr;
assign addr = srca + srcb;
assign subr = srca - srcb;
assign sltr = (srca < srcb) ? 1 : 0;
assign Andr = srca & srcb;
assign Orr = srca | srcb;
always_comb
begin
case(alucontrol)
3'b010: aluout = addr;
3'b110: aluout = subr;
3'b111: aluout = sltr;
3'b000: aluout = Andr;
3'b001: aluout = Orr;
default: aluout = 32'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
endcase
zero = (subr == 0) ? 1 : 0;
end
endmodule
module mux2#(parameter WIDTH = 8)
(input logic [WIDTH-1:0] d0, d1,
input logic s,
output logic [WIDTH-1:0] y);
always_comb
begin
y = s?d1 : d0;
end
endmodule
and their instantiation under the same top module:
alu alu(srca, srcb, alucontrol, aluout, zero);
mux2 #(32) resmux(aluout, readdata, memtoreg, result);
When I try to connect my 2-1Mux resmux with my alu, the aluout doesn't get connected to resmux
aluout gets suspended
I could solve this by exchanging the order of aluout and zero, but could anybody explain why this happens and how to avoid? Thanks a lot!

There are a number of mechanisms for connecting ports in SystemVerilog. The mechanism you are using is positional. That means each signal connection has to go in the prescribed order that they appear in the module declaration of alu. The way your code is written, the signal zero in module top is connected to last port aluout declared in module alu.
SystemVerilog also has a by_name syntax .portname(signal). You can list all your port connections in any order that way.
alu alu(.srca(srca), .srcb(srcb), .alucontrol(alucontrol), .alu(aluout), .zero(zero));
When the signal name you are connecting matches the declared port name, you can just use .portname.
alu alu(.alucontrol, .aluout, .zero, .srca, .srcb);
And finally, if all the port names match the signal names, you can use a wildcard, .* as well as list exceptions explicitly
alu alu(.*, .zero(my_zero));

Related

How to make 4 bit ring counter with 4 flip flops?

I have this 4 bit ring counter that I'm trying to make, and I feel like I'm so close, but I can't figure out how to make one input depend on the previous state's output. Here's what I have:
`default_nettype none
// Empty top module
module top (
// I/O ports
input logic hz100, reset,
input logic [20:0] pb,
output logic [7:0] left, right
);
// Your code goes here...
q[3:0];
assign q[3:0] = right[3:0];
hc74_set setFF(.c(pb[0]), .d(pb[1]), .q(right[0]), .sn(pb[16]));
hc74_reset resetFF1(.c(pb[0]), .d(pb[1]), .q0(right[1]), .rn(pb[16]));
hc74_reset resetFF2(.c(pb[0]), .d(pb[1]), .q1(right[2]), .rn(pb[16]));
hc74_reset resetFF3(.c(pb[0]), .d(pb[1]), .q2(right[3]), .rn(pb[16]));
endmodule
// Add more modules down here...
// This is a single D flip-flop with an active-low asynchronous set (preset).
// It has no asynchronous reset because the simulator does not allow it.
// Other than the lack of a reset, it is half of a 74HC74 chip.
module hc74_set(input logic d, c, sn,
output logic q, qn);
assign qn = ~q;
always_ff #(posedge c, negedge sn)
if (sn == 1'b0)
q <= 1'b1;
else
q <= d;
endmodule
// This is a single D flip-flop with an active-low asynchronous reset (clear).
// It has no asynchronous set because the simulator does not allow it.
// Other than the lack of a set, it is half of a 74HC74 chip.
module hc74_reset(input logic d, c, rn,
output logic q, qn);
assign qn = ~q;
always_ff #(posedge c, negedge rn)
if (rn == 1'b0)
q <= 1'b0;
else
q <= d;
endmodule
This is on an FPGA simulator, which is why there are a few things like pb (these are push buttons) and left, right outputs which are sets of 8 LEDs each.
Let's first make sure we are on the same page
Based on wikipedia description of a ring counter
This could be implemented as follows:
module top (
// I/O ports
input logic reset_n,
input logic clk,
output logic [3:0] ring
);
// Your code goes here...
always #(posedge clk or negedge reset_n) begin
if(~reset_n) begin
ring = 4'b0001;
end
else begin
ring[0] <= ring[3];
ring[1] <= ring[0];
ring[2] <= ring[1];
ring[3] <= ring[2];
end
end
endmodule
The output ring is a 4-bit one hot vector, reset_n = 0 makes ring = 0001 every clock with reset_n = 1 rolls the ring to the right, [0001, 0010, 0100, 1000, 0001, ...].
But you want to use instances of the flops you defined. Notice that in an assignment a <= b, a is the output of the flop (q port), and b is the input of the flop (d port).
module top (
// I/O ports
input logic reset_n,
input logic clk,
output logic [3:0] ring
);
// Your code goes here...
hc74_set setFF(.c(clk), .d(ring[3]), .q(ring[0]), .sn(reset_n));
hc74_reset resetFF1(.c(clk), .d(ring[0]), .q0(ring[1]), .rn(reset_n));
hc74_reset resetFF2(.c(clk), .d(ring[1]), .q1(ring[2]), .rn(reset_n));
hc74_reset resetFF3(.c(clk), .d(ring[2]), .q2(ring[3]), .rn(reset_n));
endmodule
You have to connect the ports accordingly, I just used clk for the clock and reset_n for the negated reset signal.

How do I design Serial to Parallel Buffer in Verilog only using clocks?

I am looking to design a serial to parallel converter in Verilog which converts a fast clock serial input to a slower clock parallel input. I tried the following code which works in RTL but does not verify on Cadence Conformal. nclk is 16 times faster than clk. The serial data comes in at nclk and the parallel data is intended to come out at clk rate.
sEEG - Serial Input
eegOut - Parallel output
I can only have clk and nclk as my operation references due to tape-out bond pad limitations.
Following is the code that I have come up with which works well in functional simulation but Formal Verification fails.
module deserializer(sEEG, nclk, clk, eegOut);
input sEEG;
input nclk,clk;
reg [15:0] temp;
output reg [15:0] eegOut;
reg [4:0] i;
always #(negedge nclk) begin
temp[i] = sEEG;
i = i + 1;
end
always#(posedge clk) begin
i<=0;
eegOut <= temp;
end
endmodule
I feel you should use four bits in order to index 16 elements. If you parameterize the module, this could be done with:
# (parameter WIDTH = 16)
then later use it as:
localparam BIT_SEL = $clog2(WIDTH); //..this should give you "4" if WIDTH = 16
reg [BIT_SEL-1:0] i;
Also, you might want to include a clock synchronizer, you don't want metastability problems, an easy way to do this is to include "double-triggers", practically is to buffer the data and replicate it to the next slow clock cycle (adds 1 slow clock cycle latency). So, maybe this works:
module deserializer
# (parameter WIDTH = 16)
(sEEG, nclk, clk, eegOut);
input sEEG;
input nclk,clk;
reg [WIDTH-1:0] temp;
reg [WIDTH-1:0] temp_reg; //..synchronizer
output reg [WIDTH-1:0] eegOut;
always #(negedge nclk) begin
temp[WIDTH-2:0] <= temp[WIDTH-1:1];
temp[WIDTH-1] <= sEEG;
end
always#(posedge clk) begin
temp_reg <= temp;
eegOut <= temp_reg;
end
endmodule

How to bind an interface with system verilog module?

I have an system verilog interface
interface add_sub_if(
input bit clk,
input [7:0] a,
input [7:0] b,
input doAdd,
input [8:0] result
);
clocking dut_cb #(posedge clk);
output a;
output b;
output doAdd;
input result;
endclocking // cb
modport dut(clocking dut_cb);
endinterface: add_sub_if
And i have a SV module which uses this interface
module dummy(add_sub_if.dut _if);
....
endmodule: dummy
What is the ideal way to hook up this in my TB?
If i instantiate the interface, i need to create wires.
If i use bind then also i need to do a port mapping of the individual signals, that beats the convenience of having an interface.
Another add on question is, how to assign one such interface to another interface?
Thanks in advance,
Rajdeep
You can find a simple example of an interface definition and usage in the IEEE Std 1800-2012 Section 3.5 (Interfaces). It shows how to define the interface and hook it up to the design (the way you have already done it). It also shows how the interface can be instantiated (and connected) inside a top level module/wrapper (I copied the code below directly from the spec for your convenience):
interface simple_bus(input logic clk); // Define the interface
logic req, gnt;
logic [7:0] addr, data;
logic [1:0] mode;
logic start, rdy;
endinterface: simple_bus
module memMod(simple_bus a); // simple_bus interface port
logic avail;
// When memMod is instantiated in module top, a.req is the req
// signal in the sb_intf instance of the 'simple_bus' interface
always #(posedge clk) a.gnt <= a.req & avail;
endmodule
module cpuMod(simple_bus b); // simple_bus interface port
...
endmodule
module top;
logic clk = 0;
simple_bus sb_intf(.clk(clk)); // Instantiate the interface
memMod mem(.a(sb_intf)); // Connect interface to module instance
cpuMod cpu(.b(sb_intf)); // Connect interface to module instance
endmodule
Once you have the interface hooked up, then you can have drive/sample all the signals from a testcase program (just remember that you have to pass the interface to it). In this case, it would be be something like:
program testcase(simple_bus tb_if);
initial begin
tb_if.mode <= 0;
repeat(3) #20 tb_if.req <= 1'b1;
[...]
$finish;
end
endprogram
For a real-world example, you can check the source code of a UVM testbench that is available on my GitHub page. The interface hook-up is done in the xge_test_top.sv file.
Here is fsm dut with testbench.
This fsm dut performs state transition 1 - 0 - 1 - 0 in sequence.
Test bench verifies dut is properly working or not.
verilog module code(dut) :
module melay_fsm(o,clk,rst,i);
output o;
input i,clk,rst;
reg o;
reg [1:0]state;
// [1:0]state;
always#(posedge clk,posedge rst)
begin
if(rst)
begin
state <=2'b00;
end
else
begin
case(state)
2'b00:
begin
if(i)
state<=2'b01;
else
state<=2'b00;
end
2'b01:
begin
if(!i)
state<=2'b10;
else
state<=2'b01;
end
2'b10:
begin
if(i)
state<=2'b11;
else
state<=2'b00;
end
2'b11:
begin
if(!i)
state<=2'b00;
else
state<=2'b01;
end
endcase
end
end
always#(posedge clk,negedge rst)
begin
if(rst)
o<=1'b0;
else if(state==2'b11 && i==0)
o<=1'b1;
else
o<=1'b0;
end
endmodule
System verilog module code(testbench) :
interface melay_intf(input bit clk);
logic o,rst,i;
wire clk;
clocking c1#(posedge clk);
input o;
output i,rst;
endclocking
modport tes(clocking c1);
endinterface
module top;
bit clk;
always
#1 clk = ~clk;
melay_intf i1(clk);
melay_fsm a1(.o(i1.o),.clk(i1.clk),.rst(i1.rst),.i(i1.i));
melay_tes(i1);
endmodule
program melay_tes(melay_intf i1);
initial
#100 $finish;
initial
begin
i1.rst <= 0;
#4 i1.rst <= 1;
#4 i1.rst <= 0;
i1.i = 1;
#2 i1.i = 0;
#2 i1.i = 1;
#2 i1.i = 0;
#2 i1.i = 1;
#2 i1.i = 0;
repeat(10)
begin
i1.i = 1;
#2 i1.i = $urandom_range(0,1);
end
end
initial
$monitor("output = %d clk = %d rst = %d i = %d",i1.o,i1.clk,i1.rst,i1.i);
initial
begin
$dumpfile("mem.vcd");
$dumpvars();
end
endprogram
Important thing to note down here is connection of signals in top module.
melay_fsm a1(.o(i1.o),.clk(i1.clk),.rst(i1.rst),.i(i1.i));
Please, observe properly how I bind interface with testbench and dut.
Please, observe following things.
I defines interface with all the dut's signals.
I took instance(i1) of interface(melay_intf) in top module.
I took instance (a1) of dut (melay_fsm) in top module.
Now observes melay_fsm a1(.o(i1.o),.clk(i1.clk),.rst(i1.rst),.i(i1.i))
All the dut's signals are connected with interface.
I passed instance of interface(i1) in testbench. melay_tes(i1)
So, testbench can access interface signals and interface signals are connected to dut's signals.
Now, you can access dut's signals in your test bench with help of interface.
I think now you can understand proper flow.
Please ask the question if you have any doubt.
You can bind interface in system verilog module.
Here, I provides sample code with help of that you can understood how to bind interface in system verilog module and with dut.
Here I provides verilog module and system verilog module. Main part of code is interface from which verilog and system verilog module are connected.
verilog module code(dut) :
module dff(qn,d,clk,reset);
output qn;
input d,clk,reset;
reg qn;
always#(posedge clk,negedge reset)
begin
if (!reset)
begin
qn=1'bx;
end
else if (d==0)
begin
qn=0;
end
else if (d==1)
begin
qn=1;
end
end
endmodule
System verilog module code(testbench) :
interface melay_intf(input bit clk);
logic o,clk,rst,i;
clocking c1#(posedge clk);
input o;
output i,rst;
endclocking
endinterface
module top;
bit clk;
always
#1 clk = ~clk;
melay_intf i1(clk);
dff d1(.o(i1.o),.clk(i1.clk),.rst(i1.rst),.i(i1.i));
melay_tes(i1.tes);
endmodule
program melay_tes(melay_intf i1);
initial
#100 $finish;
initial
begin
i1.rst <= 0;
#4 i1.rst <= 1;
#4 i1.rst <= 0;
i1.i = 1;
#2 i1.i = 0;
#2 i1.i = 1;
#2 i1.i = 0;
#2 i1.i = 1;
#2 i1.i = 0;
repeat(10)
begin
i1.i = 1;
#2 i1.i = $urandom_range(0,1);
end
end
initial
$monitor("output = %d clk = %d rst = %d i = %d",i1.o,i1.clk,i1.rst,i1.i);
initial
begin
$dumpfile("mem.vcd");
$dumpvars();
end
endprogram
Here important part is interface and in it I used clocking block for synchronization purpose. Here clocking c1#(posedge clk); so all signals which are mention inside the clocking block which are i,o,rst.All this signal change its value at every posedge of clk signal.
Here dff d1(.o(i1.o),.clk(i1.clk),.rst(i1.rst),.i(i1.i)); Important thing that you find in top module I made connection between verilog signals and system verilog signals.
You can find verilog module name is "dff". I took the instance of dff verilog module and made the connection. Here i1.o,i1.clk,i1.rst,i1.i is system verilog signals which are connected to o,clk,rst,i signals of verilog module of with dot convention.

Not understanding types in Verilog

I am trying to make a block for an 8-bit multiplier, and the testbench is giving me a result that basically says that I don't know what I'm doing with my wires and regs. To make this easier to answer, I'm going to display my code, and then the parts that I think are important:
module multiplier_result(
input ADD_cmd,
input LOAD_cmd,
input SHIFT_cmd,
input reset,
input [7:0] B_in,
input [7:0] Add_out,
input cout,
output wire [7:0] RB,
output wire [15:0] RC,
output wire [8:0] temp_reg,
output wire LSB
);
wire [8:0] from_mux;
reg[16:0] balreg;
reg tempadd;
//assign the outputs. all combinational
assign RB = balreg[15:8];
assign RC = balreg[15:0];
assign LSB = balreg[0];
assign temp_reg = balreg[16:8];
mux_9 mux(
.sel(~ADD_cmd),
.Add_out(Add_out),
.cout(cout),
.mux_out(from_mux),
.temp_reg(temp_reg)
);
always # (*) begin
if(reset) begin
balreg[16:0] = 17'd0;
tempadd = 1'b0;
end
else
begin
if(LOAD_cmd)
begin
balreg[16:8] = 9'b000000000;
balreg[7:0] = B_in;
end
if(SHIFT_cmd)
begin
balreg[16:8] = from_mux;
balreg = balreg >> 1;
end
end
end
endmodule
Now, here is what's troubling me:
Here I'm assigning wires to different bits of the balreg register (in black). What is going on in my head (please excuse my paint skills):
But for some reason, LSB gets what it's supposed to, while RB and RC get high impedance. Here is the simulate result, followed by the code I used (just a simple test case)
module multiplier_result_tb(
);
reg ADD_cmd;
reg LOAD_cmd;
reg SHIFT_cmd;
reg reset;
reg [7:0] B_in;
reg [8:0] Add_out;
wire [7:0] RB;
wire [15:0] RC;
wire [8:0] temp_reg; //size 9
wire LSB;
multiplier_result dut(ADD_cmd,LOAD_cmd,SHIFT_cmd,reset,B_in,Add_out,RB,RC,temp_reg,LSB);
initial begin
LOAD_cmd = 0;
#10;
LOAD_cmd = 1;
reset = 0;
B_in = 8'b00001010;
Add_out = 9'd0;
ADD_cmd = 0;
SHIFT_cmd = 0;
end
endmodule
I'm not following these results at all. The balreg register is all set up, so the RB and RC wires MUST be defined, but according to the simulation, they are high impedance.
The only conclusion that I get at, is that I really don't know what's going on with the types (the model I had in my had worked for me so far).
Any help, ideas, tips are much appreciated.
You only connected 10 of the 11 ports of the dut. Didn't you get a warning? You are making connections by position, not by name. You connected RB to input cout. You need to drive cout in your testbench.
Another way to make connections is by name. This is more verbose, but it can make your code clearer:
multiplier_result dut (
// Inputs:
.ADD_cmd (ADD_cmd),
.Add_out (Add_out),
.B_in (B_in),
.LOAD_cmd (LOAD_cmd),
.SHIFT_cmd (SHIFT_cmd),
.cout (cout),
.reset (reset),
// Outputs:
.LSB (LSB),
.RB (RB),
.RC (RC),
.temp_reg (temp_reg)
);

Automatic SystemVerilog variable size using interface width and $size?

I am trying to make a module (a DSP in my case) with a standardized memory interface in SystemVerilog, and would like the variables in the module to size automatically based on the bus widths in the attached interface. My rationale: this makes the code more portable by allowing it to auto-size to any connected interface, instead of requiring an HDL coder to pass in parameters that tell the module the widths of all the interface busses that will connect to it (not that this would be terrible, it just seems cleaner without the parameters).
I can't seem to get this to work, however. Here's an example that illustrates the problem; the following synthesizes in Quartus II 12.1:
// Top level module with some 15-bit ports
module top ( input [14:0] data_in,
output [14:0] data_out1, data_out2,
data_out3, data_out4 );
test_interface my_interface(); // Initialize the interface
test_module my_module(.*); // Initialize & connect module
endmodule
// Define a simple interface:
interface test_interface ();
logic [8:0] my_port;
endinterface
// Define the module:
module test_module ( input [14:0] data_in,
test_interface my_interface,
output [14:0] data_out1, data_out2,
data_out3, data_out4 );
localparam width1 = $size(data_in); // should be 15
localparam width2 = $size(my_interface.my_port); // should be 9
logic [width1-1:0] auto_sized1; // gets correct size (14:0)
logic [width2-1:0] auto_sized2; // **PROBLEM**: gets size of 0:0!
always_comb begin
auto_sized1 = 5; // ok
auto_sized2 = 5; // problem; value now truncated to 1
data_out1 = data_in + width1; // Yields data_in + 15 (ok)
data_out2 = data_in + width2; // Yields data_in + 9 (ok...!)
data_out3 = data_in + auto_sized1; // Yields data_in + 5 (ok)
data_out4 = data_in + auto_sized2; // Yields data_in + 1 (problem)
end
endmodule
Note that width2 does eventually get the correct value (9) - just too late for it to correctly set the width of auto_sized2. I initially thought that $size was simply evaluated after all variables had been assigned their widths, but this doesn't seem to be the case either since $size(data_in) works just fine for setting the width of auto_sized1.
Any thoughts? Again, it's not critical to the project's success, I'm mostly curious at this point!
Thanks -
Looks like a compiler bug. I'd probably use a parameter in the interface definition.
module top ( input [14:0] data_in,
output [14:0] data_out1, data_out2,
data_out3, data_out4 );
test_interface #(.port_size(8)) my_interface(); // Initialize the interface
test_module my_module(.*); // Initialize & connect module
endmodule
interface test_interface ();
parameter port_size = 1;
logic [port_size-1:0] my_port;
endinterface
module test_module ( input [14:0] data_in,
test_interface my_interface,
output [14:0] data_out1, data_out2,
data_out3, data_out4 );
localparam width1 = $size(data_in);
localparam width2 = my_interface.port_size;
endmodule