Multiple bits gates - verilog

I'd like to know how I could go about using AND, OR and other gates for multiple bits inputs. I was trying to build a 2:1 MUX but I got this error:
Expression width 2 does not match width 1 of logic gate array port 1.
Here's the code
module mux_21 #(parameter width = 1) (
input [width-1:0] d0, d1,
input s,
output [width-1:0] y
);
wire [width-1:0] ns, y1, y2;
not g1 (ns, s);
and g2 (y1, d0, ns);
and g3 (y2, d1, s);
or g4 (y, y1, y2);
endmodule

Primitive gates are always single bit. You need to create instance for each bit combination.
The most common way to is with a generate for-loop. Generate logic goes through static unrolled during the elaboration phase of compile.
genvar gidx;
wire ns;
wire [width-1:0] y1, y2;
not g1 (ns, s);
generate
for(gidx=0; gidx<width; gidx=gidx+1) begin : mux
and g2 (y1[gidx], d0[gidx], ns );
and g3 (y2[gidx], d1[gidx], s );
or g4 (y[gidx], y1[gidx], y2[gidx] );
end
endgenerate
You could also create a range of instances. This is a feature that has existed longer then the generate construct but less commonly used and I notices some synthesizers don't support it (ex Yosys 0.9 on EDAplayground).
wire ns;
wire [width-1:0] y1, y2;
not g1 (ns, s);
and g2 [width-1:0] (y1, d0, ns);
and g3 [width-1:0] (y2, d1, s);
or g4 [width-1:0] (y, y1, y2);

Related

Pipelining a verilog module consisting 10 components connected in series

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.

Adder and accumulator in verilog. How do I tie outputs of flip flops back into inputs of adder?

I am creating an adder and accumulator using structural only. Below is what I have do far:
module adder_and_accum(add, clb, clc, iac, x2, in, acc, carry, carrynot, qn2, qn3, qn4, qn5);
input add, clb, clc, iac, x2;
input [3:0] in;
output [3:0] acc;
output carry, carrynot, qn2, qn3, qn4, qn5;
wire adder1in2, adder2in2, adder3in2, adder4in2;
wire sum1, sum2, sum3, sum4;
wire ffin1;
wire cinadder1, cinadder2, cinadder3;
wire carrynot, clearcarry;
four_to_one_mux mux1(0, 0, in[3], 0, add, iac, adder1in2);
four_to_one_mux mux2(0, 0, in[2], 0, add, iac, adder2in2);
four_to_one_mux mux3(0, 0, in[1], 0, add, iac, adder3in2);
four_to_one_mux mux4(0, 1, in[0], 0, add, iac, adder4in2);
full_adder f1(sum1, ffin1, cinadder1, acc[3], adder1in2);
full_adder f2(sum2, cinadder1, cinadder2, acc[2], adder2in2);
full_adder f3(sum3, cinadder2, cinadder3, acc[1], adder3in2);
full_adder f4(sum4, cinadder3, 0, acc[0], adder4in2);
or(clearcarry, clc, clb);
d_flip_flop dff1(ffin1, x2, carry, carrynot, clc);
d_flip_flop dff2(sum1, x2, acc[3], qn2, clearcarry);
d_flip_flop dff3(sum2, x2, acc[2], qn3, clearcarry);
d_flip_flop dff4(sum3, x2, acc[1], qn4, clearcarry);
d_flip_flop dff5(sum4, x2, acc[0], qn5, clearcarry);
endmodule
Here are the Flip flop, mux, and full adder headers:
module full_adder(sum, cout, cin, inp1, inp2);
module four_to_one_mux(in0, in1, in2, in3, select0, select1, out);
module d_flip_flop(d, clk, q, qn, reset);
Flip flops, muxes, and full adder are modules I created and I know they work because I have tested them individually. They all show correct waveforms.
I have narrowed down the problem to the flip flop Q output being wrapped around back into my adder input. My ACC bus output just shows XXXX.
How do I tie the output for my flip flops back as an input into my adder?
Here is the schematic of the adder and accumulator I made for reference.
Switching to the built in flip flop in xilinx fixed the issue:
FDRE FDRE_inst (
.Q(acc[0]), // 1-bit Data output
.C(x2), // 1-bit Clock input
.CE(ce), // 1-bit Clock enable input
.R(clb), // 1-bit Synchronous reset input
.D(sum4) // 1-bit Data input
);
I was able to just use a wire to tie the outputs of the flip flop back into the 4 bit adder. Nothing special was required.

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))

32 bit adder subtractor ALU using generate

