How to get rid of illegal operand error in always_comb block when used "==" operator in SystemVerilog - system-verilog

I keep getting the error
illegal operand for operator "==" at the code block below
module ALU(input logic oppCode[2:0], input logic [3:0] rf1, input logic [3:0] rf2
,output logic [3:0] result, output logic EQ );
always_comb begin
if(oppCode == 3'b010) begin // Problem
result <= rf1 - rf2;
end
else if(oppCode == 3'b101) begin // Problem
result <= rf1 + rf2;
end
else if(oppCode == 3'b111) begin // Problem
EQ <= (rf1 == rf2);
end
end
endmodule
What I want to do here, is comparing the oppCode with hard coded instruction types. But I keep getting the Illegal operand for "==" error.
"==" is logical comparison operator so why it is not comparing?
How can I get rid of this?

In your code, oppCode is unpacked (logic oppCode[2:0]).
You can't compare an unpacked value with a packed value (3'b010).
Either make oppCode packed logic [2:0] oppCode or add an intermediate signal to convert the unpacked oppCode to a packed version with an always_comb and a for loop or just manually.
logic [2:0] oppCode_packed;
always_comb begin
for (int i=0; i<3; i++) begin
oppCode_packed[i] = oppCode[i];
end
end
and then use oppCode_packed in your comparisons.
Piece of advice: when you declare an unpacked signal, use the number of bits/elements you want: logic oppCode[3]. That's more lisible and you'll be less likely to confuse them.

Related

How to slicing array interface in system verliog

I try to use array interface mapping through always_comb procedure instead of generate a statement.
You can see my test codes is in below(https://www.edaplayground.com/x/5cLt)
interface tintf;
bit valid;
bit data;
bit stall;
endinterface: tintf
module top;
tintf intf_a[0:3]();
bit valid, data, stall;
always_comb begin
loop_for_mapping:
for(int i = 0; i < 4; i++) begin
intf_a[i].valid = valid;
intf_a[i].data = data;
end
end
endmodule
But I see the error message below.
intf_a[i].valid = valid;
| ncelab: *E,NOTPAR (./testbench.sv,18|13): Illegal operand for constant expression [4(IEEE)].
I don't know that is why illegal...As I know 'i' in for-loop is considered constant.
Would you let me know what I missing??
It may be true for synthesis the for loop gets unrolled into a constant set of iterations, but it's not a constant from a language point of view. Simulation tools don't know which portions of your code you plan to synthesize. You need to write this as a generate-for loop.
for(genvar i = 0; i < 4; i++) begin : loop_for_mapping
always_comb begin
intf_a[i].valid = valid;
intf_a[i].data = data;
end
end
instantiating an interface (or a module) as an array (arrayed instance) is a part of the generate feature of verilog. As a result, you can only access those by using literal constants (0,1,2...) or from other generate blocks (see dave_59's answer).
It can be more flexible if you make arrays of the interface variables instead:
interface tintf;
bit [3:0] valid;
bit [3:0] data;
bit [3:0] stall;
endinterface: tintf
module top;
tintf intf_a();
bit valid, data, stall;
always_comb begin
loop_for_mapping:
for(int i = 0; i < 4; i++) begin
intf_a.valid[i] = valid;
intf_a.data[i]= data;
end
end
endmodule

SystemVerilog 2-bit register decoding problem

I have two 2-bit inputs and an output of 1-bit. So what I'm trying to do is code a next state value with taking AND of the two inputs, then use non-blocking <= to assign that value into register xy_r, which is now two D-flipflops. So I am seeking to get always the XOR-value of the xy_r previous clock edge as my output xor_out. I suppose that the way below is not the right one?
It worked in the simulation but then again in RTL Synthesis I didn't end up with an XOR gate but a third flip-flop so it seems like xor_out is treated as a register.
I suppose I can't use assign outside of the if-else-statements because in that case the output wouldn't follow the xy_r previous state but the present.
Can you please assist me how to solve this issue, if there is a somewhat simple way.
module 2ffsxor
(input logic clk,
input logic rst_n,
input logic [1:0] x_in,
input logic [1:0] y_in,
output logic xor_out
);
logic [1:0] xy;
logic [1:0] xy_r;
always # (posedge clk or negedge rst_n)
begin
if (rst_n == '0)
xy_r <= '0;
else
begin
xy = x_in & y_in;
xy_r <= xy;
xor_out = xy_r[0] ^ xy_r[1];
end
end
endmodule
And here's a schematic what it should be:
Schematic 2ffsxor
Synthesis treats this code as if you had wrote
begin
xy_r <= x_in & y_in;
xor_out <= xy_r[0] ^ xy_r[1];
end
That's two stages of registers. But since you assigned xor_out with a blocking assignment, you have a simulation race condition for any process that tries to read xor_out. The race would be from the result from the previous values of xy_r and the result before that!
If you use an continuous assign statement outside this always block, any process reading xor_out on the clock edge will see the result from the previous state of xy_r.
But why not write this as on register:
always # (posedge clk or negedge rst_n)
begin
if (rst_n == '0)
xor_out <= '0;
else
begin
xy = x_in & y_in;
xor_out <= xy[0] ^ xy[1];
end
end

Using don't-care in enumeration typedef in synthesizable SystemVerilog

I have the following code:
typedef enum logic [1:0] {
CMD1 = 2'b1?,
CMD2 = 2'b01,
CMD3 = 2'b00
} cmd_t;
Basically, if the MSB is 1, it's CMD1 (I'll use the LSB for part of the index). And if the MSB is 0, then decode the rest of bits for the command.
I then try to decode using an always_comb:
cmd_t myCmd;
always_comb begin
casez(myCmd)
CMD1: isCmd1 = 1'b1;
CMD2: isCmd1 = 1'b0;
default: isCmd1 = 1'b0;
endcase
end
Unfortunately, I get this message from Spyglass:
[12EE] W467 Based number 2'b1? contains a don't-care (?) - might lead to simulation/synthesis mismatch
This code should be synthesizable, no? Can this Spyglass warning be waived safely?
I doubt this will synthesise correctly. I think the Spyglass message is misleading. In Verilog (and SystemVerilog) ? means exactly the same as z. You are specifying an enum with 4-state base type values, where CMD1 is to be represented exactly by 2'b1z.

How to assign an unpacked array of real?

While updating Modelsim from 10.3c to 10.6a, I encountered an error on this piece of code that used to not work without warning:
module test(
input bit clk,
input bit signed[31:0] data
);
real rdata_dl[19:0] = '{20{0}};
real rdata = 0;
always #(posedge clk) begin
rdata_dl = {rdata_dl[18:0], rdata};
rdata = data;
end
endmodule
-- Compiling module test
** Note: test.sv(10): (vlog-13177) Promoting concatenation '{rdata_dl[18:0],rdata}' to an assignment pattern: Assigning to a real/wreal array.
** Error (suppressible): (vlog-13215) test.sv(10): Assignment pattern element 'rdata_dl[18:0]': Cannot assign an unpacked type 'real $[18:0]' to a packed type 'real'.
** Error (suppressible): test.sv(10): (vlog-13174) Illegal assignment pattern. The number of elements (2) doesn't match with the type's width (20).
I managed to fix it by using this line instead: rdata_dl = {rdata_dl[18:0], real'(rdata)};.
However, I fail to understand why it failed and why the new version would work. Can anyone explain?
not sure what you are trying to do with this code. real type is 64-bit. When concatenating it with 19-bits, you're getting a 83-bit bus, where the rdata is in the LSBs.
Now, when assigning this 83-bit vector to a 20-bit bus, it will take the 20 LSBs, meaning that it is equivalent to writing the following assignment:
always #(posedge clk) begin
rdata_dl = rdata[19:0];
rdata = data;
end

LFSR description right?

I wrote a 32-bit LFSR based on the taps from [1]. I want to ask if the following description is right for the 32-bit LFSR with the taps 32,22,2 and 1.
module lfsr (
input logic clk_i,
input logic rst_i,
output logic [31:0] rand_o
);
logic[31:0] lfsr_value;
assign rand_o = lfsr_value;
always_ff #(posedge clk_i, negedge rst_i) begin
if(~rst_i) begin
lfsr_value <= '0;
end else begin
lfsr_value[31:1] <= lfsr_value[30:0];
lfsr_value[0] <= ~(lfsr_value[31] ^ lfsr_value[21] ^ lfsr_value[1] ^ lfsr_value[0]);
end
end
endmodule
[1] http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf
Looks Ok. you could also use an XOR, instead of an XNOR, as long as you reset to something else (the XOR version locks up at all 0's, the XNOR at all 1's).
For many apps the pseudo-random output is the single bit you shift out (31 in your case), rather than the entire register. It's also (more?) common to shift right, and put the XOR data in the top bit, and use the bit 0 output as your PR data.
Your code is specifically SystemVerilog, and not Verilog, so I've removed the Verilog tag.