Why is wire variable causing illegal left-hand side in continuous assignment? - verilog

I have read through all similar posts, but none address the issue I'm having, namely that line 41 assign Y[b]=~Y[b]; causes error "Illegal left-hand side in continuous assignment."
I haven't assigned any regs so I don't see what the issue is. If I replace b with an actual number (say, 3) it works fine. But I need b as a variable here.
// Hamming code 1-bit error correction
module HCG(I,e,O);
input [4:1] I; // input BCD
input [7:1] e; // noise simulation
wire [7:1] X; // Hamming code
wire [7:1] Y; // Hamming code after addition of noise
wire [3:1] P; // Parity at start
wire [3:1] S; // Parity at end
wire b; // the error bit
output [4:1] O; // corrected output
assign X[1]=I[1]^I[2]^I[4]; // Hamming code generator
assign X[2]=I[1]^I[3]^I[4];
assign X[3]=I[1];
assign X[4]=I[2]^I[3]^I[4];
assign X[5]=I[2];
assign X[6]=I[3];
assign X[7]=I[4];
assign P[1]=X[1]; // Parity at start
assign P[2]=X[2];
assign P[3]=X[4];
assign Y[1]=e[1]^X[1]; // noise added
assign Y[2]=e[2]^X[2];
assign Y[3]=e[3]^X[3];
assign Y[4]=e[4]^X[4];
assign Y[5]=e[5]^X[5];
assign Y[6]=e[6]^X[6];
assign Y[7]=e[7]^X[7];
assign S[1]=Y[3]^Y[5]^Y[7]; // Parity at end
assign S[2]=Y[3]^Y[6]^Y[7];
assign S[3]=Y[5]^Y[6]^Y[7];
assign b=(S[1]!=P[1])? b:b+1; // if parity of 2^0 not the same, add 1 to b
assign b=(S[2]!=P[2])? b:b+2; // if parity of 2^1 not the same, add 2 to b
assign b=(S[3]!=P[3])? b:b+4; // if parity of 2^2 not the same, add 4 to b
assign Y[b]=~Y[b]; // correct the incorrect bit
assign O[1]=Y[3]; // assigning outputs
assign O[2]=Y[5];
assign O[3]=Y[6];
assign O[4]=Y[7];
endmodule

The lines between module and endmodule are executed concurently. (It seems like you think they are executed sequentially.) Therefore, you are driving all the bits of Y in these lines
assign Y[1]=e[1]^X[1]; // noise added
assign Y[2]=e[2]^X[2];
assign Y[3]=e[3]^X[3];
assign Y[4]=e[4]^X[4];
assign Y[5]=e[5]^X[5];
assign Y[6]=e[6]^X[6];
assign Y[7]=e[7]^X[7];
and then are driving one of the bits of Y again in this line:
assign Y[b]=~Y[b]; // correct the incorrect bit
So (a) you have a short circuit and (b) which bit has the short circuit? That depends on b. So, the position of the short circuit depends on the state of one of the internal wires. You have described a circuit that can reconfigure itself depending on its inputs. Verilog won't let you do that. Verilog is a hardware description language. Conventional digital hardware can't reconfigure itself depending on the state of its inputs.

The problem is the continuous assignment you are doing. To quote from the IEEE Std 1800-2012. (Section 10.3) on continuous assignments:
Continuous assignments shall drive values onto nets or variables, both vector (packed) and scalar. This assignment shall occur whenever the value of the right-hand side changes. Continuous assignments provide a way to model combinational logic without specifying an interconnection of gates.
When you do assign Y[b]=~Y[b], the assignment itself automatically causes the right-hand side to change again, which triggers the assignment again.

Verilog standard lists legal lhs values for the continuous assignment as the following (Table 10-1):
Net or variable (vector or scalar)
Constant bit-select of a vector net or packed variable
Constant part-select of a vector net or packed variable
Concatenation or nested concatenation of any of the above left-hand sides
in your case Y[b] is not a constant selection, because b is not a constant. Therefore syntactically your lhs is illegal and you get this message from the compiler.
On a side note you have a zero-delay loop here. See other answers for explanation.

Related

System Verilog attaching vector [10..0] to integer

