So, I created my first system Verilog testbench by modifying the tutorial from https://verificationguide.com/systemverilog-examples/systemverilog-testbench-example-01/ ( In this tutorial a memory block is tested, I modified it for a simple AND gate).
There are seven files excluding the DUT file,
environment.sv
interface.sv
transactions.sv
generator.sv
testbench.sv ( topLevel testbench)
driver.sv
test.sv
I used Intel modelsim to compile these files.
While compiling, I got these errors in driver.sv and generator.sv
** Error: (vlog-13069) D:/Altera/Projects/AndGate/testbench/driver.sv(28): near ";": syntax error, unexpected ';', expecting '('.
** Error: (vlog-13069) D:/Altera/Projects/AndGate/testbench/generator.sv(4): near "trans": syntax error, unexpected IDENTIFIER, expecting ';' or ','.
Below are the corresponding files,
driver.sv
`define DRIV_IF mem_vif.DRIVER.driver_cb
class driver;
int num_trans;
virtual mem_intf mem_vif;
mailbox gen2driv;
function new(virtual mem_intf mem_vif, mailbox gen2driv);
this.mem_vif = mem_vif;
this.gen2driv = gen2driv;
endfunction
task reset();
wait(mem_vif.reset);
$display("--------- [DRIVER] Reset Started ---------");
`DRIV_IF.A <= 0;
`DRIV_IF.B <= 0;
`DRIV_IF.C <= 0;
wait(!mem_vif.reset);
$display("--------- [DRIVER] Reset Ended ---------");
endtask
task drive();
transaction trans;
gen2driv.get(trans);
$display("Num transactions : %0d", num_trans);
#(posedge mem_vif.DRIVER.clk);
`DRIV_IF.A <= trans.A;
`DRIV_IF.B <= trans.B;
trans.C = `DRIV_IF.C;
$display("\tA = %0h \tB = %0h \tC = %0h", trans.A, trans.B, `DRIV_IF.C);
num_trans++;
endtask
endclass
generator.sv
class generator;
var rand transaction trans;
mailbox gen2driv;
int repeat_count;
event ended;
function new(mailbox gen2driv, event ended);
this.gen2driv = gen2driv;
this.ended = ended;
endfunction
task main();
repeat(repeat_count) begin
trans = new();
if(!trans.randomize())$fatal("Random Generation failed");
gen2driv.put(trans);
end
-> ended;
endtask
endclass
Please, help me with this...
For future reference, it would really help to point to the line 28 and 4 in the respective files where the error is occurring as well as give the command line used to compile the code. But since I've seen this exact error before, I know it is because you put all of these files separately on your command line and not compiled together as a package.
Modelsim/Questa compiles every SystemVerilog file on the command line as a separate compilation unit. Identifiers declared in one compilation unit cannot be seen by other compilation units. When the generator and driver classes get compiled, it has no idea what transaction means and you get a syntax error. Modules and interfaces names exist in a separate namespace and the syntax where they are referenced allows them to used before their declarations have been compiled.
To remedy this, you could `include all you class files in testbench module, or the normal practice is putting them all in a package and importing the package. There is also a compilation mode where everything on the command line in one compilation unit, but that option is not scaleable as your designer get larger.
I also suggest reading these two posts I wrote:
https://blogs.sw.siemens.com/verificationhorizons/2010/07/13/package-import-versus-include/
https://blogs.sw.siemens.com/verificationhorizons/2009/05/07/programblocks/
Related
I downloaded the memory model for the DDR3 bank that I'd be testing in simulation using Modelsim (2019.2) from Micron's website (link).
I followed the instructions from the README file to compile it but I run into syntax errors! I don't think Micron would make bug-gy code public and available to developers.
Modelsim command:
vlog +define+sg25 C:/Micro_projects/FPGA/hdl/micron/ddr3/ddr3.v
ERRORS
# ** Error: (vlog-13069) C:/Micro_projects/FPGA/hdl/micron/ddr3/ddr3.v(421): near ";": syntax error, unexpected ';', expecting '('.
# ** Error: C:/Micro_projects/FPGA/hdl/micron/ddr3/ddr3.v(424): Illegal declaration after the statement near line '421'. Declarations must precede statements. Look for stray semicolons.
# ** Error: (vlog-13069) C:/Micro_projects/FPGA/hdl/micron/ddr3/ddr3.v(433): near "integer": syntax error, unexpected integer, expecting IDENTIFIER or genvar.
# ** Error: C:/Micro_projects/FPGA/hdl/micron/ddr3/ddr3.v(433): (vlog-13205) Syntax error found in the scope following 'i'. Is there a missing '::'?
initial
begin : file_io_open
reg [BA_BITS - 1 : 0] bank;
reg [ROW_BITS - 1 : 0] row;
reg [COL_BITS - 1 : 0] col;
reg [BA_BITS + ROW_BITS + COL_BITS - 1 : 0] addr;
reg [BL_MAX * DQ_BITS - 1 : 0] data;
string _char; //LINE 421
integer in, fio_status;
if (!$value$plusargs("model_data+%s", tmp_model_dir))
begin
tmp_model_dir = "/tmp";
$display(
"%m: at time %t WARNING: no +model_data option specified, using /tmp.",
$time
);
end
for (integer i = 0; i < `BANKS; i = i + 1)
memfd[i] = open_bank_file(i);
I hope someone can suggest me how to proceed with it. I have contacted Micron but haven't heard from them yet (it has been a few days). I am stuck and any comments are appreciated!
Thank you,
Surabhi
The error is from the line which includes string, which is a SystemVerilog keyword.
You need to enable SystemVerilog syntax using the modelsim -sv option.
module testy
#(
parameter W = 10,
parameter C = 2
)
(
aa
);
generate
if (W == 8)
begin:W8
if(C == 1)
begin:W8C1
typedef struct {
logic [8:0] so;
}my_struct;
end
if(C == 2)
begin:W8C2
typedef struct {
logic [10:0] so;
}my_struct;
end
end
endgenerate
input my_struct aa;
endmodule
I get this error:
irun(64): 14.20-p001: (c) Copyright 1995-2015 Cadence Design Systems, Inc.
file: testy.v
input my_struct aa;
|
ncvlog: *E,SVNOTY (testy.v,30|14): Syntactically this identifier appears to begin a datatype but it does not refer to a visible datatype in the current scope.
module worklib.testy:v
errors: 1, warnings: 0
ncvlog: *F,NOTOPL: no top-level unit found, must have recursive instances.
irun: *E,VLGERR: An error occurred during parsing. Review the log file for errors with the code *E and fix those identified problems to proceed. Exiting with code (status 2).
I thought generates were statically determined but I have problems compiling it - since parameters cant be overridden in packages and couldn't think of a way to do this in design which needs to be synthesized and didn't want to add interfaces or classes. Is there a bettwe way to do this. My struct has over 100 entries if I include all the combinations and use only what I want but I thought using generates I could trim it to what I want based on a set of parameters.
Thanks
Your problem is the scope of the typedef is local to the blocks inside your generate statements. If all you need to do is change the size of a data type, you can use a constant function call, with is statically determined. But then you run into another problem with your unpacked struct declaration - it is still local to the module and you will not be able to connect another struct to it with a matching data type. An interface would be a better solution and is synthesizable.
Another possibility is passing down a type parameter.
I am using a generate loop to instantiate a paramaterizable number of modules, and I want to assign some of the inputs to the module based on the loop iteration. Unfortunately I'm running into issues with synthesis where design compiler says there's an error because the port width doesn't match. Here's what I'm trying to do:
genvar k;
generate
for(k = 0; k < `NUM/2; ++k) begin
cmp2 cmps(
.a (arr[k]),
.b (arr[k+1]),
.a_idx (k), //gives errors about port width mismatch
.b_idx (k+1), //but I can't get it to work any other way
.data_out(data[k]),
.idx_out (idx[k])
);
end
endgenerate
I've also tried using localparams in the loop and assigning a_idx and b_idx to the localparam but I still get the same error under synthesis.
I've tried something like .a_idx((k)[bit_width-1:0]), but that doesn't work either.
Any ideas?
k and k+1 are 32-bit wide, which causes the width mismatch.
Depending on what your synthesis tool supports, you might want to try the following:
Bit slicing:
.a_idx (k[0 +: bit_width])
Cast to bit_width-wide logic:
typedef logic[bit_width-1:0] logicN_t;
// .... //
.a_idx (logicN_t'(k)),
.b_idx (logicN_t'(k+1)),
// .... //
I have a module which stores a bitmap of different characters, that I am planning on using to display text on a matrix. Currently, the bitmap is populated with a memory initialization file, and this file is passed in as a parameter (I have confirmed this working in Quartus and ModelSim).
In order to actually have a lookup table for all the characters, I wanted to make a separate module which has instantiations of the all bitmaps, and selects the correct one based on a character code. These bitmap instantiations are created in a generate block, and they take the correct filename from an array. However, ModelSim doesn't like this. My code is as follows:
module mem_char_disp_lib(
output logic pixel,
input logic [4:0] x,
input logic [5:0] y,
input logic [6:0] code,
input logic clk
);
localparam CHAR_NUM = 26;
logic [CHAR_NUM-1:0] alphabet;
const var [CHAR_NUM-1:0] BITMAPS = {
"/mem/char/A.hex",
"/mem/char/B.hex",
"/mem/char/C.hex",
// ... a lot more declarations here...
"/mem/char/X.hex",
"/mem/char/Y.hex",
"/mem/char/Z.hex"
};
genvar i;
generate
for (i=0; i<CHAR_NUM; i=i+1) begin : mem_char_disp_blocks
mem_char_disp #(.BITMAP(BITMAPS[i])) block (
.pixel(alphabet[i]),
.x, .y, .clk,
.code(i),
.data(1'b0),
.write_en(1'b0)
);
end
endgenerate
always_comb
pixel = alphabet[code];
endmodule
The error ModelSim is giving me is:
The expression for a parameter actual associated with the parameter name ('BITMAP') for the module instance ('block') must be constant.
(referring to the line inside the for loop)
I am not sure why this doesn't work. On a hardware level, it seems like I'm just making a lot of copies of a module, and slightly tweaking each one with a constant parameter known at compile-time. Is there some basic syntax that I'm missing?
Edit: I have also tried the following code, which seems to give a runtime error:
for (i=0; i<CHAR_NUM; i=i+1) begin : mem_char_disp_blocks
parameter [CHAR_NUM-1:0] BITMAPS = {
"/mem/char/A.hex",
// more elements...
"/mem/char/Z.hex"
};
mem_char_disp #(.BITMAP(BITMAPS[i])) block (
.pixel(alphabet[i]),
.x, .y, .clk,
.code(i),
.data(1'b0),
.write_en(1'b0) );
end
The error is Module parameter 'BITMAP' not found for override. (One of these errors for each of the generated modules; CHAR_NUM total.) This doesn't make sense to me, since instantiating a single one directly works just fine (e.g. mem_char_disp #(.BITMAP("/mem/char/A.hex") block /* ... */).
A const variable is not a constant - it is a write-once variable that gets initialized at runtime when the variable gets allocated. You need to us a parameter or localparam to assign to another parameter as you discovered in your update. You also need to fix the dimensions of the array
parameter bit [1:15*8] BITMAPS[26] = {
"/mem/char/A.hex", // 15 8-bit chars
// more elements...
"/mem/char/Z.hex" // 26 elements
};
Can't help you with your last error without seeing the declaration of the module mem_char_disp
Hi I've following scenario and it's not working for me.
file: a.svh
a.svh defines some parameters and functions- let's say function xyz(b)
file b.sv
package b;
`include "a.svh"
typedef logic[(xyz(10)-1):0] h;
endpackage
Now the issue is, b.sv can't find xyz function in it's scope, even thought I'm tick-including a.svh in b.sv. Everything works fine if I don't use a package in b.sv file. (comment out package b and endpackage lines).
//package b;
`include "a.svh"
typedef logic[(xyz(10)-1):0] h;
//endpackage
Is it an illigal case in systemverilog?
I recreated your scenario on EDAplayground. I didn't get any errors.
A function is intended to be evaluated during simulation. Some simulators support evaluating function during compile/elaboration, but it doesn't appear to be a requirement.
SystemVerilog also has let, which is more appropriate for for compile time evaluation (it supports simulation time as well). Refer to IEEE Std 1800-2012 ยง 11.13 Let construct:
let declarations can be used for customization and can replace the text macros in many cases. The let construct is safer because it has a local scope, while the scope of compiler directives is global within the compilation unit. Including let declarations in packages (see Clause 26) is a natural way to implement a well-structured customization for the design code.
a.svh
function int xyz_func(int b);
return b;
endfunction
let xyz_let(b) = b;
design.sv (equivalent to your b.sv, EDAplayground requires design.sv to exist)
package b;
`include "a.svh"
typedef logic[(xyz_func(10)-1):0] hf;
typedef logic[xyz_let(10):1] hl;
endpackage
testbench.sv
module tb;
import b::*;
hf myhf;
hl myhl;
initial begin
myhf = -1;
myhl = -1;
$display("hf:%b left:%0d right:%0d", myhf, $left(myhf), $right(myhf));
$display("hl:%b left:%0d right:%0d", myhl, $left(myhl), $right(myhl));
end
endmodule
Output:
hf:1111111111 left:9 right:0
hl:1111111111 left:10 right:1