Verilog concatenation of decimal and string literal - verilog

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" ]

Related

Byte Masking AxiStream: How to mask tdata with tkeep systemverilog

In AxiStream the tkeep value in each transfer denotes the valid bytes in the tdata field of the same transfer.
In systemverilog i want to use tkeep to mask (set to 0) the invalid bits in the tdata field.
If tkeep denoted invalid bits then I could simply do:
masked_tdata = tdata & tkeep;
However tkeep denotes valid bytes.
Is there an elegant way to perform this "Byte Masking" operation in SystemVerilog (Does not have to be synthesizable as this is part of a testbench).
logic[31:0] tdata = 4'hC1FF
logic[3:0] tkeep = 4'b0001;
logic[31:0] masked_tdata;
assign masked_tdata = tdata & tkeep; // evaluates to 0x0001
// what I want it to evaluate to is 0x000F
If by elegant you mean as a single expression, I can't think of one that is more elegant than using for loop.
for(int i;i<$bits(tdata)/8;i++)
masked_tdata[i*8+:8] = tkeep[i] ? tdata[i*8+:8] : '0;

Casting from int to parameterized-width logic

Given the parameters
parameter int eC,
parameter int cntW = ...
I have the following assignment:
logic [cntW-1:0] count;
logic [cntW-1:0] front;
logic [cntW-1:0] back;
assign count = condition ? front : back+eC+1 - front;
where back+eC+1 - front is promoted to a 32 bit int, which is wider than cntW.
How can I explicitly cast int to the variable width cntW to suppress the warning that comes from the implicit conversion?
The warning is
Continuous assignment width mismatch
5 bits (lhs) versus 32 bits (rhs).
Source info: assign count = ((back >= front) ? (back - front) : (((back +
eC) + 1) - front));
First of all, the bare number 1 is implicitly a 32-bit signed decimal value. Operands in arithmetic expression get extended to the width of the largest operand before applying the operators. You can use 1'b1 which is an explicit 1-bit value. Also declare eC with the same width as the other variables
typedef logic [cntW-1:0] cnt_t;
parameter cnt_t eC;
cnt_t count;
cnt_t front;
cnt_t back;
assign count = condition ? front : back+eC+1'b1 - front;
Another thing you do is use a cast
assign count = condition ? front : cntW'(back+eC+1) - front;

Shifter output is always 0 when using concatenation and case

I have the following code:
module shifter(
input[7:0] in,
input[1:0] amt,
output logic[7:0] out
);
always_comb case(amt)
2'h0: out = in;
2'h1: out = {{in[6:0]}, 0};
2'h2: out = {{in[5:0]}, 0, 0};
2'h3: out = {{in[4:0]}, 0, 0, 0};
default: out = in;
endcase
endmodule
It describes a simple shifter which takes in the amount of shifts through the amt input. The problem is that no matter what the value of amt is (except 0), out is always 0 as seen on this waveform from a test:
Am I concatenating wrong? Examples I've seen online are similar to this, however.
Try constraining the size of the 0 to 1'b0 in 2'h1: out = {{in[6:0]}, 0};. What happens is that you are assigning a concatenation of in[6:0] and 32-bit (default width) 0, so only LSBs of the 0 goes to the out.
Also, default is redundant since you've described all the possible cases for amt.
The code you wrote is illegal according to the IEEE 1800-2017 LRM section 11.4.12 Concatenation operators:
Unsized constant numbers shall not be allowed in concatenations. This
is because the size of each operand in the concatenation is needed to
calculate the complete size of the concatenation
The tool you are using has a bug and did not catch this error, which is very difficult to find on your own.

design ROM to save filter coefficients in verilog

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

what does "Memory index truncation" mean?

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.

Resources