module rocket_move (
input logic clk,
input logic resetN,
input logic signed [10:0] spaceship_X,
input logic signed [10:0] spaceship_Y,
output logic signed [10:0] rocket_topLeftX, // output the top left corner
output logic signed [10:0] rocket_topLeftY // can be negative
);
// a module used to generate the rocket trajectory.
int x = spaceship_X[10:0];
int y = spaceship_Y[10:0];
Im trying to attach a rocket bitmap to the center of spaceship bitmap which i've already build and works,
spaceship_[10..0] is vector that holds position on axis X and Y of a spaceship, im trying to use a variable for future calculations but i get error every time, i've tried to do calculations straigh with spaceship_X[10..0], in that case i dont get an error but cant see the rocket bitmap either. thanks in advance
"Error (10748): Verilog HDL error at rocket_move.sv(26): expression in variable declaration assignment to x must be constant"
Assigning an int at its declaration will give it an initial value at time zero. At the time off assignment the spaceship X/Y value is still its type’s default value.
Assuming x/y are only driven by spaceship X/Y you code do the following:
int x,y;
always_comb begin
x = spaceship_X[10:0];
y = spaceship_Y[10:0];
end
Or:
int x,y;
assign x = spaceship_X[10:0];
assign y = spaceship_Y[10:0];
If x/y have mutual assignment, then handle all the assignment conditions within the always_comb. If the variables are synchronous, then use always_ff #(posedge clk) block with non-blocking assignment (<=).

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 data types

I am studying verilog as part of my university course however my module lecturer left so I was hoping for some help here,
An example we have been given for a parametric n-bit gray to binary code converter, as follows:
module bin_n_gray #(parameter n=4) (input [n-1 : 0] gray, output [n-1 : 0] bin);
integer i;
always # (*)
for(i = 0; i < n; i = i+1)
bin[i] = ^(gray >> i);
endmodule
My question:
As the bin[i] variable is on the left hand side of an assignment statement within an # always block shouldn't this variable be declared as output reg [n-1 : 0] bin?
As I thought that a variable on the left hand side of an assignment statement of a process block i.e always / initial should be declared as a reg datatype?
As the bin[i] variable is on the left hand side of an assignment statement within an '# always' block shouldn't this variable be declared as 'output reg [n-1 : 0] bin?
Yes, it should require the reg as you say, at least according to Xilinx XST. The code as given in your question errs when synthesizing using that tool (and is missing an unrelated semicolon).
First let's begin by understanding what a procedural block in Verilog is, exactly (with the assumption that we're using Verilog to develop hardware, such as an FPGA design). Procedural blocks are always blocks (of two types, combinational and sequential) as well as few other types of blocks we won't cover here. The first thing to know is that in a procedural block, the only assignments allowed are those that have a reg on the left hand side.
This doesn't necessarily mean that a physical register/flipflop will be created. In this case, one will not be. The reason is the declaration of the block as always # (*). This declaration means that the process is combinational (i.e. not sequential, not having any internal state or clock signal). As a result, no physical flip-flops are created.
Alternatively, you can have a procedural block declared as always # (posedge some_clock_signal). This means that sequential logic is created, and physical flip-flops (or other means of storage such as the distributed memory in FPGA lookup tables) may be used. The takeaway is that you're still declaring as reg there, but now you're actually creating registers.
There is one case where you use wire (or output), which is by continuous assignment (for example, assign a = b & c), which falls outside a procedural block. In this example, I'm using generate to do the same thing as the loop in your original code:
module bin_n_gray #(parameter n=4) (input [n-1 : 0] gray, output [n-1 : 0] bin);
genvar i;
generate
for (i=0; i < n; i=i+1)
begin: graydecoder // arbitrary label needed by generate syntax
assign bin[i] = ^(gray >> i);
end
endgenerate
endmodule

Verilog: Passing parameters

I have written two verilog modules. The first one is named topmodule.v and the second one is tx.v. The module topmodule.v pass a parameter data[31:0] to tx.v. I want to take the variables Rmax and Cmax from data[31:0]. After that I want to make Rmax and Cmax to be the width of a bus. Moreover, I want to define a reg matrix called Mat with dimensions Cmax-x-Rmax. I receive the error at the 6th line of the code, "Range must be bounded by constant expression". Kindly help me to resolve this problem. The code is given below.
tx (data, output)
input [31:0] data;
reg [15:0] Rmax, Cmax;
assign Rmax [15:0] = data [31:16];
assign Cmax [15:0] = data [15:0];
reg [Rmax-1:0] Matrix [0:Cmax-1];
The error means pretty much what it says, you cannot have a variable size bus or array.
Declare your matrix to be the maximum size that you ever need, and if you want to use a smaller one, then just use a subsection of it while leaving the rest vacant.
Remember that the width of buses are physical objects, they can't change when the circuit is running, only during synthesis.
If you really want these to be parameters then use that:
module tx #(parameter DATA=32'h00000000) (
// inputs and outputs here
);
reg [DATA[31:16]-1:0] Matrix [0:DATA[15:0]-1];
However, I'm not really sure of what you are trying to accomplish. Show some more pseudo code and get a more useful answer.

