Simple (yet wrong) Verilog code - verilog

I'm trying to implement an ALU by using Verilog language; as a first approach I want to simulate this very simple version of it:
module alu(opcode, in1, in2, result);
input[4:0] opcode;
input[11:0] in1, in2;
output[11:0] result;
case(opcode)
5'b00000 assign result=in1+in2;
5'b00010 assign result=in1;
5'b00011 assign result=in1+1;
5'b01000 assign result=in1<<1;
5'b01001 assign result=in1>>>1;
5'b10001 assign result=in1 && in2;
5'b10010 assign result=in1 || in2;
endcase
endmodule
Regardless of its simplicity, I'm getting this compilation error:
case(opcode)
|
*E,NOTPAR: Illegal operand for constant expression [4(IEEE)].
I really can't figure out what's wrong with the code.

1) Put case in the combo always block (i.e. always # (*) if you are using verilog 2001 syntax).
2) Drop the assign keyword, declare result as output reg
3) Put : after the condition, like 5'b0000:
4) Take care of the possible overflow in arithmetic operations
5) Logical and and or will give you a 1-bit result, yet you assign it to the 12-bit output. Maybe you wanted a bitwise version of the aforementioned operations (google the difference)?

Related

Best way to optionally register inputs

I have a systemverilog module with a LOT of input signals of varying sizes. I want to optionally register them before use. Here is my desired criteria for the code that does this optional registering:
I should only need to write out the assignments once (no duplicate code)
I should not need to use any macros (I don't want scoping issues)
Here's a minimal reproducible example of my current solution:
module optional_register #(
parameter bit REGISTER_INPUTS=1
)(
input wire clk,
input wire a_in,
input wire b_in,
input wire c_in,
input wire d_in,
output logic a_out,
output logic b_out,
output logic c_out,
output logic d_out
);
function assign_inputs();
a_out <= a_in;
b_out <= b_in;
c_out <= c_in;
d_out <= d_in;
endfunction
generate if (REGISTER_INPUTS) begin
always_ff # (posedge clk)
assign_inputs();
end else begin
always_comb
assign_inputs();
end endgenerate
endmodule
This code synthesizes correctly in Vivado 2020.2 with both the registers on and off. But I am worried that the non-blocking assignments in the function are technically invalid, according to The IEEE Std for Verilog (1364-2001), section "10.3.4 Function rules" which states:
A function shall not have any nonblocking assignments.
So my concern is that this won't work in other synthesizers, and may cause unexpected behavior in simulation. Can anyone speak to this?
Any other ideas?
This is SystemVerilog code, you should be using the IEEE 1800-2017 LRM.
Nonblocking assignments are allowed inside function as long as LHS target is not a variable with an automatic lifetime. Do not use NBA to assign to argument outputs or the return value of a function with a static lifetime because their current values get copied out before the NBA updates happens.
You should declare your function with no return value.
function void assign_inputs();
Using NBAs in combinational logic is not the best for simulation performance, but is usually OK functionality wise.

How to change input signal to parameter in systemverilog?

I have an input logic sequence and I would like to convert it to a parameter in order to add it elsewhere in my program.
For example,
module myModule(input logic[7:0] SW, output logic[7:0] LEDR);
parameter shift = SW;
assign LEDR = SW[shift + 1: shift];
endmodule
I know that's not correct syntax, I just wanted to get the main idea.
Parameters are by definition compile time constants. That means you can not change their value based on an expression that can change over time.
What you can do is change the way you model so it does not require a parameter. For example , you could write your code as
module myModule(input logic[7:0] SW, output logic[7:0] LEDR);
assign LEDR = SW[SW +: 2];
endmodule
You cannot convert a variable to parameter. The value of the parameter will be locked after elaborations. A variable will not have a value until simulation.
Part-select (sometimes called range-slice) should do what you need. See
Indexing vectors and arrays with +: for more info.
Having SW slice itself does make sense since the resulting value would always be 0. Here is better example:
module myModule(input [8:0] IN, input [2:0] SW, output [1:0] LEDR);
assign LEDR = IN[SW +: 2];
endmodule

Verilog Module Instantiation and empty begin end

