Quartus and modelsim - compile size casting

1.6k Views Asked by At

I'll try to compile in Quartus and simulate in ModelSim some module.

See this:

module somemodule(
   ... inputs, outputs, etc...
);
localparam BUFFER_LEN   = 96;
localparam BUFFER_LENW  = $clog2(BUFFER_LEN);
localparam DATA_WIDTH   = 32;

logic [BUFFER_LENW-1:0] bits_remain;

always_ff @(posedge rd_clk) begin : _proc_bitsremain
    if (state == LOAD) begin
        case (somevalue)
                  1: bits_remain <= DATA_WIDTH * 1;
                  2: bits_remain <= DATA_WIDTH * 2;
            default: bits_remain <= BUFFER_LEN;
        endcase
    end
    else
        bits_remain <= bits_remain - 1;
end
endmodule

So, I compile it in modelsim. I have 0 errors and 0 warnings. Simulation is success, all is good. Next, I compile (synthesis) it in Quartus, and I have this warning:

Warning (10230): Verilog HDL assignment warning at <location>: 
truncated value with size 32 to match size of target (7)

So, I understand the warning, and fix it by size casting:

module somemodule(
   ... inputs, outputs, etc...
);
localparam BUFFER_LEN   = 96;
localparam BUFFER_LENW  = $clog2(BUFFER_LEN);

logic [BUFFER_LENW-1:0] bits_remain;

always_ff @(posedge rd_clk) begin : _proc_bitsremain
    if (state == LOAD) begin
        case (somevalue)
                  1: bits_remain <= BUFFER_LENW'(DATA_WIDTH * 1);
                  2: bits_remain <= BUFFER_LENW'(DATA_WIDTH * 2);
            default: bits_remain <= BUFFER_LENW'(BUFFER_LEN);
        endcase
    end
    else
        bits_remain <= BUFFER_LENW'(bits_remain - 1);
end
endmodule

In Quartus compilation is success. But, If I'll try to compile this code in ModelSim again, I have a error:

** Error: <location>(148): near "'": syntax error, unexpected '\'', expecting ';'

Where I wrong and why modelSim can't compile a size casting?

3

There are 3 best solutions below

0
On

The casting is covered by section 6.24 in IEEE 1800-2012 & IEEE 1800-2009. IEEE 1800 is the SystemVerilog standard. I do not see it covered in any of the Verilog standards (please leave a comment if you can point me to the section in IEEE 1364-1995, 2001 or 2005).

Forcing to use system verilog compiler might solve the issue, normally done through changing the file extension to '.sv' or adding a -sv flag to the command line.

The standards do not dictate which parts are for simulation only and which are synthesisable, so you may run into issues where you can simulate but not synthesise. If I have followed the question correctly the reverse is true at the minute. which could just be differing levels of support for SystemVerilog.

However you can cast using temp variables or have a temp variable to catch the extra bits, which never gets used and is optimised away.

reg [W-1:0] temp_two;
always @* begin
  temp_two = (DATA_WIDTH * 2);
end

//...
bits_remain <= temp_two[4:0]; 

Or

reg [W-5:0] temp_throw_away;
{temp_throw_away, bits_remain} <= (DATA_WIDTH * 2);
2
On

The legality of the syntax BUFFER_LENW'(DATA_WIDTH * 1) is questionable in the current SystemVerilog standard. The LRM only mentions a positive decimal number appearing before the ' and everything else is interpreted as a type. However many tools now allow an integer parameter as you have done so here. ModelSim 10.3 and later releases now support this extension to the LRM.

There are two currently legal ways to write this in SystemVerilog. One is with a part-select on a concatenation.

bits_remain <= {DATA_WIDTH * 2}[BUFFER_LENW-1:0];

The other way is using a typedef and bit-stream cast

typedef logic [BUFFER_LENW-1:0] buffer_width_t;
buffer_width_t bits_remain;


bits_remain = buffer_width_t'(DATA_WIDTH * 2);
0
On

To typecast from a 32-bit unsigned to 8-bit unsigned, you need to select the bits you want from the 32-bit local parameter, and then perform any operations you want in the usual way.

localparam MY_CONST_32_BITS = 96;  // parameters always seem to be type cast to 32 bit, even if you pass 8'd96 as the value.
wire [7:0] my_const_8_bits = MY_CONST_32_BITS[7:0];  // Select lower 8 bits out of 32 bits
wire [8:0] double_my_const_9_bits = my_const_8_bits * 8'd2;  // 8 bit wide unsigned decimal value 2.

The above code compiles fine for me in Altera Quartus tools.