how to implement verilog code with small modules - verilog

(Verilog) The following is a 32-bit Arithmetic Logic Unit (ALU) [see slides]. It has two 2-1 and one 3-1 MUX, a 32-bit Adder, a 32-bit subtractor, and a 16-bit multiplier. The function table shows different functions this ALU performs for different values of F (a 3-bit control signal). Notice the interconnect among different modules inside the ALU.
Please describe this ALU using Verilog. Your implementation should start with the smaller blocks showing in the ALU, and then using those smaller blocks to build the whole ALU. In other words, your implementation should promote reusability of smaller modules (i.e., modular). Optimize your implementation if possible.
function table in the image
module adding(r,a,b);
input[31:0] a;
input[31:0] b;
output[31:0] r;
assign r=a+b;
endmodule
module ALU(F,A,B,R);
input[2:0] F;
input[31:0] A;
input[31:0] B;
output[31:0] R;
reg R;
always #(F)
begin
if ( F == 3'b000 ) adding ad(R,A,B);
else if ( F == 3'b001 ) R = A+1;
else if ( F == 3'b010 ) R = A-B;
else if ( F == 3'b011 ) R = A-1;
else if ( F == 3'b10x ) R = A*B;
end
endmodule
this what I did so far but I got errors!! I will continue with the other statement as I know how to make the first small module

Notice some basic verilog syntax issues.
bit width mismatch in declaration of R.
sensitivity list not complete for the always block.
module instantiation is not allowed under a structural if.
I don't know if the undefined branches for F is intended, it is leading to behavior perhaps your don't want.
Since you are mainly working on module partition, it's related to the point 3. You will need to instantiate the basic (reusable) modules separately, and then select the outputs via F.
wire [31:0] adder_b;
wire [31:0] adder_result;
assign adder_b = F[0] ? 32'h1 : B; // select input outside 'adding'
adding ad (adder_result, A, ader_b);
always#(*)begin
if(F2:1] == 2'b00) R = adder_result;
...
end

There are many ways to write simple code in verilog.it depends on requirement some time here I presented different ways to write this code.
first by assign keyword and the second by case statements.
assign result = (opcode==3'b000) ? A+B :
((opcode==3'b001)? A+1 :
((opcode==3'b010)? A-B :
((opcode==3'b011)? A-1 : A*B)));
always #(*) begin
casex(opcode)
3'b000: result=A+B;
3'b001: result=A+1;
3'b010: result=A-B;
3'b011: result=A-1;
3'b1xx: result=A*B;
endcase
end

Related

error in verilog "varible cannot be a net"

i wrote a truth table code in verilog and it show this error "varibale Y cannot be a net"
it is an equation to design a CMOS circuit it there any other way to declare the value of varibles instead of using the truth table? or is this method better if the error can be solved? this is the code down bellow
module pro1 ( A,B,C,D,E,Y);
output Y ;
input A,B,C,D,E ;
assign Y = ~(A&B^C&D^A&E&D^C&E&B);
always #(A or B or C or D or E)
begin
case ({A,B,C,D,E})
5'b00000:Y=0;
5'b00001:Y=0;
5'b00010:Y=0;
5'b00011:Y=0;
5'b00100:Y=0;
5'b00101:Y=0;
5'b00110:Y=1;
5'b00111:Y=1;
5'b01000:Y=0;
5'b01001:Y=0;
5'b01010:Y=0;
5'b01011:Y=0;
5'b01100:Y=0;
5'b01101:Y=1;
5'b01110:Y=1;
5'b01111:Y=1;
5'b10000:Y=1;
5'b10001:Y=0;
5'b10010:Y=0;
5'b10011:Y=1;
5'b10100:Y=0;
5'b10101:Y=0;
5'b10110:Y=1;
5'b10111:Y=1;
5'b11000:Y=1;
5'b11001:Y=1;
5'b11010:Y=1;
5'b11011:Y=1;
5'b11100:Y=1;
5'b11101:Y=1;
5'b11110:Y=1;
5'b11111:Y=1;
endcase
end
endmodule
Verilog only allows continuous assignments to wires na d procedural assignments to variables. For simple combinational logic, the two following descriptions are identical in functionality.
module pro1 ( input wire A,B,C,D,E,
output wire Y);
assign Y = ~(A&B^C&D^A&E&D^C&E&B);
endmodule
module pro1 ( input wire A,B,C,D,E,
output reg Y);
always #(*)
Y = ~(A&B^C&D^A&E&D^C&E&B);
endmodule
See https://blogs.sw.siemens.com/verificationhorizons/2013/05/03/wire-vs-reg/

Instantiate a module based on a condition in Verilog

I have a 1023 bit vector in Verilog. All I want to do is check if the ith bit is 1 and if it is 1 , I have to add 'i' to another variable .
In C , it would be something like :
int sum=0;
int i=0;
for(i=0;i<1023;i++) {
if(a[i]==1) {
sum=sum+i;
}
Of course , the addition that I am doing is over a Galois Field . So, I have a module called Galois_Field_Adder to do the computation .
So, my question now is how do I conditionally check if a specific bit is 1 and if so call my module to do that specific addition .
NOTE: The 1023 bit vector is declared as an input .
It's hard to answer your question without seeing your module, as we can't gage where you are in your Verilog. You always have to think of how your code translates in gates. If we want to translate your C code into synthesizable logic, we can take the same algorithm, go through each bit one after the other, and add to the sum depending on each bit. You would use something like this:
module gallois (
input wire clk,
input wire rst,
input wire [1022:0] a,
input wire a_valid,
output reg [18:0] sum,
output reg sum_valid
);
reg [9:0] cnt;
reg [1021:0] shift_a;
always #(posedge clk)
if (rst)
begin
sum[18:0] <= {19{1'bx}};
sum_valid <= 1'b0;
cnt[9:0] <= 10'd0;
shift_a[1021:0] <= {1022{1'bx}};
end
else
if (a_valid)
begin
sum[18:0] <= 19'd0;
sum_valid <= 1'b0;
cnt[9:0] <= 10'd1;
shift_a[1021:0] <= a[1022:1];
end
else if (cnt[9:0])
begin
if (cnt[9:0] == 10'd1022)
begin
sum_valid <= 1'b1;
cnt[9:0] <= 10'd0;
end
else
cnt[9:0] <= cnt[9:0] + 10'd1;
if (shift_a[0])
sum[18:0] <= sum[18:0] + cnt[9:0];
shift_a[1021:0] <= {1'bx, shift_a[1021:1]};
end
endmodule
You will get your result after 1023 clock cycles. This code needs to be modified depending on what goes around it, what interface you want etc...
Of importance here is that we use a shift register to test each bit, so that the logic adding your sum only takes shift_a[0], sum and cnt as an input.
Code based on the following would also work in simulation:
if (a[cnt[9:0])
sum[18:0] <= sum[18:0] + cnt[9:0];
but the logic adding to sum would in effect take all 1023 bits of a[] as an input. This would be quite hard to turn into actual lookup tables.
In simulation, you can also implement something very crude such as this:
reg [1022:0]a;
reg [9:0] sum;
integer i;
always #(a)
begin
sum[9:0] = 10'd0;
for (i=0; i < 1023; i=i+1)
if (a[i])
sum[9:0] = sum[9:0] + i;
end
If you were to try to synthesize this, sum would actually turn into a chunk of combinatorial logic, as the 'always' block doesn't rely on a clock. This code is in fact equivalent to this:
always #(a)
case(a):
1023'd0: sum[18:0] = 19'd0;
1023'd1: sum[18:0] = 19'd1;
1023'd2: sum[18:0] = 19'd3;
etc...
Needless to say that a lookup table with 1023 input bits is a VERY big memory...
Then if you want to improve your code, and use your FPGA as an FPGA and not like a CPU, you need to start thinking about parallelism, for instance working in parallel on different ranges of your input a. But this is another thread...

Verilog: tristates for synthesis, and difference between conditional and case?

How do I convert a tristate bus to 2-state logic for synthesis?
I've made a little test
module test1( inout tristate, output flattened);
assign flattened = tristate ? 1 : 0;
endmodule
module test2( inout tristate, output reg flattened);
always #(tristate) begin
case(tristate)
0: flattened = 0;
default: flattened = 1;
endcase
end
endmodule
`timescale 1ns / 1ps
module test_tb;
reg tristateEnable;
reg tristateValue;
wire tristate = tristateEnable ? tristateValue : 1'bz;
wire flattened1, flattened2;
test1 uut1(tristate, flattened1);
test2 uut2(tristate, flattened2);
initial begin
tristateValue = 1'b0;
tristateEnable = 1;
#10 tristateValue = 1'b1;
#10 tristateEnable = 1'b0;
end
endmodule
Simulating it I got that module test1 sets flattened to X and module test2 sets it to 1, the latter is what I wanted, but I haven't synthesized it yet. Is there a better / standard way of doing this?
You've asked two questions: (1) what is the difference between the conditional operator and the case statement, and (2) how to handle tri-state values.
On the language question:
In short, Verilog has a 4-state data type, and the operators handle the 4 states differently.
The case statement does a "4-state test", otherwise known as "case equality". The case expression (tristate in your example) is compared against 0, 1, x, and z. When it is z, the default branch is taken, so flattened is 1, as you found.
The conditional ('ternary') operator also does a 4-state test, and finds tristate as z. It doesn't know what to do now, so it combines the two values you supplied (0 and 1) into a resulting x, which is what you see. Basically, it's trying to be smart. See table 5-21 in the 2005 LRM.
Note that the if statement does not do a 4-state test.
Tristates: you're confused because your control signal (tristate) goes to z; it's the data signal (flattened) that should go to z.
You don't 'flatten' tristates for synthesis; you normally model a pull-up or pull-down. This will be specific to your technology, but you may just need to instantiate a pullup or pulldown component. Your synthesiser may or may not do this automatically for you if you have code like
assign sig_o = (ena == 1'b1)? sig_i : 1'bz;
You need to read your synthesiser docs to be sure. Note that you should only ever use a conditional operator like this if ena is guaranteed to be 2-state (0/1).

How do I fix "Error-[IBLHS-NT] Illegal behavioral left hand side"?

I am trying to debug this code shown below. I can not get it to work at all. The attached Verilog file has two modues: 1) "equality" which defines the Device Under Test (DUT) and 2) "test" which generates the inputs to test the DUT. The module "equality" has a coding error. Let me know if you can give me a hint. Thanks!
The errors I am receiving are:
Error-[IBLHS-NT] Illegal behavioral left hand side
ECE413/src/Equality_bugs_Test_Bench.v, 7
Net type cannot be used on the left side of this assignment.
The offending expression is : Equal
Source info: Equal = 1;
Error-[IBLHS-NT] Illegal behavioral left hand side
ECE413/src/Equality_bugs_Test_Bench.v, 9
Net type cannot be used on the left side of this assignment.
The offending expression is : Equal
Source info: Equal = 0;
My SystemVerilog Code is:
module equality (Equal, a, b); // This module defines the DUT.
input[3:0] a, b;
output Equal;
always # (a or b)
begin
if (a == b)
Equal = 1;
else
Equal = 0;
end
endmodule
//
//
//
module test; // This is the test bench. It specifies input signals to drive the DUT.
reg [3:0] a, b;
wire Equal;
equality Eq1 (Equal, a, b); // This line instantiates the DUT.
initial
begin
a = 4'b0000; // Initialize "a" to 0.
b = 4'b0000; // Initialize "b" to 0.
#512 $finish; // Simulate for 32x16 = 512 time steps to exercise the entire truth table.
// (32 steps/cycle x 16 cycles)
end
// The next four lines clock the bits of input "b" so as to count up from 0 to 15.
always #2 b[0] = ~b[0]; // (Note: all procedural blocks run concurrently.)
always #4 b[1] = ~b[1];
always #8 b[2] = ~b[2];
always #16 b[3] = ~b[3]; // One complete cycle is 2x16 = 32 time steps.
always #32 a = a+1; // "a" is incremented by one after each complete count of "b".
endmodule
Procedural assignments (inside always blocks) must be made to signals declared as reg. Change:
output Equal;
to:
output reg Equal;
For a shorter, equivalent version:
module equality (
output Equal,
input [3:0] a, b
);
assign Equal = (a == b);
endmodule

"<signal> is not a constant" error in if-statement

I am trying to write a simple module to output a 14-bit number based on the value of four input signals. My attempt is shown below.
module select_size(
input a,
input b,
input c,
input d,
output [13:0] size
);
if (a) begin
assign size = 14'h2222;
end
else begin
if (b) begin
assign size = 14'h1111;
end
else begin
if (c) begin
assign size = 14'h0777;
end
else begin
assign size = 14'h0333;
end
end
end
endmodule
Upon compilation, I receive the following error:
ERROR:HDLCompiler:44 - Line 67: c is not a constant
I don't understand why that particular if-statement isn't working if the other two preceding it are. I have tried changing the condition to
if (c == 1) begin
but to no avail.
Does anybody know how to solve this error? Thank you!
Two problems:
1) You need to put if statements inside an always block.
If you use verilog-2001, you can use
always #*
if ....
end
end
Otherwise specify all the inputs in the sensitivity list:
always #(a or b or c or d)
if ....
end
end
2) Constant assignments are not allowed inside if statements.
Remove the assign keyword from any statements inside the if block:
if (a) begin
size = 14'h2222;
end
You will also have to declare size as a reg type.
However my preference would be to rewrite the entire module with conditional operator, I find it much preferrable to read. This following module achieves the same result:
module select_size(
input a,
input b,
input c,
input d,
output [13:0] size
);
assign size = a ? 14'h2222 :
b ? 14'h1111 :
c ? 14'h0777 :
14'h0333 ;
endmodule
As #Tim has already answered, using reg types inside always blocks or wire with assign.
#Tim has also described the nested ternary assignments, while in the example are written very well, they are generally seen as bad practice. They imply a very long combinatorial path and can be hard to maintain. The combinatorial path may be optimised by synthesis which should imply a mux with optimised selection logic.
Easier to maintain code will have a lower cost of ownership, and as long as it does not lead to a larger synthesised design it is normally preferred.
My implementation would be to use a casez, (? are don't cares). I find the precedence of each value easier to see/debug.
module select_size(
input a,
input b,
input c,
input d,
output logic [13:0] size //logic (SystemVerilog) or reg type
);
always #* begin
casez ({a,b,c})
3'b1?? : size = 14'h2222 ;
3'b01? : size = 14'h1111 ;
3'b001 : size = 14'h0777 ;
3'b000 : size = 14'h0333 ;
default: size = 'bx ;
endcase
end
endmodule

Resources