Verilog: Can you put "assign" statements within always# or begin/end statements?

Is this allowed?
input w;
input [8:0]y;
output reg [8:0]x;
always#(w)
begin
//x[0] or A is never on in any next state
assign x[0] = 0;
assign x[1]= (y[0]&~w) | (y[5]&~w) | (y[6]&~w) | (y[7]&~w) | (y[8]&~w); //B
assign x[2]= (y[1]&~w); //C
assign x[3]= (y[2]&~w); //D
assign x[4]= (y[3]&~w) | (y[4]&~w); //E
assign x[5]= (y[0]&w) | (y[1]&w) | (y[2]&w) | (y[3]&w) | (y[4]&w); //F
assign x[6]= (y[5]&w);
assign x[7]= (y[6]&w);
assign x[8]= (y[7]&w) | (y[8]&w);
end
You can, it's called a "Procedural Continuous Assignment". It overrides ordinary procedural assignments, there doesn't seem to be a call for them in the code you've posted. I'm not sure if they're synthesisable, but I never have cause to use them anyway.
A note on your code - you're missing y from your sensitivity list: eg always #( w or y ) or always #(*) is safer.
Building upon Marty's answer, you should read section 9.3 of the IEEE Verilog Standard (1364-2005, for example), where it describes "Procedural Continuous Assignment". The spec allows for assign statements within an always block. However, from my experience, it is quite rare.
Another issue with your code is that it has compile errors with two different simulators that I tried. Both generate error messages that bit-selects or part-selects cannot be used on the left hand side of the assignment.
Another possible solution is to get rid of the always block, and just use simple continuous assignments.
input w;
input [8:0] y;
output [8:0] x;
assign x[0] = 0;
assign x[1]= (y[0]&~w) | (y[5]&~w) | (y[6]&~w) | (y[7]&~w) | (y[8]&~w); //B
assign x[2]= (y[1]&~w); //C
assign x[3]= (y[2]&~w); //D
assign x[4]= (y[3]&~w) | (y[4]&~w); //E
assign x[5]= (y[0]&w) | (y[1]&w) | (y[2]&w) | (y[3]&w) | (y[4]&w); //F
assign x[6]= (y[5]&w);
assign x[7]= (y[6]&w);
assign x[8]= (y[7]&w) | (y[8]&w);
The procedural continuous assign statement was intended to be an optimized way of writing a mux-like behavior. For example, if you have
always #(A or B or select)
if (select)
out = A;
else
out = B;
You could write this as
always #(select)
assign out = A;
else
assign out = B;
But people don't like having to deal with sensitivity lists, so #(*) was added to Verilog, and SystemVerilog added always_comb.
But the real killer for this construct is that many people would write code like
always #(*)
assign out = A;
Which simulates fine, but you now have a double penalty in performance because the assign statement is already sensitive to changes in A, but so is the always block. This repeatedly executes the procedural assign statement replacing the same RHS.
Assign is a continuous assignment statement which is used with wires in Verilog. assign statements don't go inside procedural blocks such as always. Registers can be given values in an always block.
Assign statements can be viewed as:
always #(*)
statements for wires.
Yes, but you don't want to. Since x[] doesn't depend on x[] the order doesn't matter. Just use <= instead of assign =.
There is no need using assign inside a procedural block (In this case Always)
Assign is a continuous assignment, and it has to go outside a procedural block.
Thinking from the circuit level: this always(w) begin ..... end , so every code inside it will be activated whenever w is changed ie it falls or raise .
assign statement requires pin/port which it assign to some wire or reg output
its a complete combinational circuit I am unable to see how the same will only activate at w, that is who/what circuit will make it to only change when w either rises or fall
anyway you cant assign a reg output to some wire/reg output using assign statement because as I said it requires you to put pin/port to be assigned only
anyway if you go for basic verilog and not so called "Procedural Continuous Assignment" i guess its weird to use the same .

Resources