The output waveform shows no change in the sum, dif, burrow, and out. Even after increasing delay time, still the output shows no change. This should work like the mod adder like add 10 and 2 and with mod 3 give output zero.
CODE
module Mod_adder(a,b,p,out);
input [3:0] a;
input [3:0] b;
input [3:0] p;
output [3:0] out;
wire [3:0] sum;
wire cout;
wire burrow;
wire [3:0] dif;
ripple_carry_adder r1(a,b,sum,cout,1'b0);
ripple_carry_adder r2(sum,~p,dif,burrow,1'b1);
repeat_sum rs1(dif,burrow,sum);
outval o1(sum,burrow,out);
endmodule
module full_adder(in0, in1, cin, out, cout);
input in0, in1, cin;
output out, cout;
assign out = in0 ^ in1 ^ cin;
assign cout = ((in0 ^ in1) & cin) | (in0 & in1);
endmodule
module ripple_carry_adder(in0, in1, out, cout,cin);
input [3:0] in0;
input [3:0] in1;
output [3:0] out;
output cout;
input cin;
wire c1, c2, c3;
full_adder fa0(in0[0], in1[0], cin, out[0], c1);
full_adder fa1(in0[1], in1[1], c1, out[1], c2);
full_adder fa2(in0[2], in1[2], c2, out[2], c3);
full_adder fa3(in0[3], in1[3], c3, out[3], cout);
endmodule
module repeat_sum(dif,burrow,sum);
input [3:0] dif;
input burrow;
output [3:0] sum;
assign sum = (burrow == 1'b0) ? dif:sum;
endmodule
module outval(sum,burrow,out);
input [3:0] sum;
input burrow;
output [3:0] out;
assign out = (burrow == 1'b1) ? sum:out;
endmodule
TEST BENCH
` include "MOD_ADDER.V"
module Mod_adder_tb;
reg [3:0] a;
reg [3:0] b;
reg [3:0] p;
wire [3:0] out; // wires
// Instantiate the module to be tested
Mod_adder MA1(a,b,p,out);
initial begin // initial block
$dumpfile("Test_Full_Adder.vcd");
$dumpvars(1, MA1);
a=4'b1010;
b=4'b0100;
p=4'b0011;
#100;
end // end of initial block
endmodule
I see 2 major problems.
Your out testbench signal is unknown (X) because of driver contention. For example, the sum signal in Mod_adder has multiple drivers: from the r1 instance and from the rs1 instance. The out output of r1 and the sum output of rs1 are both driving the sum wire. You should not drive the same signal from 2 different module instances. You could rename one of the sum signals to something unique, like sum_rs1 and declare a new wire.
wire [3:0] sum, sum_rs1;
Also, you have combinational feed back loops. For example:
assign out = (burrow == 1'b1) ? sum:out;
The out signal should not be on both the LHS and RHS of a continuous assignment.
I am building a shift-unit that is capable of arithmetic and logical right shift, and logical left shift depending on the control signals given to it. However, the arithmetic right shift operator output generates output similar to that logical right shift operator, i.e. sign extension does not occur.
Main code
`timescale 1ns / 1ps
module shift_unit(
input [15:0] a,
input [3:0] b,
input clk,
input isLSL,
input isLSR,
input isASR,
output reg [15:0] result
);
wire [15:0] LSL_result, LSR_result, ASR_result;
LSL lsl(a, b, clk, isLSL, LSL_result);
LSR lsr(a, b, clk, isLSR, LSR_result);
ASR asr(a, b, clk, isASR, ASR_result);
always#(posedge clk) begin
case({isLSL, isLSR, isASR})
3'b001: result <= ASR_result;
3'b010: result <= LSR_result;
3'b100: result <= LSL_result;
endcase
end
endmodule
LSL code:
`timescale 1ns / 1ps
module LSL(
input [15:0] a,
input [3:0] b,
input clk,
input isLSL,
output [15:0] out
);
reg [15:0] result;
always#(posedge clk) begin
if(isLSL) result = a << b;
end
assign out = result;
endmodule
LSR code:
`timescale 1ns / 1ps
module LSR(
input [15:0] a,
input [3:0] b,
input clk,
input isLSR,
output [15:0] out
);
reg [15:0] result;
always#(posedge clk) begin
if(isLSR) result = a >> b;
end
assign out = result;
endmodule
ASR code:
`timescale 1ns / 1ps
module ASR(
input [15:0] a,
input [3:0] b,
input clk,
input isASR,
output [15:0] out
);
reg [15:0] result;
always#(posedge clk) begin
if(isASR) result = a >>> b;
end
assign out = result;
endmodule
And finally, the testbench:
`timescale 1ns / 1ps
module shift_unit_test;
reg [15:0] a;
reg [3:0] b;
reg clk;
reg isLSL;
reg isLSR;
reg isASR;
wire [15:0] result;
shift_unit uut (
.a(a),
.b(b),
.clk(clk),
.isLSL(isLSL),
.isLSR(isLSR),
.isASR(isASR),
.result(result)
);
always #5 clk = ~clk;
initial begin
clk = 1'b0;
a = 16'b1100101011001010;
b = 4;
{isLSL, isLSR, isASR} = 3'b100; #100;
{isLSL, isLSR, isASR} = 3'b010; #100;
{isLSL, isLSR, isASR} = 3'b001; #100;
end
endmodule
The above code has been modelled using Xilinx ISE 14.7.
Any help would be greatly appreciated.
You need to be working with signed signals to get sign extension.
module ASR(
input wire signed [15:0] a,
input [3:0] b,
input clk,
input isASR,
output reg signed [15:0] out
);
always#(posedge clk) begin
if(isASR) out = a >>> b;
end
endmodule
`timescale 100ns/1ps
module CarryLAS_tb;
reg [7:0] a;
reg [7:0] b;
reg ci;
wire [7:0] sum;
wire of; //overflow
wire co;
integer i;
CarryLAS_8 CLA(a,b,ci,sum,co,of);
initial begin
a=0;
b=0;
ci=0;
end
initial begin // all possible cases
for(i=0; i<262144; i=i+1) // 2^18
#10 {a, b, ci} = i;
end
endmodule
module CarryLAS_8(a,b,ci,sum,co,of);
input [7:0] a,b;
input ci; // 0; Add 1: Subtract
output [7:0] sum;
output co;
output of;
wire[7:0] c;
wire[7:0] xb;
xor(xb[0],b[0],ci);
xor(xb[1],b[1],ci);
xor(xb[2],b[2],ci);
xor(xb[3],b[3],ci);
xor(xb[4],b[4],ci);
xor(xb[5],b[5],ci);
xor(xb[6],b[6],ci);
xor(xb[7],b[7],ci);
xor(of,c[7],c[6]);
xor(co,c[7],ci);
CarryLA_8 CLAS(a,xb,ci,sum,co);
endmodule
module CarryLA_8(a,b,ci,sum,co);
input [7:0] a,b;
input ci;
output [7:0] sum;
output co;
wire [7:0] sum;
wire cm,co;
CarryLA_4 CLA0(a[3:0],b[3:0],ci,sum[3:0],cm);
CarryLA_4 CLA1(a[7:4],b[7:4],cm,sum[7:4],cm);
endmodule
module CarryLA_4(a,b,ci,sum,co);
input [3:0] a,b;
input ci; // 0; Add 1: Subtract
output [3:0] sum;
output co;
wire[3:0] g,p,cout;
wire G0,P0;
wire[9:0] w;
and a0(g[0],a[0],b[0]);
and a1(g[1],a[1],b[1]);
and a2(g[2],a[2],b[2]);
and a3(g[3],a[3],b[3]);
xor x0(p[0],a[0],b[0]);
xor x1(p[1],a[1],b[1]);
xor x2(p[2],a[2],b[2]);
xor x3(p[3],a[3],b[3]);
and and0(w[0],p[0],ci);
or or0(cout[0],g[0],w[0]);
and and1(w[1],p[1],p[0],ci);
and and2(w[2],p[1],g[0]);
or or1(cout[1],g[1],w[2],w[1]);
and and3(w[3],p[2],p[1],p[0],ci);
and and4(w[4],p[2],p[1],g[0]);
and and5(w[5],p[2],g[1]);
or or2(cout[2],g[2],w[5],w[4],w[3]);
and and6(w[6],p[3],p[2],p[1],g[0]);
and and7(w[7],p[3],p[2],g[1]);
and and8(g[2],a[2],b[2]);
or or3(G0,g[3],w[8],w[7],w[6]);
and and9(P0,p[3],p[2],p[1],p[0]);
and and10(w[9],P0,ci);
or or4(cout[3],G0,w[9]);
and and11(co,cout[3],1);
xor xor0(sum[0],p[0],ci);
xor xor1(sum[1],p[1],cout[0]);
xor xor2(sum[2],p[2],cout[1]);
xor xor3(sum[3],p[3],cout[2]);
endmodule
This is my Verilog code. simulated well, but the result kinda sucks.
'sum' produces values with some Xs, and 'co', 'of'(overflow detection) are also Xs. I couldn't find out what the problem is. It might be about carry I think.
Could anyone help me with this?
Any help would be really appreciated.
Thanks in advance.
Captured waveform is attached
enter image description here
enter image description here
You have multiple drivers on wire [8:0] c. In your generate you have:
or o1 (c[i+1],g[i],q[i]);
and then you have the FullAdder instances that drive c:
FullAdder a0(a[0],b[0],ci,sum[0],c[0]);
I can't be certain that this is the reason that it won't simulate, but it certainly will make it not function correctly.
you should change "initial" part of your testbench like this:
initial
begin
assign ci =0;
assign a=8'b00000001;
assign b=8'b00000001;
#20
assign a=8'b00010010;
assign b=8'b00110111;
#20
assign a=8'b01011100;
assign b=8'b10010001;
#20
$finish;
and little wrong in module CarryLA_4 :
module CarryLA_4(a,b,ci,sum,co);
input [3:0] a,b;
input ci;
output [3:0] sum;
output co;
wire[3:0] g,p,cout;
wire G0,P0;
wire[9:0] w;
and a0(g[0],a[0],b[0]);
and a1(g[1],a[1],b[1]);
and a2(g[2],a[2],b[2]);
and a3(g[3],a[3],b[3]);
xor x0(p[0],a[0],b[0]);
xor x1(p[1],a[1],b[1]);
xor x2(p[2],a[2],b[2]);
xor x3(p[3],a[3],b[3]);
and and0(w[0],p[0],ci);
or or0(cout[0],g[0],w[0]);
and and1(w[1],p[1],p[0],ci);
and and2(w[2],p[1],g[0]);
or or1(cout[1],g[1],w[2],w[1]);
and and3(w[3],p[2],p[1],p[0],ci);
and and4(w[4],p[2],p[1],g[0]);
and and5(w[5],p[2],g[1]);
or or2(cout[2],g[2],w[5],w[4],w[3]);
and and6(w[6],p[3],p[2],p[1],g[0]);
and and7(w[7],p[3],p[2],g[1]);
and and8(w[8],p[3],p[2],p[1],p[0],ci);
and and9(w[9],p[3],g[2]);
or or3(cout[3],g[3],w[9],w[8],w[7],w[6]);
and and10(co,cout[3],1);
xor xor0(sum[0],p[0],ci);
xor xor1(sum[1],p[1],cout[0]);
xor xor2(sum[2],p[2],cout[1]);
xor xor3(sum[3],p[3],cout[2]);
endmodule
module DIGITADD(
input [3:0] A,
input [3:0] B,
input CIN,
output COUT,
output [3:0] SUM
);
reg [4:0] s2;
assign SUM = s2[3:0];
assign COUT = s2[4];
//BCD ADDER PART
always # ( * )
begin
s2 = A + B + CIN;
if (s2 > 9)
begin
s2 = s2 + 6;
end
end
endmodule
TEST BENCH
module DIGITADD_tb(
reg [3:0] A,
reg [3:0] B,
reg CIN,
wire COUT,
wire [3:0] SUM);
DIGITADD uut(
.A(A),
.B(B),
.CIN(CIN),
.COUT(COUT),
.SUM(SUM));
initial begin
$dumpfile("dump.vcd");
$dumpvars(1,DIGITADD_tb);
#10;
#10 A=4'b0000;B=4'b0011;CIN=1'b0;
#10 A=4'b0111;B=4'b1000;CIN=1'b1;
$finish;
end
endmodule
You have added local variables in your testbench in the style of a port list:
module DIGITADD_tb(
reg [3:0] A,
reg [3:0] B,
reg CIN,
wire COUT,
wire [3:0] SUM);
Should be:
module DIGITADD_tb(); //<-- no ports
reg [3:0] A; //<-- semicolon
reg [3:0] B;
reg CIN;
wire COUT;
wire [3:0] SUM;