For a lab in a digital design course, I am designing a partial ALU. I have defined its operations and am required to use a casez statement to govern which function (either addition of a & b w/ overflow checking, bitwise inversion of b, a AND b, and a OR b) is selected by the four 2-bit combos of sel:
module eightbit_palu(input wire[7:0] a, b,
input wire[1:0] sel,
output wire[7:0] f,
output wire ovf);
wire[7:0] sum, bitInv, bitAnd, bitOr;
wire sumOvf;
assign sum = a + b;
assign sumOvf = (a+b>127)||(a+b<-128) ? 1 : 0;
assign bitInv = !b;
assign bitAnd = a & b;
assign bitOr = a | b;
always #(a or b or sel) begin
casez(sel)
2'b00: f = sum; ovf = sumOvf;
2'b01: f = bitInv; ovf = 0;
2'b10: f = bitAnd; ovf = 0;
2'b11: f = bitOr; ovf = 0;
endcase
end
endmodule
I have embedded the casez statement within an always #, but I am getting a syntax error that I believe might be due to the outputs being wires. I am not sure how to work around that seemingly simple issue.
I tried turning the variables declared before the assign statements into regs, but then there was a problem converting them to wires. I would really appreciate some insight as to how Verilog works — unfortunately my professor is teaching in SystemVerilog, yet our labs are required to be in Verilog.
Yes, you should change your output wires to reg since you are making procedural assignments to them (inside an always block).
The other error is that you need to add begin/end keywords around multiple statements in each case item. Here is code that compiles cleanly for me:
module eightbit_palu(input wire[7:0] a, b,
input wire[1:0] sel,
output reg [7:0] f,
output reg ovf);
wire[7:0] sum, bitInv, bitAnd, bitOr;
wire sumOvf;
assign sum = a + b;
assign sumOvf = (a+b>127)||(a+b<-128) ? 1 : 0;
assign bitInv = !b;
assign bitAnd = a & b;
assign bitOr = a | b;
always #(a or b or sel) begin
casez(sel)
2'b00: begin f = sum; ovf = sumOvf; end
2'b01: begin f = bitInv; ovf = 0; end
2'b10: begin f = bitAnd; ovf = 0; end
2'b11: begin f = bitOr; ovf = 0; end
endcase
end
endmodule
You also have a problem with this line:
always #(a or b or sel) begin
A sensitivity list should include only signals on the RHS of assignments within the block. Your list incorrectly includes a and b, and it misses others like sum. You should use an implicit sensitivity list which automatically includes the appropriate signals.
always #*
Related
I'm making a 8Bit select adder with 4bit adder.
When i try to test this code.
i got a 2 error.
First one is "coutL is not a constant"
Second one is "Target of concurrent assignment or output port
connection should be a net type."
Can anyone help me?
module selectAdd8(
input [7:0] a,
input [7:0] b,
input cin,
output reg [7:0] sum,
output reg cout
);
reg coutL, sumL, sum0, sum1, cout0, cout1;
always # (*);
begin
add4 add_lower(a[3:0],b[3:0],cin,sumL,coutL);
add4 add4_0(a[7:4],b[7:4],0,sum0,cout0);
add4 add4_1(a[7:4],b[7:4],1,sum1,cout1);
if (coutL==1) begin
assign sum = {sum1, sumL};
assign cout = cout1;
end else begin
assign sum = {sum0, sumL};
assign cout = cout0;
end
end
endmodule
The following statement makes no sense with semicolon after it:
always # (*);
I guess the following begin .. end were intended to go with the previous always block. They did not because of the semicolon. In any case, instantiating of modules inside such a block is illegal in verilog, it should be done outside the block and outside of begin/end:
add4 add_lower(a[3:0],b[3:0],cin,sumL,coutL);
add4 add4_0(a[7:4],b[7:4],0,sum0,cout0);
add4 add4_1(a[7:4],b[7:4],1,sum1,cout1);
Both, stand-alone begin/end and if statement represent a generate block in modern verilog. So, the following is a part of the generate block:
if (coutL==1) begin
assign sum = {sum1, sumL};
assign cout = cout1;
end else begin
assign sum = {sum0, sumL};
assign cout = cout0;
end
But such blocks only operate with constants. So countL must be a constant, i.e. a parameter. It is a reg, therefore, there is an error.
Again, it seems that you intended this as a part of the always block. assign statements within such a block are a very special verilog constructs and should not be used without a very good understanding of what they do.
My guess is that you intended something like the following:
module selectAdd8(
input [7:0] a,
input [7:0] b,
input cin,
output reg [7:0] sum,
output reg cout
);
reg coutL, sumL, sum0, sum1, cout0, cout1;
always # (*)
begin
if (coutL==1) begin
sum = {sum1, sumL};
cout = cout1;
end else begin
sum = {sum0, sumL};
cout = cout0;
end
end
add4 add_lower(a[3:0],b[3:0],cin,sumL,coutL);
add4 add4_0(a[7:4],b[7:4],0,sum0,cout0);
add4 add4_1(a[7:4],b[7:4],1,sum1,cout1);
endmodule
I am using EDA Playground with Aldec Riviera simulator, and I have this module here:
module alu(input logic [31:0] a, b,
input logic [2:0] alucontrol,
output logic [31:0] result,
output logic zero);
logic [31:0] condinvb, sum;
assign condinvb = alucontrol[2] ? ~b : b;
assign sum = a + condinvb + alucontrol[2];
always_comb
case (alucontrol[1:0])
2'b00: result = a & b;
2'b01: result = a | b;
2'b10: result = sum;
2'b11: result = sum[31];
endcase
assign zero = (result == 32'b0);
endmodule
and my testbench is here:
module alu_testbench();
logic [31:0] a,b;
logic [2:0] alucontrol;
logic [31:0] result;
logic zero, clk;
alu test_alu(a,b,alucontrol);
initial begin
$dumpfile("dump.vcd"); $dumpvars(1);
clk = 0;
a = 'hdead0000; b = 'h0000beef; alucontrol = 'b010; #1;
a = 'hc0debabe; b = 'h0000ffff; alucontrol = 'b000; #1;
a = 'hc0de0000; b = 'h0000babe; alucontrol = 'b001; #1;
a = 'hc0debabe; b = 'h0000babe; alucontrol = 'b100; #1;
end
always begin
#1; clk = ~clk;
end
endmodule
When I run the testbench and look at the generated waveform, I do not see result being updated. Instead, it stays as XXXX_XXXX. What am I doing wrong in the testbench?
In the testbench, you declared the result signal, but it is not connected to anything. You probably intended it to be driven by the alu output of the same name. In that case, you should connect it to the instance:
Change:
alu test_alu(a,b,alucontrol);
to:
alu test_alu(a,b,alucontrol,result,zero);
Try your code on other simulators on edaplayground; you should get warnings about unconnected ports.
With your code, if you looked inside the alu instance, the result signal would not be X.
Another equivalent way to code the instance is to use connections by name:
alu test_alu (
.a (a),
.b (b),
.alucontrol (alucontrol),
.result (result),
.zero (zero)
);
This makes it easier to avoid common connection errors.
Why am I getting error "q is not constant"?
module prv(
input [7:0]x,
input [7:0]y,
output [49:0]z
);
wire [24:0]q;
assign z=1;
genvar k;
for (k=50; k<0; k=k-1)
begin
wire [25:0]a;
assign a=0;
assign q= x;
genvar i;
for(i=0; i<8; i=i+1)
begin
if(q[0]==1)
begin
assign a=a+z;
end
assign {a,q}={a,q}>>1;
end
assign z={a[24:0],q};
end
endmodule
I'm afraid that you are trying to use Verilog the wrong way. q is a wire, not a variable (a reg) so it cannot be assigned with a value that includes itself, because that would cause a combinational loop. You are using the assign statement as if it were a regular variable assignment statement and it's not.
Declare a and q as reg, not wire. i and k don't need to be genvars variables, unless you are trying to generate logic by replicating multiple times a piece of code (description). For for loops that need to behave as regular loops (simulation only) use integer variables.
Besides, behavioral code must be enclosed in a block, let it be combinational, sequential, or initial.
A revised (but I cannot make guarantees about its workings) version of your module would be something like this:
module prv(
input wire [7:0] x,
input wire [7:0] y,
output reg [49:0] z
);
reg [24:0] q;
reg [25:0] a;
integer i,k;
initial begin
z = 1;
for (k=50; k<0; k=k-1) begin
a = 0;
q = x;
for (i=0; i<8; i=i+1) begin
if (q[0] == 1) begin
a = a + z;
end
{a,q} = {a,q}>>1;
end
z = {a[24:0],q};
end
endmodule
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.
Can you tell me why this simple verilog program doesn't print 4 as I want?
primitive confrontatore(output z, input x, input y);
table
0 0 : 1;
0 1 : 0;
1 0 : 0;
1 1 : 1;
endtable
endprimitive
comparatore :
module comparatore (r, x, y);
output wire r;
input wire [21:0]x;
input wire [21:0]y;
wire [21:0]z;
genvar i;
generate
for(i=0; i<22; i=i+1)
begin
confrontatore t(z[i],x[i],y[i]);
end
endgenerate
assign r = & z;
endmodule
commutatore :
module commutatore (uscita_commutatore, alpha);
output wire [2:0]uscita_commutatore;
input wire alpha;
reg [2:0]temp;
initial
begin
case (alpha)
1'b0 : assign temp = 3;
1'b1 : assign temp = 4;
endcase
end
assign uscita_commutatore = temp;
endmodule
prova:
module prova();
reg [21:0]in1;
reg [21:0]in2;
wire [2:0]uscita;
wire uscita_comparatore;
comparatore c(uscita_comparatore, in1, in2);
commutatore C(uscita, uscita_comparatore);
initial
begin
in1 = 14;
$dumpfile("prova.vcd");
$dumpvars;
$monitor("\n in1 %d in2 %d -> uscita %d uscita_comparatore %d \n", in1, in2, uscita, uscita_comparatore);
#25 in2 = 14;
#100 $finish;
end
endmodule
The issue is in commutatore. You are using initial, which means the procedural block is only executed at time 0. At time 0, the input alpha is 1'bx, meaning temp is not assigned to anything. Instead of initial, use always #* which will execute the procedural block every time alpha changes.
Generally you should not assign statements in procedural blocks. It is legal Verilog however it is often the source of design bugs and synthesis support is limited.
always #*
begin
case (alpha)
1'b0 : temp = 3;
1'b1 : temp = 4;
default: temp = 3'bx; // <-- optional : to catch known to unknown transitions
endcase
end
The reason you are not getting 4 as you expect for an output is because your commutatore uses an initial block with assign statements in it when you wanted an always #* block to perform the combinational logic to get temp. initial blocks only fire once at the beginning of a simulation, while you want continuous assignment to act as combinational logic. Also, the assign statements in the block are not needed, they only make the simulation behave improperly for your purposes (typically, you will never need to use assign inside another block (initial,always,etc) as this has another meaning than simply set x to y.
For example, you really want something like this:
always #(*) begin
case (alpha)
1'b0: temp = 3'd3;
1'b1: temp = 3'd4;
endcase
end
Also, Verilog already has a build XNOR primative so your confrontatore is not needed, you can use xnor instead.