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
Related
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.
A basic sequence class for randomize reset below:
class random_reset;
rand int rst_period;
constraint rst_range { rst_period inside {[1:100]}; }
task random_system_reset (
ref reg rst,
ref reg clk);
begin
rst = 1;
repeat (rst_period) #(posedge clk);
rst = 0;
end
endtask
endclass
However, I test need at least 6 clocks. Got anyway to make sure when I call this class, will get the random value bigger than 6?
Assuming you want to keep your original constraint as-is, but in some circumstances, you need to enforce the period to be 6 or more, you can use randomize() with:
random_reset rr = new();
initial rr.randomize() with { rst_period >= 6; };
For this rr object, rst_period will be between 6 and 100.
Refer to IEEE Std 1800-2017, section 18.7 In-line constraints—randomize() with.
I write ldpc_if.sv and ldpc_transaction.sv as follows.
"ldpc_if.sv"
interface ldpc_if#(parameter COLS=9216, parameter ROWS=1024) (input clk, input reset);
logic [COLS-ROWS-1:0] en_enq_data;
logic en_enq_valid;
logic en_enq_ready;
logic [ROWS-1:0] en_deq_data;
logic en_deq_valid;
logic en_deq_ready;
logic [COLS-1:0] de_enq_data;
logic de_enq_valid;
logic de_enq_ready;
logic [COLS-1:0] de_deq_data;
logic de_deq_valid;
logic de_deq_ready;
endinterface
"ldpc_transaction.sv"
class ldpc_transaction#(parameter WIDTH=8192) extends uvm_sequence_item;
rand bit [WIDTH-1:0] data;
bit [8191:0] encode_data_in;
bit [1023:0] encode_data_out;
bit [9215:0] decode_data;
`uvm_object_utils(ldpc_transaction)
function new(string name = "ldpc_transaction");
super.new();
endfunction
endclass
And I write ldpc_monitor.sv to monitor interface.
task ldpc_monitor::collect_one_pkt(ldpc_transaction tr);
while(1) begin
#(posedge vif.clk);
if(vif.en_enq_valid && vif.en_enq_ready) break;
end
tr.encode_data_in <= vif.en_enq_data;
while(1) begin
#(posedge vif.clk)
if(vif.en_deq_valid && vif.en_deq_ready) break;
end
tr.encode_data_out <= vif.en_deq_data;
while(1)begin
#(posedge vif.clk)
if(vif.de_deq_valid && vif.de_deq_ready)begin
break;
end
end
tr.decode_data <= vif.de_deq_data;
$display("tr.decode_data = %0h", tr.decode_data);
$display("vif.de_deq_data = %0h", vif.de_deq_data);
endtask
vcs compiles all files successfully. However, tr.decode_data is always displayed as zero. But, vif.de_deq_data is correct. Why is vif.de_deq_data not assigned to tr.decode_data.
It's because the $display you've used to display your transaction is blocking. Conversely, you've used an non-blocking assignment to set tr.decode_data.
Thus, your $display statement actually gets executed before your assignment. Getting a 0 is just an artefact of your simulator - could be any random stuff in the memory assigned to that variable (though most simulators just reset to 0).
Quick search revealed this useful example which illustrates exactly your problem.
https://verificationguide.com/systemverilog/systemverilog-nonblocking-assignment/
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.
I am getting the following error in System Verilog with VCS synthesizer:
The following access has an invalid number of indices.
bus[i]
I am basically trying to do a parametrizable mux made of interfaces, with the select bus being one-hot:
module myMux
#(int unsigned WIDTH=3)
(
my_interface bus[WIDTH-1:0],
input logic [WIDTH-1:0] select,
output logic [31:0] out_data
)
always_comb begin
out_data = 'x;
for (int unsigned i=0; i < WIDTH; i++) begin
if (select[i]) out_data = bus[i].in_data;
end
end
endmodule
I tried the different methods outlined in this answer here (including using |= ) but I always get the same error. Using a "genvar i" instead of an int does not even compile.
If I replace bus[i] with bus[0], then it compiles (but it is not what I want) . . . also, replacing WIDTH with a number in the for statement (ie i < 1) gives me the same error even though it is less than the value of WIDTH.
Any ideas? the code needs to be synthesizable.
Accessing an instances of an arrayed interface can only be accessed via a simulation constant (parameter, genvar, or hard-coded number). Data types and design elements both use dotted names to access there respected member or hierarchical-name, but the rules for accessing index arrays are different. Best description I can quickly find is in IEEE Std 1800-2012 § 23.6 Hierarchical names and § 23.7 Member selects and hierarchical names.
Here are two possible solutions:
Tri-state solution: floating if select is 0, x on the bit with multiple conflicting drivers.
module myMux
#(int unsigned WIDTH=3)
(
my_interface bus[WIDTH-1:0],
input logic [WIDTH-1:0] select,
output wire [31:0] out_data
);
for (genvar i=0; i < WIDTH; i++) begin : loop
assign out_data = select[i] ? bus[i].in_data : 'z;
end
endmodule
Priority selector: using a local 2D array to map the interface instances. This map can be accessed in an always block. If you are on FPGA, this is the better solution as it doesn't need tri-state.
module myMux
#(int unsigned WIDTH=3)
(
my_interface bus[WIDTH-1:0],
input logic [WIDTH-1:0] select,
output logic [31:0] out_data
);
logic [31:0] map [WIDTH];
for (genvar i=0; i < WIDTH; i++) begin : loop
assign map[i] = bus[i].in_data;
end
always_comb begin
out_data = 'x;
for(int unsigned i=0; i<WIDTH; i++) begin
if (select[i]) out_data = map[i];
end
end
endmodule