I am trying to do some width manipulation on the data path and need to pad some some zeros when necessary. I have written the following bit of logic in verilog and trying to synthesize. The following code is a minimal working example and shows the issue that I am facing. When I run the below code.
module mwe
#(parameter RWIDTH = 20, // can be 20 or 16
parameter BWIDTH = 16 // is generally always 16
)
(
input clk,
input rst,
input a,
output reg [RWIDTH -1:0] y
);
wire [8*BWIDTH-1:0] native_wdata_bus; // 128 bit bus
reg [8*RWIDTH-1:0] modified_wdata_bus; // can be 128 bit or 160 bit bus based on RDATA configuration
wire [8*RWIDTH-1:0] native_rdata_bus; // can be 128 bit or 160 bit bus based on RDATA configuration
reg [8*BWIDTH-1:0] modified_rdata_bus; // generally is 128 bit bus
// locally calulating the WIDTH_DIFF
localparam WIDTH_DIFF = RWIDTH-BWIDTH;
// function to pad zeros
function [WIDTH_DIFF -1 : 0] pad_zeros(input WIDTH_DIFF);
pad_zeros = {WIDTH_DIFF{1'b0}};
endfunction
always @* begin : width_change
integer i;
for (i=0; i<8; i=i+1) begin
modified_rdata_bus[BWIDTH*i +: BWIDTH-1] = native_rdata_bus[(RWIDTH*i)+WIDTH_DIFF +: (RWIDTH-1)-WIDTH_DIFF];
if(RWIDTH != BWIDTH)
modified_wdata_bus[(RWIDTH*i) +: (RWIDTH-1)] = {native_wdata_bus[(BWIDTH*i) +: (BWIDTH-1)], pad_zeros(WIDTH_DIFF)};
else
modified_wdata_bus[RWIDTH*i +: RWIDTH-1] = native_wdata_bus[BWIDTH*i +: BWIDTH-1];
end
end
endmodule
I get the following when I compile the code using Vivado xvlog.
INFO: [VRFC 10-2263] Analyzing Verilog file "/home/rtl/mwe/mwe.v" into library work
INFO: [VRFC 10-311] analyzing module mwe
ERROR: [VRFC 10-2951] 'WIDTH_DIFF' is not a constant [/home/rtl/mwe/mwe.v:23]
ERROR: [VRFC 10-2865] module 'mwe' ignored due to previous errors [/home/rtl/mwe/mwe.v:1]
I have been looking at other errors similar to mine
Verilog If statement - Signal is not a Constant. But it still doesn't exactly answer my question. Why does the Verilog compiler interpret that WIDTH_DIFF
is not constant?
Though I am interested to resolve the issue, I am also trying to understand how the verilog interprets the above piece of code (any pointers would be helpful).
In the function declaration, you used: input WIDTH_DIFF
. The input is a variable type, not a constant type. Therefore, in the expression {WIDTH_DIFF{1'b0}}
inside the function, WIDTH_DIFF
is interpreted as a variable, not a constant.
You can remove the function and directly use the concatenation inline. Change:
modified_wdata_bus[(RWIDTH*i) +: (RWIDTH-1)] = {native_wdata_bus[(BWIDTH*i) +: (BWIDTH-1)], pad_zeros(WIDTH_DIFF)};
to:
modified_wdata_bus[(RWIDTH*i) +: (RWIDTH-1)] = {native_wdata_bus[(BWIDTH*i) +: (BWIDTH-1)], {WIDTH_DIFF{1'b0}}};