I'm trying to implement the memory model as below, but I got these warning messages:
assign Data = (!CS && !OE) ? Mem[Address] : {WordSize{1'bz}};
|
ncelab: *W,BIGWIX (./sram.v,16|39): Memory index truncation.
Mem[Address] = Data;
|
ncelab: *W,BIGWIX (./sram.v,20|14): Memory index truncation.
Here is my code:
// RAM Model
//
module sram (Address, Data, CS, WE, OE);
parameter AddressSize = 2592;
parameter WordSize = 32;
input [AddressSize-1:0] Address;
inout [WordSize-1:0] Data;
input CS, WE, OE;
reg [WordSize-1:0] Mem [0:(1<<AddressSize)-1];
assign Data = (!CS && !OE) ? Mem[Address] : {WordSize{1'bz}};
always #(CS or WE)
if (!CS && !WE)
Mem[Address] = Data;
always #(WE or OE)
if (!WE && !OE)
$display("Operational error in RamChip: OE and WE both active");
endmodule
What does "Memory index truncation" mean?
You can get more verbose help on any Cadence Incisive warnings using nchelp:
nchelp ncelab BIGWIX
ncelab/BIGWIX =
A memory is being indexed. The index expression has a width
greater than a machine word, which is typically 32 bits.
Only 32 bits are used. This truncation may result in
undesired behavior.
As mentioned in the Comment, you probably do not want the Address input signal to be 2592 bits wide or your memory to have (1<<2592) locations.
Related
I want to store filter coefficients(fixed values) in ROM using verilog.Below is the code for ROM using case.
module rom_using_case (
address , // Address input
data , // Data output
read_en , // Read Enable
ce // Chip Enable
);
input [3:0] address;
output [7:0] data;
input read_en;
input ce;
reg [7:0] data ;
always # (ce or read_en or address)
begin
case (address)
0 : data = 10;
1 : data = 55;
2 : data = 244;
3 : data = 0;
4 : data = 1;
5 : data = 8'hff;
6 : data = 8'h11;
7 : data = 8'h1;
8 : data = 8'h10;
9 : data = 8'h0;
10 : data = 8'h10;
11 : data = 8'h15;
12 : data = 8'h60;
13 : data = 8'h90;
14 : data = 8'h70;
15 : data = 8'h90;
endcase
end
endmodule
what does the case block do in the above code?
can i store filter coefficients in data variable in the case block?
can i access those filter coefficients?
As you state the coefficients will be stored in a RAM LUT or in a ROM block.
The code is (somewhat) self-descriptive, the always is sensitive to the address then each time the address changes its value the stored value will be assigned to data, case is the selector for which location of the memory block will be assinged to data.
Your implementation is enough for small filters, but if you need a lot of coefficients it will get hard to maintain.
For this purpose you can use the $readmemh or $readmemb. Those are verilog intrisic tasks.
From: https://www.csee.umbc.edu/~tinoosh/cmpe415/slides/Rom-LUT-verilog.pdf
The $readmemh system task expects the content of the named file to be
a sequence of hexadecimal numbers, separated by spaces or line breaks.
Similarly, $readmemb expects the file to contain a sequence of binary.
Here is a snippet which shows how to use it:
reg [19:0] data_ROM [0:511];
...
initial $readmemh("rom.data", data_ROM);
always #(address)
if (ce & read_en)
d_out = data_ROM[address];
The "rom.data" contains the coefficients in text. For example, in your case:
8'hA
8'h37
8'hF4
8'h0
8'h1
8'hff
8'h11
8'h1
8'h10
8'h0
8'h10
8'h15
8'h60
8'h90
8'h70
8'h90
I am new to Verilog.
How can I randomize the following:
bit [7:0] data [];
*Without use randomize() of systemVerilog.
SystemVerilog will not change the size of a dynamic array unless you put a constraint on it. So you either need to allocate the array before calling randomize(), or use a constraint to randomize the size.
bit [7:0] data [];
data = new[10];
randomize(data);
or
bit [7:0] data [];
randomize(data) with {data.size inside {[5:15]} ;};
or if you do not have access to the randomize() SystemVerilog, you can do
data = new[10];
foreach(data[ii]) data[ii] = $urandom;
constrain the size of the array to the required range and call randomize. It should generate an array with random data ( in the example below of size between 30 and 40 )
class rand_gen ;
rand bit [7:0] data[];
constraint db { data.size inside {[30:40]}; }
task generate ();
randomize(data);
end task
endclass
I want to concatenate decimal with the string. Like:
parameter AWIDTH = 15;
...
...
wire [AWIDTH-1:0] addra_bus;
assign addra_bus = cg_one ? {addra} : {AWIDTH, "'bz"};
On basic of 'cg_one', it would pick either {addra} or {AWIDTH, "'bz"}. In false condition of ternary operator I am concatenating AWIDTH with 'bz. If cg_one is 1'b0, I should get 15'bz as value in addra_bus. Make sense?
Problem is while synthesizing this code. I get a warning as :
WARNING: expression size 56 truncated to fit in target size 15 (VERI-1209)
Why is it so? From where size 56 is coming?
You should not be using a string literal. All you need to do is
assign addra_bus = cg_one ? addra : 'z;
'z will be expanded to the width of addra_bus
Your are trying to save by default 32 bit AWIDTH and 24 bit "'bz" (56 bits in total) into 15 bit addra_bus.
You should limit the width of the AWIDTH and increase the width of addra_bus . For example:
parameter AWIDTH = 6'd30;
wire [AWIDTH-1:0] addra_bus;
assign addra_bus = cg_one ? {addra} : {AWIDTH, "'bz"};
As Dave already mentioned to put the bus to high state you could do
assign addra_bus = cg_one ? addra : {AWIDTH{1'bz}}; But setting a bus to "z" in a synthesizable code is not desired until you are driving a chip-level IO signal.
If you want to display the string 15'bz in the bus for debug .
reg [7:0] val = {"0"+AWIDTH%10};
reg [7:0] val1 = {("0"+AWIDTH/10)};
assign addra_bus = cg_one ? {addra} : {val,val1};
[ assuming you param size is only unto 99.][ as you need 8 bits per character the code above only displays "15" ]
I have some data from a 1 bit serial port which comes in multiples of bytes of variant lengths as such:
byte expected_1 [$] = {8'hBA, 8'hDD, 8'hC0, 8'hDE};
byte expected_2 [$] = {8'h01, 8'h23, 8'h45, 8'h67, 8'h89, 8'hAB, 8'hCD, 8'hEF};
At each positive clock edge, one bit is sent. I need to testbench hundereds of sequences ( maybe thousand in the future ) so I want to automate the process with assertions in system verilog. The new 2012 standard allows for queues to be passed to properties, but can the queues be sent though a recursive property? I received some error about hierarchical ref.
This is what I have so far (with help from #Greg here):
default clocking sck #(posedge sck); endclocking : sck
sequence seq_serial(logic signal, logic [7:0] expected); // check each bit
byte idx = 7;
(signal == expected[idx], idx--)[*8];
endsequence : seq_serial
property recurring_queue(bit en, logic data, byte data_e [$])
int queue_size = data_e.size;
logic [7:0] expected = data_e.pop_front();
if(queue_size != 0) (
!en throughout (seq_serial(data, expected) ##1 recurring_queue(en, data, data_e))
);
endproperty : recurring_queue
`define ez_assert(exp)
assert property (recurring_queue(en, data, exp))
else $error("Bad Sequence # time: %t. Info: %m", $time);
Calling the assertion in my testbench should be as easy as this:
A1 : `ez_assert(expected_1);
The error messages read:
1) passing hierarchical ref to be used in another hierarchical ref is not supported
2) Illegal SVA property in RHS of'##' expression
3) Local variable queue_size referenced in expression before getting initialized
I'm open to other ideas for asserting long variable-length serial sequences.
Try the same strategy as seq_serial:
sequence seq_queue_pattern(bit en, logic data, byte expt_queue [$]);
int qidx = 0;
( !en throughout (seq_serial(data,expt_queue[qidx]), qidx++)[*] )
##1 (qidx==expt_queue.size);
endsequence : seq_queue_pattern
asrt_expected_1 : assert property ( $fell(en) |-> seq_queue_pattern(en,data,expected_1));
asrt_expected_2 : assert property ( $fell(en) |-> seq_queue_pattern(en,data,expected_2));
This assertion will fail if en is high or the seq_serial chain does not match expected. Do not that parenthicy location matters:
en is don't care one clock after final seq_serial completes:
( !en throughout (seq_serial(data,expt_queue[qidx]), qidx++)[*] ) ##1 (qidx==expt_queue.size)
en must be low one clock after final seq_serial completes or failes and don't care after that
!en throughout ( (seq_serial(data,expt_queue[qidx]), qidx++)[*] ##1
(qidx==expt_queue.size) )
en must be low one clock after final seq_serial completes and don't care after that
!en throughout ( (seq_serial(data,expt_queue[qidx]), qidx++)[*] ##1
(qidx==expt_queue.size) ) ##1 (qidx==expt_queue.size)
Queues within sequences and properties are new and may not be fully supported by all simulators yet. To work around this limitation, use a parametrized macro to create a sequence for each expected queue stream:
`define asrt_qpat(en,monitor, expt_queue) \
sequence seq_queue_pattern__``expt_queue (bit en, logic data); \
int qidx = 0; \
(!en throughout (seq_serial(data,expt_queue[qidx]), qidx++)[*]) \
##1 (qidx==expt_queue.size); \
endsequence : seq_queue_pattern__``expt_queue \
\
asrt_``expt_queue : assert property( #(posedge clk) \
$fell(en) |=> seq_queue_pattern__``expt_queue (en,monitor) ) \
else $error("Bad Sequence # time: %t. Info: %m", $time);
`asrt_qpat(en,data[0],expected_1)
`asrt_qpat(en,data[1],expected_2)
Here is a small bit of Verilog code. I would expect it to return three identical results, all 8-bit representations of -1.
module trivial;
reg we;
reg [7:0] c;
initial
begin
c = 8'd3;
we = 1'b1;
$display ("res(we) = %d", (we ? (-$signed(c)) / 8'sd2 : 8'd0));
$display ("res(1) = %d", (1'b1 ? (-$signed(c)) / 8'sd2 : 8'd0));
$display ("res = %d", (-$signed(c)) / 8'sd2);
end
endmodule
Briefly, the version of the standard I have (1364-2001) says in section 4.1.5 that division rounds towards zero, so -3/2=-1. It also says in section 4.5 that operator sign only depends on the operands (edit: but only for "self determined expressions"; turns out it's necessary to read the part of the standard on signs together with the part on widths). So the sub-expression with the division should presumably be unaffected by the context it is used in, and similarly for the sub-expression involving $signed. So the results should all be the same?
Three different simulators disagree with me. And only two of them agree with each other. The apparent cause is that unsigned division is used instead of the signed division that I would expect. (-3=253, and 253/2=126.5)
Can someone please tell me if any of the simulators are right and why? (see below) I clearly must be missing something, but what please? Many thanks. edit: see above for what I was missing. I now think there is a bug in Icarus and the other two simulators are right
NB: the unused value in the ternary choice does not seem to make any difference, whether signed or unsigned. edit: this is incorrect, perhaps I forgot to save the modified test before retrying with signed numbers
Altera edition of Modelsim:
$ vsim work.trivial -do 'run -all'
Reading C:/altera/12.1/modelsim_ase/tcl/vsim/pref.tcl
# 10.1b
# vsim -do {run -all} work.trivial
# Loading work.trivial
# run -all
# res(we) = 126
# res(1) = 126
# res = -1
GPL Cver
GPLCVER_2.12a of 05/16/07 (Cygwin32).
Copyright (c) 1991-2007 Pragmatic C Software Corp.
All Rights reserved. Licensed under the GNU General Public License (GPL).
See the 'COPYING' file for details. NO WARRANTY provided.
Today is Mon Jan 21 18:49:05 2013.
Compiling source file "trivial.v"
Highest level modules:
trivial
res(we) = 126
res(1) = 126
res = -1
Icarus Verilog 0.9.6
$ iverilog.exe trivial.v && vvp a.out
res(we) = 126
res(1) = -1
res = -1
NCSIM gives:
res(we) = 126
res(1) = 126
res = -1
But if all inputs to the mux are signed I get:
$display ("res(we) = %d", (we ? (-$signed(c)) / 8'sd2 : 8'sd0)); //last argument now signed
$display ("res(1) = %d", (1'b1 ? (-$signed(c)) / 8'sd2 : 8'sd0));
$display ("res = %d", (-$signed(c)) / 8'sd2);
res(we) = -1
res(1) = -1
res = -1
Remembering if we do any arithmetic with an unsigned number the arithmetic is done as unsigned, the same happens when using bit selects:
reg signed [7:0] c;
c = c[7:0] + 7'sd1; //<-- this is unsigned
In the example the mux is part of a single line expression, I assume this is logically flattened for optimisation and therefore the signed/unsigned of all arguments is taken into consideration.