Pipelining a verilog module consisting 10 components connected in series - verilog

I am trying to pipeline a module which consists of 5 multipliers and 5 adders connected in series. The module is a polynomial calculator. Without pipelining the module is working perfectly so far.
multipliers [31:0] m0,m1,m2,m3,m4; // separate module
adders [31:0] a0,a1,a2,a3,a4; // separate module
user_input [31:0] input; // register
constants [31:0] c0,c1,c2,c3,c4; // registers
pipeliners [31:0] p0,p1,p3,p4,p4; // pipelining resisters
wires [31:0] w0,w1,w2,w3,w4; // wires
Without pipelining the structure looks like following,
[input]*[c0] => w0 => [w0]+[c1] => w1 => [w1]*[input] => w2 => [w2]+[c2] => w3 ... //goes on like this
As all of them are connected in series, the critical path consists of 10 components.
My implemented pipelining idea is following,
[input]*[c0] => w0 => p0 => [p0]+[c1] => w1 => p1 => [p1]*[input] => w2=> p2 => [p2]+[c2] => w3 ... //goes on like this
I have an error, "cannot be driven by primitives or continuous assignment."It is due to p0,p1,p3 ... registers. Converting them into wire solves the error but then they are not registers anymore. I am using iverilog as compiler.
My question is, how can I do the pipelining so that I get the output using least possible clock cycles and resolve the error as well?
******* Edited version with code *******
`timescale 1ns / 1ps
module poly (
clk,
q,
result
);
input clk;
input [31:0] q; //user input
output [31:0] result;
reg [31:0] c,c0,c1,c2,c3,c4;
reg [31:0] p, p0, p1, p2, p3, p4, p5, p6,p7,p8,p9,p10,p11,p12;
always #(q)
if (q>=32'h08000000 && q<32'h0A000000) begin
c <= 32'h058B90C0;
c0 <= 32'h74599F60;
c1 <= 32'h79481740;
c2 <= 32'h445B7440;
c3 <= 32'h5AF892E0;
c4 <= 32'h9E2C2258;
end else if (q>=32'h0A000000 && q<32'h0C000000)
begin
c <= 32'h258B90C0;
c0 <= 32'hFB942240;
c1 <= 32'h21558EC0;
c2 <= 32'h5D882000;
c3 <= 32'h75F846E8;
c4 <= 32'hF48F5786;
end
wire [31:0] x0,x1,x2,x3,x4;
wire [31:0] y0,y1,y2,y3,y4;
multiplier m4 (.i_multiplicand(q),.i_multiplier(c4),.o_result(x4));
assign = x4;
adder a4 (.a(p0),.b(c3),.c(y4));
assign p1 = y4;
assign p2 = q;
multiplier m3 (.i_multiplicand(p2),.i_multiplier(p1),.o_result(x3));
assign p3 = x3;
adder a3 (.a(p3),.b(c2),.c(y3));
assign p4 = y3;
assign p5 = q;
multiplier m2 (.i_multiplicand(p5),.i_multiplier(p4),.o_result(x2));
assign p6 = x2;
adder a2 (.a(p6),.b(c1),.c(y2));
assign p7 = y2;
assign p8 = q;
multiplier m1 (.i_multiplicand(p8),.i_multiplier(p7),.o_result(x1));
assign p9 = x1;
adder a1 (.a(p9),.b(c0),.c(y1));
assign p10 = y1;
assign p11 = q;
adder a0 (.a(p10),.b(p11),.c(y0));
assign p12 = y0;
multiplier m0 (.i_multiplicand(p12),.i_multiplier(c),.o_result(x0));
assign result = x0;
endmodule

As Morgan already stated you get only registers if you have a reg and a clock.
always #(posedge clk)
begin
p1 <= y4;
p2 <= q;
// etc.
end
Which if you think about it is rather obvious as this is a register:
Which as you can see has as input a signal and a clock.

Related

In Verilog, what is the pragma directive to inform a simulator / synthesizer to throw an error for undefined netlists? [duplicate]

I have to make a 64 Bit ALU that takes in A and B 64-bit inputs, a carry_in input and outputs a 64bit result along with a 1-bit carry_out. There is also a 5 bit function-select FS. Where FS[0] controls whether B is inverted or not (using a 2to1 mux.) F[1] does the same for the A. And FS[4:2] determines which operation (Adding, subtracting, logical operations, etc) using an 8to1 Mux. Below is the code for the ALU and Testbench.
I'm pretty sure my testbench is good and so is all the separate components for the ALU. I'm not too confident about my top-level where I instantiate and connect all the inputs/outputs. What is causing the high impedance in the waveform?
module ALU(A, B, FS, cin, cout, result);
input [63:0] A, B;
input [4:0] FS;
input cin;
output cout;
output [63:0] result;
eight_one_mux u7 (firstoutA & secoutB, firstoutA | secoutB, sum, firstoutA ^ secoutB,
left, right, 1'b0, 1'b0, FS[4:2], result);
adder u6 (firstoutA, secoutB, cin, sum, cout);
firstmux u1 (A, !A, FS[1], firstoutA);
secmux u2 (B, !B, FS[0], secoutB);
Alu_shifter u5 (A, left, right);
endmodule
//--------------------------------------------------------------------------------//
//These are the two muxes to split into input and inverted input A,B
module firstmux(a, nota, firstS, firstoutA);
input [63:0] a, nota;
input firstS;
output reg [63:0] firstoutA;
always #(a or nota or firstS)
begin
case(firstS)
0 : firstoutA = a;
1 : firstoutA = nota;
default : firstoutA = 1'bx;
endcase
end
endmodule
//<><><><><><><>//
module secmux(b, notb, secS, secoutB);
input [63:0] b, notb;
input secS;
output reg [63:0] secoutB;
always #(b or notb or secS)
begin
case(secS)
0 : secoutB = b;
1 : secoutB = notb;
default : secoutB = 1'bx;
endcase
end
endmodule
//--------------------------------------------------------------------------------//
//This is the Shifter Blocks
module Alu_shifter (shiftA, right, left); //This shifter block shifts the A input once right or left
input [63:0] shiftA;
output [63:0] right;
output [63:0] left;
shift_right w1 ( //instantiate right shifter block
.a_R(shiftA),
.R(right)
);
shift_left w2 ( //instantiate left shifter block
.a_L(shiftA),
.L(left)
);
endmodule
////////><><><><><><><><><><><><><><><///////
module shift_right (a_R, R); // right shifter block
input [63:0] a_R;
output [63:0] R;
assign R = a_R >> 1; //shift A right once (shift in a 0)
endmodule
module shift_left (a_L, L); //left shifter block
input [63:0] a_L;
output [63:0] L;
assign L = a_L << 1; //shift A left once (shift in a 0)
endmodule
//End shifter blocks (3 total modules)
//----------------------------------------------------//////////////////////
//This is the Adder that Adds A, B and cin
module adder(addA, addB, nic, sum, cout);
input [63:0] addA, addB;
input nic;
output [63:0] sum;
output cout;
assign {cout, sum} = addA + addB + nic;
endmodule
//----------------------------------------------------//////////////////////
//This is the 8to1 Mux that decides which operation is put forward
module eight_one_mux(D0, D1, D2, D3, D4, D5, D6, D7, S, out);
input [63:0] D0, D1, D2, D3, D4, D5, D6, D7;
input [2:0] S;
output reg [63:0] out;
always #(D0 or D1 or D2 or D3 or D4 or D5 or D6 or D7 or S)
begin
case(S)
0 : out = D0; //And
1 : out = D1; //Or
2 : out = D2; //Adder
3 : out = D3; //xor
4 : out = D4; //lefter
5 : out = D5; //righter
6 : out = D6; //GND
7 : out = D7; //GND
default : out = 1'bx;
endcase
end
endmodule
////////////-------------------------------////////////////////////////////
module ALU_tb();
reg [63:0] A, B;
reg [4:0] FS;
reg cin;
wire cout;
wire [63:0] result;
ALU dut (
.A(A),
.B(B),
.FS(FS),
.cin(cin),
.cout(cout),
.result(result)
);
initial begin
A = 8'b11001100;
B = 8'b11001101;
FS = 5'b01101;
cin = 1;
end
always
#5 cin <= ~cin;
always begin
#5
A <= A + 1;
B <= B + 2;
#5;
end
initial begin
#100 $finish;
end
endmodule
```
Unexpected high impedance (z) values are typically the result of undriven signals, and that is the problem with your code.
adder u6 (firstoutA, secoutB, cin, sum, cout);
In the line above, you connect the 1-bit signal firstoutA to the 64-bit addA input port. This connects firstoutA to addA[0], leaving the other 63 bits undriven. Thus, addA[63:1] are all z.
firstoutA is a 1-bit signal because you did not explicitly declare it. Also, undeclared signals are assumed to be of type wire, which default to z.
It is good practice to declare all signals.
To find all undeclared signals, add this to the top of your code:
`default_nettype none
You should get compile errors like:
Error-[IND] Identifier not declared
Identifier 'firstoutA' has not been declared yet. If this error is not
expected, please check if you have set `default_nettype to none.
Error-[IND] Identifier not declared
Identifier 'secoutB' has not been declared yet. If this error is not
expected, please check if you have set `default_nettype to none.
First you need to define signals (wire) for connections between modules. For example, you have left and right as outputs of Alu_shifter module and they are connected to firstmux and secmux modules; however, they are not defined in your top module. You should add following signal definitions to your topmodule:
wire [63:0] left,right;
wire [63:0] firstoutA;
wire [63:0] secoutB;
wire [63:0] sum;
Also, eight_one_mux module takes eight 64-bit inputs. However, you set the last two of them as 1'b0. You should change them to 64'b0 as below.
eight_one_mux u7 (firstoutA & secoutB, firstoutA | secoutB, sum, firstoutA ^ secoutB,
left, right, 64'b0, 64'b0, FS[4:2], result);
Finally, !A does not invert all bits of A (same for B). It applies a reduction operation and generates a 1-bit signal (and firstmux module expects a 64-bit signal in its second input port).

4-bit register using D flip-flop with enable and asynchronous reset

I am modelling a 4-bit register using D flip-flops with enable and asynchronous reset. It contains 4 D FF and 4 2:1 Mux. I used structural Verilog to model the circuit.
My design is shown below.
module DFlipFlop(D,clk,reset,Q);
input D;
input clk,reset;
output Q;
reg Q;
always #(posedge clk or posedge reset)
begin
if(reset==1'b1)
Q <= 1'b0;
else
Q <= D;
end
endmodule
module m21(D0, D1, S, Y);
output Y;
input D0, D1, S;
assign Y=(S)?D1:D0;
endmodule
module DFF_with_Enable(D,clk,enable,reset,Q);
input D,clk,reset,enable;
output Q;
reg Q;
wire in;
m21 mux(D,in,enable,in);
DFlipFlop DFF(in,clk,reset,Q);
endmodule
module fourbitreg(D,clk,reset,enable, Q);
input[0:3] D; // Data input
input clk,reset,enable;
output [3:0]Q;
reg [3:0]Q;
wire d0,d1,d2,d3;
wire q0,q1,q2,q3;
d0 = D[0];
d1 = D[1];
d2 = D[2];
d3 = D[3];
DFF_with_Enable df0(d0,clk,reset,enable,q0);
DFF_with_Enable df1(d1,clk,reset,enable,q1);
DFF_with_Enable df2(d2,clk,reset,enable,q2);
DFF_with_Enable df3(d3,clk,reset,enable,q3);
assign Q = {q0,q1,q2,q3};
endmodule
I used iverilog for simulation. How do I fix the following errors during compilation?
design.sv:37: syntax error
design.sv:37: error: Invalid module instantiation
design.sv:38: error: Invalid module instantiation
design.sv:39: error: Invalid module instantiation
design.sv:40: error: Invalid module instantiation
The circuit of 1 DFF MUX pair is shown below.
There are multiple compile errors.
Inside DFF_with_Enable and fourbitreg, do not declare Q as a reg because you make continuous assignments to Q.
You need to use the assign keyword to make continuous assignments to d0, etc.:
assign d0 = D[0];
assign d1 = D[1];
assign d2 = D[2];
assign d3 = D[3];
You should also try different simulators on edaplayground to get more meaningful error messages.

variable width assignment from 2 wires in a new wire with bit masking [VERILOG]

I'm trying to implement in hardware (using Verilog) the function described by this pseudo code:
if A then
output [63:0] = b[63:56], c[X-1:0], b[Y-1:0]
else output [63:0] = c[X-1:0], b[Y-1:0]
A is a boolean value, while output, b and c are 64 bits long.
X and Y change at runtime so they can't be Verilog variables.
The value of X changes with A:
if A then
X = 56 - Y
else X = 63 - Y
while Y is read from a 6 bit register so it can be any number from 0 to 63.
So for both cases of A all 64 bits of output will be assigned.
I know bit masking and mux selection with A is required but it is a bit complex and I can't quite get a clear picture on how to implement this in Verilog.
The runtime dependent bit selection can be implemented with shift(<<), variable bit selection(a[k+:8]), a smartly designed for loop(a[i] = condition ? b:c) or a completely expressed case. And all of them should have similar synthesis result. Based on experience, the case implementation should have best area performance.
Here is an example (with testbench) for shift implementation:
`timescale 1ns/1ps
module example(
input A,
input [5:0] Y,
input [63:0] b, c,
output [63:0] result
);
reg [63:0] o_a, o_abar;
assign result = A ? o_a : o_abar;
wire [5:0] X = A ? (56-Y) : (63-Y);
reg [63:0] c1_tmp, b1_tmp, mask;
always#(*)begin
c1_tmp = (c << Y) & {8'd0, {56{1'b1}}};
mask = (({64{1'b1}}>>X) << Y) | ({64{1'b1}} >> (64-Y));
b1_tmp = mask & b;
o_a = c1_tmp | b1_tmp;
end
reg [63:0] c2_tmp, b2_tmp;
always#(*)begin
c2_tmp = c << Y;
b2_tmp = b & ({64{1'b1}} >> Y);
o_abar = c2_tmp | b2_tmp;
end
endmodule
module test;
reg A;
reg [5:0] Y;
reg [63:0] b, c;
wire [63:0] result;
example ex(.A(A), .Y(Y), .b(b), .c(c), .result(result));
initial begin
A = 1;
Y = 6;
c = -1;
b = 0;
#10
$display("%b", result);
$finish;
end
endmodule

feedback on mux in verilog

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.

No output from a pattern matching module

The objective is to write structural Verilog code for a circuit that has two inputs, w1 and w2, and an output, q. The circuit compares the input sequences of w1 and w2. If w1 and w2 match for 4 consecutive clock pulses, q should be 1; otherwise it should remain at 0.
Example:
w1 = 0100111010010
w2 = 0000110010010
q = 0000010000111
I've drawn a state diagram and a state table and concluded that I need 3 D flip flops for this circuit. I then wrote K-maps for the inputs of each D-FF. However, when I wrote the code, the resulting waveform unexpectedly looks like this:
Here is my code:
module PatternMatch2(q, w1, w2, clk, rst);
output q;
input w1, w2, clk, rst;
DF DF1(y1, yBar1, Y1, clk, rst),
DF2(y2, yBar2, Y2, clk, rst),
DF3(y3, yBar3, Y3, clk, rst);
and and0(Y1, nI, yBar3, yBar1),
and1(Y2In1, nI, yBar2, y1),
and2(Y2In2, nI, y2, yBar1),
and3(Y3In1, nI, y3),
and4(Y3In2, nI, y2, y1),
and5(q, y3, yBar2, yBar1);
xor xor0(i, w1, w2);
or or0(Y2, Y2In1, Y2In2),
or1(Y3, Y2In1, Y2In3);
not not0(nI, i);
endmodule
// D - Flip Flop Module
module DF(q, qBar, D, clk, rst);
input D, clk, rst;
output q, qBar;
reg q;
not n1 (qBar, q);
always# (posedge rst or posedge clk)
begin
if(rst)
q = 0;
else
q = D;
end
endmodule
I'm not sure what's wrong in my code as my equations seem correct.
When I compile your code, I get this warning message:
Implicit wire 'Y2In3' does not have any driver
You need to drive your or1 input appropriately.
You only need 2 FFs organized as a saturating counter with reset for such task:
Create a reset signal rst=XOR(w1,w2) and connect to both FF's reset input
Connect your FFs inputs (d0, d1) to outputs (q0, q1) according to a following truth table (2-bit counter with saturation):
q1 q0 => d1 d0
0 0 => 0 1
0 1 => 1 0
1 0 => 1 1
1 1 => 1 1
That is:
d0 = OR(NOT(q0), q1)
d1 = OR(q0, q1)
Your output will be: q=AND(q0, q1, NOT(rst))

Resources