I am a beginner in systemverilog and I tried to make a complex code used to compare between two mailboxes
and it gives me these errors in simulation
enter image description here
//the package code
package types;
typedef struct{
int pid;
}packet;
endpackage
//the main code
module mbox;
import types::*;
//Declare two mailboxes here
mailbox exp_mb = new(256);
mailbox act_mb = new(256);
// This task supplies stimulus to the two mailboxes
task stimulus();
packet stim_pkt;
for (int i = 0; i < 256; i++) begin
stim_pkt.pid = i;
//*** Write stim_pkt to both mailboxes here
exp_mb.put(stim_pkt);
act_mb.put(stim_pkt);
$display("Sending pkt: ",i);
end
endtask
// Add task checker here
task check(input mailbox exp_mb ,act_mb);
bit com;
packet x;
packet y;
for (int i = 0; i < 256; i++) begin
x.pid = exp_mb.get(i) ;
y.pid = act_mb.get(i);
com = compare(x,y);
if (com == 1)
$display ("No Error");
else
$display ("Error in %d", i);
end
endtask
// Add function compare here
function bit unsigned compare (packet a ,b);
if (a.pid == b.pid)
return 1;
else
return 0;
endfunction// Add an initial block to run stimulus & checker tasks simultaneously
initial
begin
fork
stimulus();
check(exp_mb ,act_mb);
join_none
end
endmodule
The error message tells you exactly what the problem is. The mailbox get() method does not return a value, it places a value in its argument.
I believe you want
exp_mb.get(x) ;
act_mb.get(y);
Also, A good idea is add types to your mailboxes. Will become very helpful in getting compile errors instead of runtime errors as your code grows and the number of different packet types grow.
mailbox #(packet) exp_mb = new(256);
mailbox #(packet) act_mb = new(256);
...
task check(mailbox #(packet) exp_mb ,act_mb);
Related
This question already has an answer here:
Compilation error: A net is not a legal lvalue in this context
(1 answer)
Closed last year.
The community reviewed whether to reopen this question last year and left it closed:
Original close reason(s) were not resolved
I am looking to create a FIFO using a 2D array (P_MDIM is the width of each vector, P_NDIM is the depth of the array/memory to store these vectors).
I am having trouble with the above error message on many spots in my code (assigning to out, full, and empty).
I don't know why it occurs. I thought my array ("memory") would be a 2D array of reg (not nets). Below is my full code:
module fifo( signal, enqueue, dequeue, clk, out, full, empty );
//depth of the memory
parameter P_NDIM = 16;
//width of each memory cell(in bits)
parameter P_MDIM = 16;
input [P_MDIM - 1:0] signal;
input enqueue;
input dequeue;
input clk;
output [P_MDIM - 1:0] out;
output full;
output empty;
logic [P_MDIM - 1:0] [P_NDIM - 1:0] memory = 0;
integer enqueue_pos = 0;
integer i = 0;
always #(posedge clk) begin
//enqueue data
if(enqueue) begin
//checking if memory is full
if(enqueue_pos == P_NDIM - 1) begin
$display("data not entered, memory full");
end
//add signal into memory
else begin
memory[enqueue_pos][P_MDIM-1:0] = signal;
enqueue_pos <= enqueue_pos + 1;
end//else
end//if enqueue
//dequeue data
if(dequeue) begin
//checking if memory is empty
if(enqueue_pos == 0) begin
$display("no data to dequeue, memory empty");
out[P_MDIM-1:0] = 0;
end
//output signal from memory, shift memory
else begin
out = memory[0][P_MDIM - 1:0];
enqueue_pos <= enqueue_pos - 1;
for(i = 0; i <= P_NDIM - 2; i = i + 1) begin
memory[i][P_MDIM-1:0] = memory[i + 1][P_NDIM-1:0];
end//for
end//else
end//if dequeue
//check full and empty
full = (enqueue_pos == P_NDIM-1 ? 1'b0 : 1'b1);
empty = (enqueue_pos == 0 ? 1'b0 : 1'b1);
end//always
endmodule
You declared out as a net type, but then you assigned to it inside a procedural always block. Signals assigned in a procedural block should be declared as logic:
Change:
output [P_MDIM - 1:0] out;
output full;
output empty;
to:
output logic [P_MDIM - 1:0] out;
output logic full;
output logic empty;
Unrelated to the error, in your always block, you are using a mixture of blocking (=) and nonblocking (<=) assignments. They should all be nonblocking.
I'm having an issue with my SV code. I'm attempting to simulate a carry look ahead adder. However, when I look at my timing results
they show result has having an x propagated, as well as SUM.
Here is my SystemVerilog code
module fulladder (input logic i_bit1, i_bit2, i_carry,
output logic o_sum, o_carry);
assign o_sum = i_bit1 ^ i_bit2 ^ i_carry;
assign o_carry = (i_bit1 & i_bit2) | (i_carry & (i_bit1 ^ i_bit2));
endmodule
module carry_lookahead_adder
#(parameter WIDTH)
(input logic [WIDTH-1:0] i_add1,
input logic [WIDTH-1:0] i_add2,
output logic [WIDTH:0] o_result
);
logic [WIDTH:0] w_C;
logic [WIDTH-1:0] w_G, w_P, w_SUM;
//Generate full adders
genvar i;
generate for (i= 1; i<WIDTH; i++)
begin : f_loop
fulladder fi (
.i_bit1(i_add1[i]),
.i_bit2(i_add2[i]),
.i_carry(w_C[i]),
.o_sum(w_SUM[i]),
.o_carry()
);
end
endgenerate
genvar jj;
generate
for (jj=0; jj<WIDTH; jj++)
begin
assign w_G[jj] = i_add1[jj] & i_add2[jj];
assign w_P[jj] = i_add1[jj] | i_add2[jj];
assign w_C[jj+1] = w_G[jj] | (w_P[jj] & w_C[jj]);
end
endgenerate
assign w_C[0] = 1'b0; //No carry input
assign o_result = {w_C[WIDTH], w_SUM};
endmodule
and the testbench
module carry_lookahead_adder_tb (w_RESULT);
parameter WIDTH = 32;
logic [WIDTH-1:0] r_ADD_1 = 0;
logic [WIDTH-1:0] r_ADD_2 = 0;
output logic [WIDTH:0] w_RESULT;
carry_lookahead_adder #(.WIDTH(WIDTH)) carry_lookahead_inst
(
.i_add1(r_ADD_1),
.i_add2(r_ADD_2),
.o_result(w_RESULT)
);
initial
begin
$dumpfile("dump.vcd");
$dumpvars;
#10;
r_ADD_1 = 32'b00000000000000000000000000000000;
r_ADD_2 = 32'b00000000000000000000000000000001;
#10;
r_ADD_1 = 32'b00000000000000000000000000000010;
r_ADD_2 = 32'b00000000000000000000000000000010;
#10;
r_ADD_1 = 32'b00000000000000000000000000000101;
r_ADD_2 = 32'b00000000000000000000000000000110;
#10;
r_ADD_1 = 32'b00000000100000000000000000000101;
r_ADD_2 = 32'b00000000100000000000000000000110;
#10;
r_ADD_1 = 32'b11111111111111111111111111111111;
r_ADD_2 = 32'b11111111111111111111111111111111;
#10;
r_ADD_1 = 32'b00000000000000000000000000000000;
r_ADD_2 = 32'b00000000000000000000000000000001;
#10;
end
endmodule // carry_lookahead_adder_tb
Can anyone clue me into what may be causing this x? Sorry to post my full code; I'm just lost as to where the problem may be coming from.
Bit [0] of w_SUM is unknown because you are not driving it. Change the generate for loop so that the count starts from 0, not 1. Change:
generate for (i= 1; i<WIDTH; i++)
to:
generate for (i= 0; i<WIDTH; i++)
After this change, the x goes away.
The problem was that the for loop was not generating the right number of fulladder instances: you need 32, but you only got 31. There was no fulladder instance for you to connect w_SUM[0], i_add1[0], etc., to.
I'm designing a module that accepts multiple channels and outputs one channel.
Each channel consists of valid signal and data of some widths.
If a channel has valid data, the module should output that channel. If multiple channels have valid data, the module should output one of them (in my case, channel with highest index) and rests are dropped.
My simple implementation looks like this:
module test1 #(
parameter NUM_CHANNEL = 8,
parameter DATA_WIDTH = 512
) (
input logic [DATA_WIDTH - 1 : 0] data_in [NUM_CHANNEL],
input logic valid_in [NUM_CHANNEL],
output logic [DATA_WIDTH - 1 : 0] data_out,
output logic valid_out
);
always_comb begin
valid_out = 0;
for (int i = 0; i < NUM_CHANNEL; ++i) begin
if (valid_in[i]) begin
valid_out = 1;
data_out = data_in[i];
end
end
end
endmodule
This works perfectly in both simulation and real circuit (FPGA).
However, channel can be complex type so I used interface like this:
interface channel #(
parameter DATA_WIDTH = 512
);
logic valid;
logic [DATA_WIDTH - 1 : 0] data;
modport in (
input valid,
input data
);
modport out (
output valid,
output data
);
endinterface // sub_csr_if
module test #(
parameter NUM_CHANNEL = 8,
parameter DATA_WIDTH = 512
) (
channel.in in[NUM_CHANNEL],
channel.out out
);
always_comb begin
out.valid = 0;
for (int i = 0; i < NUM_CHANNEL; ++i) begin
if (in[i].valid) begin
out.valid = 1;
out.data = in[i].data;
end
end
end
endmodule
Then, this code gets Nonconstant index into instance array 'sub_port'. error in ModelSim, and i is not a constant error in Quartus.
If I unroll the loop, it works but it becomes non-parametric code. (only works for fixed NUM_CHANNEL)
Why the latter one does not work, while the first one works flawlessly?
An array of instances (module or interface) is not a true array type. As your error message indicates, you cannot select a particular instance with a variable index. With a true array, every element is identical. Because of the way parameterization, defparam, and port connections work, each instance element could have differences. The elaboration process essentially flattens all hierarchy before simulation begins.
What you can do is use a generate construct to select your instance as follows
;
module test #(
parameter NUM_CHANNEL = 8,
parameter DATA_WIDTH = 512
) (
channel.in in[NUM_CHANNEL],
channel.out out
);
logic _valid[NUM_CHANNEL];
logic [DATA_WIDTH - 1 : 0] _data[NUM_CHANNEL];
for (genvar ii=0;ii<NUM_CHANNEL;ii++) begin
assign _valid[ii] = in[ii].valid;
assign _data[ii] = in[ii].data;
end
always_comb begin
out.valid = 0;
for (int i = 0; i < NUM_CHANNEL; ++i) begin
if (_valid[i]) begin
out.valid = 1;
out.data = _data[i];
end
end
end
endmodule
I have written system verilog code for reading data from an image file (800*600 -
*.raw).
The file actually contains 800 * 600 * 3 bytes. But my code can only read upto almost
half the data.
After that the read data seems to be "00".
Valuable suggestions for resolving this is appreciated..
My code is as follows.
//`define EOF 32'hFFFF_FFFF
//`define EOF \n
reg [7:0]data_byte;
class input_video_IF;
int count;
integer input_file, fread_return,output_file;
function new ();
input_file = $fopen("test_800.raw","r");
if(input_file)
begin
$display("File OPENED");
end
else
begin
$display("File error");
end
output_file = $fopen("output_800.raw", "w");
endfunction:new
task image_file_read();
count = 0;
//while (!$feof(input_file))
while(count != 1440000)
begin
fread_return = $fread(data_byte,input_file);
count++;
$display("%d %h",count,data_byte);
//$fwrite(output_file,data_byte);
end
$finish;
$fclose(input_file);
endtask : image_file_read
endclass
program Image_read_test;
int input_file;
input_video_IF In_IF = new();
initial
In_IF.image_file_read();
endprogram
I am trying to randomize an address which should be not fall in a previously allocated segment
suppose if I was allocated address 0, 10 ,40 , and the block length is 5,
when I randomized the address , it should not fall in the range of (0-4) ,( 10-14) , (40-44).
how can I constraint this in system verilog.
I tried a method but it is not working.
Here is my code:
constraint con {
foreach(keys[i]){
!(address inside {[keys[i]:keys[i]+BLOCK_SIZE]});
}
}
keys is array of address that were already alloted , generated address should not fall in the above ranges.
thanks
shiva
Your syntax seems correct to me. What issue do you see with it?
I tried the above and it works for me. See below code.
class t_constraints;
randc bit [2:0] addr; //using randc just to make all values appear.
int keys [2] = {0,4}; // Implies addr {0:1 and 4:5 should not assigned}
int BLOCK_SIZE = 1;
constraint con { foreach(keys[i])
{!(addr inside {[keys[i]:keys[i]+BLOCK_SIZE]});}
}
endclass: t_constraints
module tb_con;
t_constraints t_con;
initial begin
t_con = new();
repeat(8) begin
t_con.randomize();
$display("addr = %h",t_con.addr);
end
$finish;
end
endmodule: tb_con
Below is the log, It seems perfect.
addr = 3
addr = 6
addr = 7
addr = 2
addr = 2
addr = 3
addr = 7
addr = 6
$finish called from file "t_constraints.sv", line 26.
Sorry for not formatting properly. I am not able to answer after formatting. It gives me error saying code is not formatted properly.
EDIT:
If you want to consider the addr generated each time for the next randomization, use inline constraints in tb.
See below code
module tb_con;
t_constraints t_con;
int t_keys [$];
int T_BLOCK_SIZE;
initial begin
t_con = new();
repeat(3) begin // constraint solver cannot solve since after 3rd iteration there won't be any legal values.
t_keys = t_con.keys;
T_BLOCK_SIZE = t_con.BLOCK_SIZE;
t_con.randomize() with{
foreach(t_keys[i])
{ !(addr inside {[t_keys[i]:t_keys[i]+T_BLOCK_SIZE]});}
};
$display("addr = %h",t_con.addr);
t_con.keys.push_back(t_con.addr);
end
$finish;
end
endmodule: tb_con
NOTE: You must be careful not to iterate more than the possible values (here 3) else your simulation will exit with constraint inconsistency error.
It worked for me. Please show a complete testcase and the incorrect results you are getting.
class a;
rand bit [5:0] address;
bit [5:0] keys[] = {0,10,40};
int BLOCK_SIZE = 5;
constraint con {
foreach(keys[i]) {
!(address inside {[keys[i]:keys[i]+BLOCK_SIZE-1]}) ; }
}
endclass
module top;
a a_h;
initial begin
a_h = new;
repeat (200) begin
if (!a_h.randomize())
$error("randomize failed");
$display(a_h.address);
assert (!(a_h.address inside {[0:4],[10:14],[40:44]}));
end
end
endmodule // top