I am trying to do a 4-bit adder subtractor in Verilog code, but there is some kind of problem in my code that I couldn't figure out. I'm not sure if the testbench or the Verilog is wrong. Can someone please help me with it? Also, when I try to simulate it, it gives Loading Errors.
My Verilog code:
module addsubparameter (A, B, OP, C_out, Sum);
input A,B;
input OP;
output C_out;
output Sum;
wire C_out, Sum;
reg assigning;
always#(OP)
begin
if (OP == 0)
assigning = A + B + OP;
else
assigning = A + (~B + 1) + OP;
end
assign {C_out, Sum} = assigning;
endmodule
module adder (a, b, op, cout, sum);
parameter size = 4 ;
input [3:0] a, b;
output [3:0] sum;
input op;
output cout;
wire [2:0] c;
genvar i;
generate
for (i = 0; i < size; i = i + 1) begin: adder
if (i == 0)
addsubparameter (a[i], b[i], op, sum[i], c[i]);
else if (i == 3)
addsubparameter (a[i], b[i], c[i-1], cout, sum[i]);
else
addsubparameter (a[i], b[i], c[i-1], sum[i], c[i]);
end
endgenerate
endmodule
And this is my testbench:
module addsub_tb();
reg [3:0] a;
reg [3:0] b;
reg op;
wire [3:0] sum;
wire cout;
adder DUT (a,b,op,sum,cout);
initial begin
a = 4'b1010; b = 4'b1100; op = 1'b0; #100;
a = 4'b1111; b = 4'b1011; op = 1'b1; #100;
a = 4'b1010; b = 4'b1010; op = 1'b0; #100;
end
endmodule
Your simulator should generate error and/or warning messages because you have syntax errors. If it does not, sign up for a free account on edaplayground, where you will have access to multiple simulators which will produce helpful messages.
You need to add instance names. For example, I added i0 in the line below:
addsubparameter i0 (a[i], b[i], op, sum[i], c[i]);
You have port connection width mismatches, and these indicate connection errors. This is a common type of error when you use connections by position. You mistakenly connected the sum signal to the cout port, and vice versa. You should use connections by name instead. For example, change:
adder DUT (a,b,op,sum,cout);
to:
adder dut (
.a (a),
.b (b),
.op (op),
.cout (cout),
.sum (sum)
);
Use this coding style for all your instances.
You won't get a simulation warning, but you might get a synthesis warnings about an incomplete sensitivity list. Change:
always#(OP)
to:
always #*
I'm writing an ALU for a processor I'm designing (first RTL project) and I'm getting a high impedance output on ALU_out when I run my testbench, even though the flags do get set and are output correctly.
module alu(
input clk,
input reset,
input [7:0] A, B,
input [3:0] Op_Sel,
output [7:0] ALU_out,
output C, V, N, Z
);
reg [8:0] Result = 0;
reg [8:0] cn_temp = 0;
reg [7:0] v_temp = 0;
reg carry = 0;
reg overflow = 0;
reg negative = 0;
reg zero = 0;
assign ALU_Out = Result[7:0];
assign C = carry;
assign V = overflow;
assign N = negative;
assign Z = zero;
always #*
begin
if (reset)
begin
Result = 0;
cn_temp = 0;
v_temp = 0;
carry = 0;
overflow = 0;
negative = 0;
zero = 0;
end
end
always #(posedge clk)
begin
case(Op_Sel)
4'b0000: // Addition
begin
Result = A + B;
negative = Result[7];
zero = (Result[7:0] == 8'b00000000);
carry = Result[8];
v_temp = A[6:0] + B[6:0];
overflow = v_temp[7] ^ carry;
end
.
.
//The rest of the instructions
.
.
.
endcase
end
endmodule
//My testbench
module alu_testbench();
reg clk;
reg reset;
reg [7:0] A;
reg [7:0] B;
reg [3:0] Op_Sel;
wire [7:0] ALU_out;
wire C, V, N, Z;
always begin
#1
clk = ~clk;
end
initial begin
clk = 0;
reset = 0;
#1
reset = 1;
#1
reset = 0;
end
initial begin
#10
A=2;
B=3;
Op_Sel = 4'b0000;
#10
A=1;
end
alu alu (
.clk(clk),
.A(A),
.B(B),
.Op_Sel(Op_Sel),
.ALU_out(ALU_out),
.C(C),
.V(V),
.N(N),
.Z(Z));
endmodule
I believe I connected up the module to the testbench (through a wire), so why am I getting high impedance on ALU_out?
This was a tricky typo. You mistakenly used an upper-case "O" in the ALU_Out signal name. Since Verilog is case-sensitive, this is a different signal from ALU_out. It is not mandatory to declare all signals in Verilog. However, you can use the following compiler directive in your code to help catch this type of common problem:
`default_nettype none
Your simulator should generate an error.
To fix it, change:
assign ALU_Out = Result[7:0];
to:
assign ALU_out = Result[7:0];
My simulators also generated a warning message because you didn't drive the reset input of alu. Here is the fix:
alu alu (
.clk(clk),
.reset(reset), /// <------ add this
.A(A),
.B(B),
.Op_Sel(Op_Sel),
.ALU_out(ALU_out),
.C(C),
.V(V),
.N(N),
.Z(Z));
I am a beginner and I wanted to write a ripple-carry-adder using the generate block. So I write the following module:
module ripple_carry_adder(ia, ib, ci, so, co);
parameter N = 32;
input[N-1:0] ia;
input[N-1:0] ib;
input ci;
output[N-1:0] so;
output co;
wire [N:0] carry;
assign carry[0] = ci;
genvar j;
generate for(j = 0; j < N; j = j + 1)
begin:r_loop
wire t1, t2, t3;
xor g1(t1, ia[i], ib[j]);
xor g2(so[j], t1, carry[j]);
and g3(t2, ia[i], ib[j]);
and g4(t3, t1, carry[j]);
or g5(carry[j+1], t2, t3);
end
endgenerate
assign co = carry[N];
endmodule
And the testbench module:
`include "ripple_carry_adder.v"
`timescale 1ns/1ps
module ripple_carry_adder_tb;
parameter N = 32;
reg clk;
reg[N-1:0] a, b;
wire[N-1:0] sum;
reg cin;
wire cout;
ripple_carry_adder rca(.ia(a), .ib(b), .ci(cin), .so(sum), .co(cout));
initial begin
#10;
a = 0;
b = 0;
cin = 0;
clk = 0;
#10;
end
always #(posedge clk)
begin
#50;
#1 a <= $random() % 1000000;
#1 b <= $random() % 1000000;
end
always #(a or b)
#5 $display("%d + %d = %d", a, b, sum);
always #5 clk = ~clk;
endmodule
But I got the result with all bits unknown:
result
I have spent 1 hour in vain trying to find the mistake. Can you help me?
As stated in my comment, the i in ia[i] is undefined. Changing it to j should get the desired functionality.
Verilog will treat any undeclared variable as a single bit wire, it is considered normal benavior and you will rarely get warnings. Some simulators have options to flag undeclared variables. There is a univeral option as well that was added in IEEE Std 1364-2001 (aka Verilog-2001). You can override the default net type with the `define_nettype macro. By setting it to none all nets after the macro declaration must be explicitly declared. You can get more details on default_nettype by reading IEEE Std 1364-2001 § 19.2 `default_nettype or IEEE Std 1800-2012 § 22.8 `default_nettype
I have a project, in which I have to implement a list processor that computes the squared-norm of a complex vector.
EDITED:
My code is compiling, and the simulation is working, and I corrected all the connections, so my input signals are reading values. But I am having some trouble with the "start" signal. In the testbench I set it to 0. then to 1 but for some reason it remains 0. Anyone know why a signal would usually stay 0 even though it was assigned to a particula value in the test bench??
I'm still amateurish in verilog, so I'm not sure what I did wrong. I've been tracking every module used, checked if there were errors in instantiating, but I'm missing something, silly or fundamental. I just have no idea what it is.
Here is the code: the total modules are control, memory, datapath, testbench and VNLP (aka the module that computes the squared-norm).
module control (output reg [7:0] counter, output reg add1_sel, add2_sel, before_sel, next_sel, acc_sel, A1_sel, A2_sel, load_before, load_next, load_acc, done_op, input clk, start_op);
wire [9:0] one, zero, before, next;
//reg [7:0] counter;
reg [1 : 0] state, next_state;
parameter Start=0, Compute=1, GetNext=2, Done=3;
reg counter_start, counter_incr;
assign one=before;
assign zero=next;
always#(posedge clk) begin
if (start_op) state<=Start;
else state<=next_state;
end
always#(posedge clk) begin
if (counter_start ==1)
counter<=0;
else if(counter_incr==1)
counter<=counter+1;
end
always#(state, start_op, zero, one) begin
load_acc=0;
next_sel=0;
before_sel=0;
A1_sel=0;
A2_sel=0;
load_next=0;
load_before=0;
done_op=0;
acc_sel=0;
add1_sel=0;
add2_sel=0;
counter_incr=0;
counter_start=0;
case(state)
Start:
begin
next_sel=0;
before_sel=0;
load_next=1;
load_before=1;
acc_sel=0;
load_acc=1;
counter_start=1;
add1_sel=0;
add2_sel=0;
//load_M1=0;
//load_M2=0;
done_op=0;
if (start_op ==0) next_state=Compute;
//else next_state=Start;
end
Compute:
begin
counter_start=0;
next_sel=1;
before_sel=1;
load_next=0;
load_before=0;
A1_sel=1;
A2_sel=1;
add1_sel=1;
add2_sel=1;
//load_M1=1;
//load_M2=1;
load_acc=1;
acc_sel=1;
done_op=0;
if (start_op ==0) next_state=GetNext;
//else next_state=Start;
end
GetNext:
begin
load_next=1;
load_before=1;
A1_sel=0;
A2_sel=0;
load_acc=0;
done_op=0;
if (start_op ==0) begin
if (zero==0 || one==1) next_state= Done;
else if (!start_op && zero!=0 && one!=1) begin next_state=Compute; counter_incr=1; end
end
end
Done:
begin
done_op=1;
load_acc=0; counter_incr=0;
if (start_op ==1) next_state=Start;
//else next_state=Done;
end
default: next_state= Start;
endcase
end
endmodule
module memory (D1, D2, A1, A2);
parameter word_size=10;
parameter address_size=9;
parameter memory_size= 512;
reg [9:0] memory [memory_size-1:0];
output reg [word_size-1:0] D1;
output reg [word_size-1:0] D2;
input [address_size-1:0] A1;
input [address_size-1:0] A2;
always#(*) begin
D1=memory[A1];
D2=memory[A2];
end
endmodule
module VNLP (
output reg[27: 0] norm2, output reg[7:0] len, output reg Done, input reg done_op, output reg [8:0] A1, A2, input [7:0] counter,
input [9:0] D1, D2, output reg [9:0] Next, Before, output reg [27:0] Accumulator,
input add1_sel, add2_sel, before_sel, next_sel, acc_sel, A1_sel, A2_sel, load_before, load_next, load_acc,clk, start_op);
reg [19:0] adder1, adder2;
wire [20:0] sum_add;
reg [27:0] acc;
reg [9:0] before, next;
reg [8:0] a1, a2;
reg [19:0] d1, d2;
//assign d1= D1*D1;
//assign d2=D2*D2;
assign sum_add= adder1 + adder2;
always#(*) begin
if (add2_sel) begin adder2=D2*D2; end
else adder2=20'b0;
if (add1_sel) adder1=D1*D1;
else adder1=20'b0;
if (before_sel) before=D2;
else before=10'b0;
if (next_sel) next=D1;
else next=10'b0;
if (acc_sel) acc=sum_add+ Accumulator;
else acc=28'b0;
if (A1_sel) A1<=Next+ 2'b10;
else A1<=Next;
if (A2_sel) A2<=Before+ 2'b10;
else A2<=Before;
if (done_op) begin
norm2<= Accumulator;
len=counter;
Done=1;
end
else begin
norm2<=28'b0;
len<=8'b0;
Done<=0;
end
end
always#(posedge clk) begin
if (load_before) Before<= before;
end
always#(posedge clk) begin
if (load_next) Next<= next;
end
always#(posedge clk) begin
if (load_acc) Accumulator<= acc;
end
endmodule
module Datapath (
input start_op, clk,
output Done,
output [7:0] len,
output [27:0] norm2);
wire [8:0] A1, A2;
wire [9:0] D1, D2;
wire done_op;
wire [7:0] counter;
wire [9:0] Next, Before;
wire [27:0] Accumulator;
wire add1_sel, add2_sel, before_sel, next_sel, acc_sel, A1_sel, A2_sel, load_before, load_next, load_acc;
VNLP VNLP(norm2, len, Done, done_op, A1, A2, counter, D1, D2, Next, Before,Accumulator,
add1_sel, add2_sel, before_sel, next_sel, acc_sel, A1_sel, A2_sel,
load_before, load_next, load_acc,clk, start_op);
memory M1 (D1, D2, A1, A2);
control control (counter,add1_sel, add2_sel, before_sel, next_sel, acc_sel, A1_sel, A2_sel, load_before, load_next, load_acc, done_op, clk, start_op);
endmodule
module Datapath_tb;
reg start_op, clk;
wire Done;
wire [7:0] len;
wire [27:0] norm2;
reg[8:0] k;
wire[9:0] word0,word1,word2,word3,
word4,word5,word6,word7,
word8,word9,word10,word11,
word12,word13,word14,word15,
word16,word17,word18,word19,
word20, word21,word22,word23,
word24,word25,word26,word27,
word28,word29,word30,word31,
word32, word33,word34,word35,
word36,word37,word38,word39;
Datapath Datapath (
start_op, clk,
Done,
len,
norm2);
assign word0 = Datapath.M1.memory[0];
assign word1 = Datapath.M1.memory[1];
assign word2 = Datapath.M1.memory[2];
assign word3 = Datapath.M1.memory[3];
assign word4 = Datapath.M1.memory[5];
assign word5 = Datapath.M1.memory[6];
assign word6 = Datapath.M1.memory[7];
assign word7 = Datapath.M1.memory[8];
assign word8 = Datapath.M1.memory[11];
assign word9 = Datapath.M1.memory[12];
assign word10 = Datapath.M1.memory[13];
assign word11 = Datapath.M1.memory[14];
assign word12 = Datapath.M1.memory[17];
assign word13 = Datapath.M1.memory[18];
assign word14 = Datapath.M1.memory[19];
assign word15 = Datapath.M1.memory[20];
assign word16 = Datapath.M1.memory[22];
assign word17 = Datapath.M1.memory[23];
assign word18 = Datapath.M1.memory[24];
assign word19 = Datapath.M1.memory[25];
assign word20 = Datapath.M1.memory[28];
assign word21 = Datapath.M1.memory[29];
assign word22 = Datapath.M1.memory[30];
assign word23 = Datapath.M1.memory[31];
assign word24 = Datapath.M1.memory[33];
assign word25 = Datapath.M1.memory[34];
assign word26 = Datapath.M1.memory[35];
assign word27 = Datapath.M1.memory[36];
assign word28 = Datapath.M1.memory[39];
assign word29 = Datapath.M1.memory[40];
assign word30 = Datapath.M1.memory[41];
assign word31 = Datapath.M1.memory[42];
assign word32 = Datapath.M1.memory[44];
assign word33 = Datapath.M1.memory[45];
assign word34 = Datapath.M1.memory[46];
assign word35 = Datapath.M1.memory[47];
assign word36 = Datapath.M1.memory[49];
assign word37 = Datapath.M1.memory[50];
assign word38 = Datapath.M1.memory[51];
assign word39 = Datapath.M1.memory[52];
//VNLP VNLP(norm2, len, done, A1, A2, counter, D1, D2, Next, Before,Accumulator, add1_sel, add2_sel, before_sel, next_sel, acc_sel, A1_sel, A2_sel, load_before, load_next, load_acc,clk, start);
//Flush memory
initial
begin: Flush
start_op=0; clk=0;
for (k=0; k<=52; k=k+1) Datapath.M1.memory[k] = 0;
end
initial
begin: Load
#5
#5 start_op=1; #5 start_op=0;
Datapath.M1.memory[0] = 49;
Datapath.M1.memory[1] = 34;
Datapath.M1.memory[2] = -33;
Datapath.M1.memory[3] = 23;
Datapath.M1.memory[5] = 17 ;
Datapath.M1.memory[6]=40;
Datapath.M1.memory[7] = 19;
Datapath.M1.memory[8]=102;
Datapath.M1.memory[11] = 22;
Datapath.M1.memory[12]=18;
Datapath.M1.memory[13] = 25;
Datapath.M1.memory[14] = -93;
Datapath.M1.memory[17]=11;
Datapath.M1.memory[18] = 6;
Datapath.M1.memory[19] = 8 ;
Datapath.M1.memory[20]=90;
Datapath.M1.memory[22] = 33;
Datapath.M1.memory[23] = 12;
Datapath.M1.memory[24] = 31;
Datapath.M1.memory[25] = 32;
Datapath.M1.memory[28] = 102;
Datapath.M1.memory[29] = 240;
Datapath.M1.memory[30]=47;
Datapath.M1.memory[31] = -11;
Datapath.M1.memory[33] = 0;
Datapath.M1.memory[34]=23;
Datapath.M1.memory[35] = 25;
Datapath.M1.memory[36] = 88;
Datapath.M1.memory[39]=5;
Datapath.M1.memory[40] = 50;
Datapath.M1.memory[41] = 56;
Datapath.M1.memory[42] = 48;
Datapath.M1.memory[44] = 56;
Datapath.M1.memory[45] = 88;
Datapath.M1.memory[46] = 112;
Datapath.M1.memory[47] = 69;
Datapath.M1.memory[49] = 39;
Datapath.M1.memory[50] = 1;
Datapath.M1.memory[51] = 101;
Datapath.M1.memory[52] = 63;
end
always forever #5 clk=~clk;
endmodule
And this is an idea of the architecture if that helps:
Architecture Schematic for processor
Usually you get Z's on inputs because you have not connected up things correctly. Check your inputs for missing connections or typos before trying to diagnose the outputs.
It seems that you are not connecting the control module in the top level (datapath module of your code). There are initiations of VNLP and memory modules but not the control module. You have assigned the same names to inputs of the VNLP and the outputs of control module, however this does not ensure that they are connected. Thus, control module is not used in your design and this is probably the reason why the inputs and outputs are not working.
I've designed a unit for my homework here,
module homework1(a, b, sel, y);
input signed [7:0] a, b;
input [1:0] sel;
output reg signed [7:0] y;
always #(a or b or sel) begin
case (sel)
2'b00: y = a + b;
2'b01: y = a - b;
2'b10: y = (a > b) ? a : b;
2'b11: y = (a > b) ? b : a;
endcase
end
endmodule
I've designed a pretty simple testbench file to run with Modelsim here,
module testbench();
reg signed [7:0] a, b;
reg [1:0] sel;
wire signed [7:0] y;
homework1 target(a, b, sel, y);
initial begin
$display("Hello!");
$monitor($time, "a = %d, b = %d, sel = %b, y = %d", a, b, sel, y);
#10 sel = 0; a = 32; b = 25;
#10 a = 46; b = 0;
#10 a = 18; b = 52;
#10 a = 37; b = 37;
#10 a = 37; b = 37;
#10 $stop;
end
endmodule
I used Modelsim to run the test bench, and while the waveform came out as expected, but not the text output. Any ideas?
It seems to work in older version of Modelsim. I'm using 10.3d now. Any settings that might cause this?
Try running your simulations with the -displaymsgmode=both optional argument. The messages may be hidden from your transcript because displaymsgmode is set to wlf.
See the modelsim manual on page 581 for more information.