I need to implement a 32 bit adder subtractor ALU for a class assignment. I have a 1-bit adder subtractor that works fine and the operation is made with the help of a select statement (code for all is given below). Anyway, the problem I am facing is that I am unable to figure out how to use the carry/borrow out of one module to the subsequent module.
module add_sub(select, i0, i1, cin, out, cout
);
input i0, i1, select, cin;
output out, cout;
wire y0, y1, y2, y3, y4, y5, y6;
wire z0, z1, z2, z3, z4;
//diff = i0 xor i1 xor cin
//borrow = cin. ~(i1 xor i2) or ~x.y
xor (y0, i1, cin);
xor (y1, i0, y0); //y1=diff or sum as only carry and borrow vary between adder and subtractor circuits
xor (y2, i1, i0);
and (y3, cin, ~y2);
and (y4, ~i0, i1);
or (y6, y5, y4); //y6 = borrow
and (z0, i0, i1);
xor (z1, i0, i1);
and (z2, cin, z1);
or (z3, z0, z2); //z3= carry out for sum
//conditional operator for assigning sum or difference. if select = 0, we add, else subtract
assign out = y1;
assign cout = select ? y6 : z3;
endmodule
This module is instantiated in a loop in the alu module that is given below...
module alu(sel, num1, num2, alu_cin, alu_out, alu_c
);
parameter N = 32;
input sel; //select line for add or sub
input [N-1:0] num1; //two inputs
input [N-1:0] num2;
input alu_cin;
output [N-1:0] alu_out; //32 bit output
output alu_c; // becomes final carry or borrow accordingly
genvar i;
generate for (i=0; i<=N-1; i=i+1)
begin: alu_loop
if (i == 0)
add_sub as_i (sel, num1[i], num2[i], alu_cin, alu_out[i], alu_c);
else
add_sub as_i (sel, num1[i], num2[i], alu_loop[i-1].as_i.cout[i-1], alu_out[i], alu_c);
end
endgenerate
endmodule
In the test bench for the alu, I gave appropriate 32 bit values and the select value as I need. The problem comes with
add_sub as_i (sel, num1[i], num2[i], alu_loop[i-1].as_i.cout[i-1], alu_out[i], alu_c);
It says "Indexing cannot be applied to a scalar." as I am trying to simulate it. Syntax check is completed perfectly.
I need access to cout from the one-bit module to pass it on as cin to the next one. The alu_c can be overwritten as only the last one bit is needed.
Any help would be appreciated. Thanks in advance. :) All this is done on Xilinx ISE through Verilog modules.
It is syntactically correct but you are using a bit-select on a single bit value, which is a semantic error.
add_sub as_i (
sel,num1[i],num2[i],alu_loop[i-1].as_i.cout[i-1],alu_out[i],alu_c);
^^^^
Declared as scalar output in add_sub
output out, cout;
While Verilog allows referencing a port using the dot notation(hierarchical referencing), it's not a good practice outside of testbenches. You should declare a wire for that connectivity instead.
for (i=0; i<=N-1; i=i+1)
begin: alu_loop
wire cout; // Visible as alu_loop[N].cout
end

How can I build a chain of modules?

I am having trouble in building a chain of modules. I can connect models manually listing all the modules but need more concise representation. The following code has been tried but doesn't work? How can I correct the codes?
module network(
input signed [31:0] xi,
output signed [31:0] yo,
input clk,
input reset
);
wire signed [31:0] x0, x1, x2, y0, y1, y2, xo;
wire [3:1] t;
//working code for chain of pe
// pe u0(xi, x0, 0, y0, clk, reset);
// pe u1(x0, x1, y0, y1, clk, reset);
// pe u2(x1, x2, y1, y2, clk, reset);
// pe u3(x2, xo, y2, yo, clk, reset);
//chain of array not working! how!
pe p[1:4] ((xi,t), (t, x), (0, t), (t,yo),clk,reset); <- want to improve
endmodule
Here, pe (input,output,input,output,clk,reset).
Try this. It should work in all version of Verilog. In this instance the parameter PE_NUM must be an int with a value of 2 or more. A generate block must be use if a 1 pe instance is desired, which requires Verilog-2001 or SystemVerilog. Some simulators may have an hit a memory limitation when PE_NUM gets big (ex 2**16).
/*All Verilog*/
module network(
input signed [31:0] xi,
output signed [31:0] yo,
input clk,
input reset
);
parameter PE_NUM = 4; // limitation PE_NUM must be greater then 1
wire signed [31:0] xo;
wire signed [0:PE_NUM-2] [31:0] xN;
wire signed [0:PE_NUM-2] [31:0] yN;
pe p[0:PE_NUM-1] ({xi,xN}, {xN,xo}, {32'b0,yN}, {yN,yo}, clk,reset);
endmodule
The following is an example with generate:
/*Verilog-2001 or SystemVerilog*/
module network(
input signed [31:0] xi,
output signed [31:0] yo,
input clk,
input reset
);
parameter PE_NUM = 4; // no limitation
wire signed [31:0] xo;
generate
if(PE_NUM <2) begin
pe p (xi, xo, 32'b0, yo, clk,reset);
end
else begin
wire signed [0:PE_NUM-2] [31:0] xN;
wire signed [0:PE_NUM-2] [31:0] yN;
pe p[0:PE_NUM-1] ({xi,xN}, {xN,xo}, {32'b0,yN}, {yN,yo}, clk,reset);
end
endgenerate
endmodule

Resources