I would like to design a 4-bit comparator as a structural model using a 2-bit comparator.
As shown in the attached picture, after giving initial values to each of Gt_I, Eq_I, and Lt_I, you need to design a 4-bit comparator as a structural model of a 2-bit comparator.
The code I've tried is a syntax error in assigning the initial values of Gt_I, Eq_I, and Lt_I. I want to know a solution.
<2bit>
module Comparator_new(a, b, Gt_I, Eq_I, Lt_I, Gt_O, Eq_O, Lt_O);
input [1:0] a;
input [1:0] b;
input Gt_I, Eq_I, Lt_I;
output Gt_O, Eq_O, Lt_O;
assign Gt_O = ~(a[1] & ~b[1] | ~a[1] & b[1]) & a[0] & ~b[0] | a[1] & ~b[1];
assign Eq_O = ~(a[0] & ~b[0] | ~a[0] & b[0]) & ~(a[1] & ~b[1] | ~a[1] & b[1]);
assign Lt_O = ~(a[1] & ~b[1] | ~a[1] & b[1]) & ~a[0] & b[0] | ~a[1] & b[1];
endmodule
<4bit>
module Comparator_stru(a, b, Gt_I, Eq_I, Lt_I, Gt, Eq, Lt);
input [3:0] a;
input [3:0] b;
input Gt_I = 2'b00;
input Eq_I = 2'b01;
input Lt_I = 2'b00;
output Gt, Eq, Lt;
wire x, y, z;
Comparator_new c0(.a(a), .b(b), .Gt_I(Gt_I), .Eq_I(Eq_I), .Lt_I(Lt_I), .Gt_O(x), .Eq_O(y), .Lt_O(z));
Comparator_new c1(.a(a), .b(b), .Gt_I(x), .Eq_I(y), .Lt_I(z), .Gt_O(Gt), .Eq_O(Eq), .Lt_O(Lt));
assign Gt_O = ~(a[3] & ~b[3] | ~a[3] & b[3]) & a[2] & ~b[2] | a[3] & ~b[3];
assign Eq_O = ~(a[2] & ~b[2] | ~a[2] & b[2]) & ~(a[3] & ~b[3] | ~a[3] & b[3]);
assign Lt_O = ~(a[3] & ~b[3] | ~a[3] & b[3]) & ~a[2] & b[2] | ~a[3] & b[3];
endmodule
`timescale 1ns/10ps
module tb_Comparator_stru;
reg a, b;
wire Gt, Eq, Lt;
Comparator_stru tb(.a(a), .b(b), .Gt(Gt), .Eq(Eq), .Lt(Lt));
initial
begin
$dumpfile("test_Comparator_stru_out.vcd");
$dumpvars(-1, tb);
$monitor("%b", Gt);
$monitor("%b", Eq);
$monitor("%b", Lt);
end
initial
begin
a = 2'b00; b = 2'b00;
#50 a = 2'b01; b = 2'b00;
#50 a = 2'b01; b = 2'b01;
#50 a = 2'b01; b = 2'b10;
#50 a = 2'b10; b = 2'b10;
#50 a = 2'b11; b = 2'b10;
#50 a = 2'b11; b = 2'b11;
#50;
end
endmodule
Gt_I, Eq_I, and Lt_I are input ports of module Comparator_stru. They are driven by, and receive values from their drivers.
In your case, if you want to assign initial values to them, you need to use initial block, and do it in the testbench.
<4bit>
module Comparator_stru(a, b, Gt_I, Eq_I, Lt_I, Gt, Eq, Lt);
input [3:0] a;
input [3:0] b;
input Gt_I; // = 2'b00;
input Eq_I; // = 2'b01;
input Lt_I; // = 2'b00;
testbench
Comparator_stru tb(.a(a), .b(b), .Gt_I(Gt_I), .Eq_I(Eq_I), .Lt_I(Lt_I), .Gt(Gt), .Eq(Eq), .Lt(Lt));
initial begin
Gt_I = 1'b0;
Eq_I = 1'b1;
Lt_I = 1'b0;
end
module Comparator_stru() will have assign variables as Gt, Lt, Eq instead of Gt_O, Lt_O, Eq_O as this module is not having Gt_O, Lt_O, Eq_O as outputs.
Related
I want to make a serial comparator using a dff with async reset base on with continuous assignment. but output will come in unknown (x) state I don't know why. I checked every wire and assigned each of them an expression
dff code (verilog):
module comparator (input a, input b, input reset, input clk, output [1:0] o);
wire q0_p, q0_n, q1_p, q1_n, d0, d1;
wire s0, r0, w01, w02, s1, r1, w11, w12;
assign d0 = (q1_n & q0_p) | (q0_p & ~a & b) | (q1_n & ~a & b);
assign d1 = (q1_p & q0_n) | (q0_n & a & ~b) | (q1_p & a & ~b);
assign w01 = ~(w02 & s0);
assign s0 = ~(w01 & reset & clk);
assign r0 = ~(s0 & clk & w02);
assign w02 = ~(r0 & d0 & reset);
assign q0_p = ~(s0 & q0_n);
assign q0_n = ~(q0_p & r0 & reset);
assign w11 = ~(w12 & s1);
assign s1 = ~(w11 & reset & clk);
assign r1 = ~(s1 & clk & w12);
assign w12 = ~(r1 & d1 & reset);
assign q1_p = ~(s1 & q1_n);
assign q1_n = ~(q1_p & r1 & reset);
assign o[0] = q0_p;
assign o[1] = q1_p;
endmodule
testbench:
module test();
reg a, b, reset, clk = 0;
wire [1:0] o;
comparator cmp(a, b, reset, clk, o);
always #1 clk <= ~clk;
initial begin
$monitor("%b %b %b", a, b, o);
reset = 0;
reset = 1;
// a = 1110, b = 1011
#1 a = 1; b = 1;
#1 a = 1; b = 0;
#1 a = 1; b = 1;
#1 a = 0; b = 1;
$finish();
end
endmodule
output:
1 1 xx
1 0 xx
1 1 xx
0 1 xx
if 'D' is in 'x' state, as soon as you deassert reset, the outputs will become 'x' again. You need to set a known value to 'D' before deassert. Also, you need a delay between assert and deassert of reset.
For example,
initial begin
$monitor("%b %b %b", a, b, o);
reset = 0;
#1
a = 0; b = 0;
reset = 1;
...
As you can see, it is non-trivial to debug simulation problems when trying to model a logic circuit with feedback at the gate level. You get unknowns (x) because you do not correctly initialize all the signals which need to be initialized.
Your testbench does not really drive the reset signal to 0 because you immediately drive it to 1 (both happen at time 0). You should add a delay between the 2 values. However, that will still be insufficient to initialize all the signals.
The solution is to use the appropriate model for your logic: behavioral level. This is trivial in Verilog. The common way to model a dff with an asynchronous active-low reset is:
always #(posedge clk or negedge nreset) begin
if (!nreset) begin
q <= 1'b0;
end else begin
q <= d;
end
end
The beauty of digital design and Verilog is that you can abstract away all the unnecessary details. The code above eliminates all the issues with properly initializing all your signals.
Using Verilog, I want to make 4by4 multiplier, but there is one error:
vlog-2110) Illegal reference to net array "w11".
about other variables w12, o1..... there is also error...
I cannot understand the meaning of the error. If you can solve this error, please tell me.
module half_adder (x,y,s,c);
input x,y;
output s,c;
assign s=x^y;
assign c=x&y;
endmodule
module full_adder (x,y,z,s,c);
input x,y,z;
output s,c;
wire w1,w2,w3;
half_adder h1(x,y,w1,w2);
half_adder h2(w1,z,s,w3);
assign c = w2|w3;
endmodule
module four_bit_adder (a, b, c0, s, c4);
input [3:0]a;
input [3:0]b;
input c0;
output [3:0]s;
output c4;
wire c1,c2,c3;
full_adder fu1(a[0],b[0],c0,s[0],c1);
full_adder fu2(a[1],b[1],c1,s[1],c2);
full_adder fu3(a[2],b[2],c2,s[2],c3);
full_adder fu4(a[3],b[3],c3,s[3],c4);
endmodule
maybe there is error next code
// 4by4_multiplier
module four_four_multi (A,B, zero, C);
input [3:0]A;
input [3:0]B;
input zero;
output [7:0]C;
wire w11[3:0];
wire w12[3:0];
wire o1[3:0];
wire w21[3:0];
wire w22[3:0];
wire o2[3:0];
wire w31[3:0];
wire w32[3:0];
wire o3[3:0];
wire o4;
assign C[0] = A[0] & B[0];
assign w11[0] = A[0] & B[1];
assign w11[1] = A[0] & B[2];
assign w11[2] = A[0] & B[3];
assign w11[3] = 0;
assign w12[0] = A[1] & B[0];
assign w12[1] = A[1] & B[1];
assign w12[2] = A[1] & B[2];
assign w12[3] = A[1] & B[3];
four_bit_adder four1(w11, w12, zero, o1 ,w21[3] );
assign C[1] = o1[0];
assign w21[0] = o1[1];
assign w21[1] = o1[2];
assign w21[2] = o1[3];
assign w22[0] = A[2] & B[0];
assign w22[1] = A[2] & B[1];
assign w22[2] = A[2] & B[2];
assign w22[3] = A[2] & B[3];
four_bit_adder four2(w21, w22, zero, o2 ,w31[3] );
assign C[2] = o2[0];
assign w31[0] = o2[1];
assign w31[1] = o2[2];
assign w31[2] = o2[3];
four_bit_adder four3(w31, w32, zero, o3 , o4 );
assign C[3] = o3[0];
assign C[4] = o3[1];
assign C[5] = o3[2];
assign C[6] = o3[3];
endmodule
The following declaration declares nets w11, w12, ... as arrays of nets.
wire w11[3:0];
wire w12[3:0];
...
The verilog standard allows you to declare them but does not allow using them as whole array in ports. To fix it in verilog you need to declare those nets as vectors:
wire [3:0] w11;
wire [3:0] w12;
...
System Verilog relaxed this rule and it should work in that language as is.
I'm attempting to run a behavioral simulation on my Verilog code in Vivado. However, after the simulation runs, instead of getting outputs, they are shown as red lines with XX, which I believe means they are undefined.
I've attempted to change the timescale at the top of the Verilog files, as shown in Xilinx forum post, but this did not fix my issue.
Here is my Verilog program:
module ctrl(
input clk,
input [5:0] A,
input [5:0] B,
input [3:0] C,
output reg [6:0] led
);
always #(posedge clk)
begin
case(C)
4'b0000:
//A + B
led <= A + B;
4'b0001:
//A - B
led <= A - B;
4'b0010:
//A++
led <= A + 1'b1;
4'b0011:
//A--
led <= A - 1'b1;
4'b0100:
//B++
led <= B + 1'b1;
4'b0101:
//B--
led <= B - 1'b1;
4'b0110:
//A & B
led = (A & B);
4'b0111:
//A | B
led = (A | B);
4'b1000:
//A ^ B
led = (A ^ B);
4'b1001:
//~A
led = {1'b0,~A[5:0]
4'b1010:
//~B
led = {1'b0,~B[5:0]};
4'b1011:
//A << B
led = A << B;
4'b1100:
//B << A
led = B << A;
4'b1101:
//Light LED[0] if A > B
if(A > B)
led = 7'b0000001;
else
led = 7'b0000000;
4'b1110:
//Light LED[0] if A < B
if(A < B)
led = 7'b00000001;
else
led = 7'b0000000;
4'b1111:
//Light LED[0] if A=B
if(A == B)
led = 7'b0000001;
else
led = 7'b0000000;
default:
//Unimplemented opcode
led <= 7'b1111111;
endcase
end
endmodule
The testbench
module ctrl_testbench();
reg[5:0] A;
reg[5:0] B;
reg[3:0] C;
wire[6:0] led;
ctrl dut (
.A(A),
.B(B),
.C(C),
.led(led)
);
initial begin
A = 6'b000001;
B = 6'b000001;
C = 4'b0000;
#100;
A = 6'b000000;
B = 6'b000000;
C = 4'b0000;
#100;
A = 6'b000010;
B = 6'b000010;
C = 4'b0001;
end
endmodule
The timing diagram then gives this after the behavioral simulation is run. As you can see A-C (The inputs) are populated correctly, however LED (the output) is red and shows XX.
I'm trying to show the actual outputs.
You need to create a clock signal and drive the clk input of your DUT:
module ctrl_testbench();
reg[5:0] A;
reg[5:0] B;
reg[3:0] C;
wire[6:0] led;
reg clk;
initial begin
clk = 0;
forever #5 clk = ~clk;
end
ctrl dut (
.clk(clk),
.A(A),
.B(B),
.C(C),
.led(led)
);
initial begin
A = 6'b000001;
B = 6'b000001;
C = 4'b0000;
#100;
A = 6'b000000;
B = 6'b000000;
C = 4'b0000;
#100;
A = 6'b000010;
B = 6'b000010;
C = 4'b0001;
$finish;
end
endmodule
It was convenient for me to create 2 initial blocks. The first never ends due to forever, and the second is necessary to end the simulation with $finish. It is common to separate out distinct functionality using multiple initial blocks.
I'm not really experienced with Verilog. I'm trying to make an RCA using a for loop but I'm getting an error when trying to synthesize the modules.
The error I'm getting is
procedural assignment to a non-register i is not permitted
//1-bit full adder
module fadder (s, cout, a, b, cin);
input a, b, cin;
output s, cout;
assign s = (a ^ b) ^ cin;
assign cout = ((a & b) | ((a | b) & cin));
endmodule
//RCA Logic
module part1(s, cout, a, b, cin, clk);
parameter BIT_WIDTH = 128;
input [BIT_WIDTH-1:0] a, b;
input cin;
input clk;
output cout;
output [BIT_WIDTH-1:0] s;
wire [BIT_WIDTH:0] cin_wire;
assign cin_wire[0] = cin;
genvar i;
generate
always#(posedge clk)
begin
for(i = 0; i <= BIT_WIDTH-1; i = i + 1) //error is on this line
begin:
fadder fadder_inst (.s(s[i]), .cout(cin_wire[i+1]), .a(a[i]), .b(b[i]), .cin(cin_wire[i]));
end
end
endgenerate
assign cout = cin_wire[BIT_WIDTH];
endmodule
Any help is appreciated. Thanks
generate
for(i = 0; i <= BIT_WIDTH-1; i = i + 1)
begin
fadder fadder_inst (.s(s[i]), .cout(cin_wire[i+1]), .a(a[i]), .b(b[i]), .cin(cin_wire[i]));
end
endgenerate
You can not generate the modules inside always block.
You have to seperately manipulate input inside always block before connecting to fadder_inst.
What I guess is, RCA is not clock dependent. Its purly asynchronous circuit.
You cannot instantiate a module inside a procedural block (initial,
always, always_comb, always_ff, always_latch, final, task, function).
You can do like following to serve your purpose.
module fadder (clk, s, cout, a, b, cin);
input a, b, cin, clk;
output reg s, cout;
always # (posedge clk)
begin
s = (a ^ b) ^ cin;
cout = ((a & b) | ((a | b) & cin));
end
endmodule
//RCA Logic
module part1(s, cout, a, b, cin, clk);
parameter BIT_WIDTH = 128;
input [BIT_WIDTH-1:0] a, b;
input cin;
input clk;
output cout;
output [BIT_WIDTH-1:0] s;
wire [BIT_WIDTH:0] cin_wire;
assign cin_wire[0] = cin;
genvar i;
generate
begin
for(i = 0; i <= BIT_WIDTH-1; i = i + 1) //error is on this line
begin:
fadder fadder_inst (.clk(clk), .s(s[i]), .cout(cin_wire[i+1]), .a(a[i]), .b(b[i]), .cin(cin_wire[i]));
end
end
endgenerate
assign cout = cin_wire[BIT_WIDTH];
endmodule
As others have pointed out, you cannot instantiate modules inside an always block. The need to be separated and a new wire needs to be created to connect the two.
In the below example cout and s are reg type outputs. There is an added wire s_wire (following your naming convention based cin_wire) which is connected to the s output of the fadder_inst instances. part1's s and cout output is synchronously assigned to s_wire and cin[BIT_WIDTH] respectivly. Note that they are assigned with non-blocking assignments (<=).
// ...
output reg cout;
output reg [BIT_WIDTH-1:0] s;
wire [BIT_WIDTH-1:0] s_wire;
wire [BIT_WIDTH:0] cin_wire;
assign cin_wire[0] = cin;
genvar i;
generate
for(i = 0; i <= BIT_WIDTH-1; i = i + 1)
begin
fadder fadder_inst (.s(s_wire[i]), .cout(cin_wire[i+1]), .a(a[i]), .b(b[i]), .cin(cin_wire[i]));
end
endgenerate
always#(posedge clk)
begin
s <= s_wire;
cout <= cin_wire[BIT_WIDTH];
end
// ...
I am preforming a feedback mux calculation using verilog. But however the system does not response (giving X) to one of input which is B (the input controlled by the mux). Can helping me pointing out where is the error and how to fix it.
Here are the codes:
module test(input sel,input [3:0]a,b,output [3:0]o);
localparam in_0 = 4'd0;
wire [3:0]w1;
assign w1 = a + b;
assign o = w1 | 4'd0;
assign b = (sel)?w1:in_0;
endmodule
Here are the testbench:
module test_tb();
reg sel;
reg [3:0] a,b;
wire [3:0]o;
test U1(.sel(sel),.a(a),.b(b),.o(o));
initial begin
sel <= 1'b0;
a <= 4'd2;
#2;
sel <= 1'b1;
#2;
a <= 4'd1;
#2;
sel <= 1'b0;
a <= 4'd4;
#2;
end
endmodule
According to the testbench (the initialization) it seems that b is not an input (it's just the output of multiplexer)
I think you want to implement the following circuit :
But to avoid creating loops (when sel=1), you should add a clk port to your design in order to control the operation :
module test(
input clk,
input sel,
input [3:0] a,
output [3:0] o
);
wire [3:0] b;
reg [3:0] w1;
assign o = w1;
assign b = (sel)?w1:4'd0;
always #(posedge clk)
w1 <= a + b;
endmodule
Looking at your example :
module test(
input sel,
input [3:0] a,
input [3:0] b,
output [3:0]o
);
localparam in_0 = 4'd0;
wire [3:0]w1;
assign w1 = a + b;
assign o = w1 | 4'd0;
assign b = (sel)? w1 : in_0;
Note that with sel==1 you have w1 = a+b, and b =w1which is w1= a+w1; as a combinatorial loop. this will not work. If there was a flip-flop inside to break the loop then it would behave like an accumulator.
Aa noted by Emman that b is an input and therefore the value can not be overriden.
This line assign b = (sel)? w1 : in_0; is not valid. Note that it never actually uses the input value as this completely overrides it in all situations.