I have made two verilog modules. The first one takes a nine-bit number and returns the position of first occurrence of 1 in it.
module findPositionOf_1(
input [8:0] data,
output reg [3:0] position
);
always #(data)
begin
if(data==9'b0000_00000)
position=4'b0000;
else if(data[0]==1)
position=4'b0000;
else if(data[1]==1)
position=4'b0001;
else if(data[2]==1)
position=4'b0010;
else if(data[3]==1)
position=4'b0011;
else if(data[4]==1)
position=4'b0100;
else if(data[5]==1)
position=4'b0101;
else if(data[6]==1)
position=4'b0110;
else if(data[7]==1)
position=4'b0111;
else if(data[8]==1)
position=4'b1000;
end
endmodule
The second module is returning the second occurrence of 1. It is calling the first module first changing that bit to zero and again finding the occurrence of 1.
module findPositionOf_2nd_1(
input [8:0] r1_data,
output [3:0] position1
);
reg [3:0] pos,pos2;
reg [8:0] temp;
integer i;
always #(r1_data)
begin
findPositionOf_1 f1(.data(r1_data), .position(pos));
i=pos;
temp=r1_data;
temp[i]=0;
findPositionOf_1 f2(temp,pos2);
if(pos2==4'b0000)
position1=0;
else
position1=pos2;
end
endmodule
I am getting the following errors during compilation. Please help.
Checker 'findPositionOf_1' not found. Instantiation 'f1' must be of a
visible checker.
A begin/end block was found with an empty body. This
is permitted in SystemVerilog, but not permitted in Verilog. Please
look for any stray semicolons.
By the way you write code it seems like you've not completely grasped how verilog(and other HDL languages) is different from "normal", procedural, coding.
You seem to assume that everything inside your always# block will execute from top to bottom, and that modules are similar to functions. This is not the case. You need to think about how you expect the hardware to look when you've designed your module.
In this case you know that you want two findPositionOf_1 modules. You know that you want the result from the first (u_f1) to affect the input of the second (u_f2). To do this, instantiate the two modules and then determine the interconnect between them.
We can create a vector with a 1 in position pos by left-shifting '1 pos number of times (1<<pos). By xor-ing the bits together, the statement r1_data ^ 1<<pos will remove the unwanted 1.
module findPositionOf_2nd_1(input [8:0] r1_data, output [3:0] position1 );
wire [3:0] pos,pos2;
wire [8:0] temp;
findPositionOf_1 u_f1(.data(r1_data), .position(pos));
findPositionOf_1 u_f2(.data(temp), .position(pos2));
assign temp = r1_data ^ (1<<pos);
assign position1 = pos2;
endmodule
You have instantiated your module inside an always block which is a procedural block, which is syntactically incorrect. Secondly, you have used your first module as a function call, which is not permitted. As said, you need to have a separate testbench, where you can connect your both modules and check. Make the position of occurance of 1st one as input to the findPositionOf_2nd_1 module. For your question, perhaps this should help
Why can't I instantiate inside the procedural block in Verilog

How do you manipulate input arrays in an always block (verilog)?

I'm very new to verilog and i'm just starting to understand how it works.
I want to manipulate an input to a module mant[22:0], in an always block but I am not sure how to go about it.
module normalize(mant,exp,mant_norm,exp_norm);
input [22:0]mant;
input [7:0]exp;
output [22:0]mant_norm;
output [7:0]exp_norm;
reg mantreg[22:0];
reg count=0;
always#(mant or exp)
begin
mantreg<=mant; //this gives an error
if(mant[22]==0)
begin
mant<={mant[21:0],1'b0};//this also gives an error
count<=count+1;
end
end
endmodule
so i have to shift the mant register if the bit22 is zero and count the number of shifts. I am so confused about when to use reg and when to use wire and how to do the manipulation. please help let me know how to go about it.
As you can see in your code you are assigning vector value (mant) to array of 23(mantreg). Instead you should declare mantreg as reg [22:0] mantreg (which is vector of 23 bit).
Wire type variable can not be assigned procedurally. They are used only in continues assignment. Other way around reg varible can only be procedural assigned.
For that try to read out LRM of Verilog .

Getting strange error in verilog (vcs) when trying to use if/else blocks

I am trying to write an "inverter" function for a 2's compliment adder. My instructor wants me to use if/else statements in order to implement it. The module is supposed to take an 8 bit number and flip the bits (so zero to ones/ones to zeros). I wrote this module:
module inverter(b, bnot);
input [7:0] b;
output [7:0]bnot;
if (b[0] == 0) begin
assign bnot[0] = 1;
end else begin
assign bnot[0] = 0;
end
//repeat for bits 1-7
When I try and compile and compile it using this command I got the following errors:
vcs +v2k inverter.v
Error-[V2005S] Verilog 2005 IEEE 1364-2005 syntax used.
inverter.v, 16
Please compile with -sverilog or -v2005 to support this construct: generate
blocks without generate/endgenerate keywords.
So I added the -v2005 argument and then I get this error:
vcs +v2k -v2005 inverter.v
Elaboration time unknown or bad value encountered for generate if-statement
condition expression.
Please make sure it is elaboration time constant.
Someone mind explaining to me what I am doing wrong? Very new to all of this, and very confused :). Thanks!
assign statements like this declare combinatorial hardware which drive the assigned wire. Since you have put if/else around it it looks like you are generating hardware on the fly as required, which you can not do. Generate statements are away of paramertising code with variable instance based on constant parameters which is why in this situation you get that quite confusing error.
Two solutions:
Use a ternary operator to select the value.
assign bnot[0] = b[0] ? 1'b0 : 1'b1;
Which is the same as assign bnot[0] = ~b[0].
Or use a combinatorial always block, output must be declared as reg.
module inverter(
input [7:0] b,
output reg [7:0] bnot
);
always #* begin
if (b[0] == 0) begin
bnot[0] = 1;
end else begin
bnot[0] = 0;
end
end
Note in the above example the output is declared as reg not wire, we wrap code with an always #* and we do not use assign keyword.
Verliog reg vs wire is a simulator optimisation and you just need to use the correct one, further answers which elaborate on this are Verilog Input Output types, SystemVerilog datatypes.

Resources