I have a module with some parameters. Those are used in a for loop, that I would have thought would unroll the contents. In the end, there would be no for loop or index, just a big list of repetitive logic.
I’m obviously not understanding this as when I try to use iverilog
to start testing the module it complains with many errors:
command being run: iverilog -g2012 -o graph/crossbar.vvp -s crossbar_tb src/defines.sv test/crossbar_tb.sv src/crossbar.sv
src/crossbar.sv:54: error: A reference to a wire or reg (`m') is not allowed in a constant expression.
src/crossbar.sv:54: error: Part select expressions must be constant.
src/crossbar.sv:54: : This lsb expression violates the rule: ((m)*('sd32))+(('sd32)-(MASK_SIZE))
m
in this case it an integer index in a for loop that im my mind would go away during the unroll.
The module code, its logic may be wonky as I haven’t tested it at all yet. But I don’t understand why it won’t unroll as expected while trying to write a test.
`default_nettype none
module crossbar
#(
parameter MASTERS = 1,
parameter CHANNELS = 1,
parameter MASK_SIZE = 4
)
(
input logic i_clock,
input logic i_reset_n,
// Inputs from masters
input logic [$clog2(MASTERS):0] i_wbm_we, // Write enable
input logic [$clog2(MASTERS):0] i_wbm_cyc, // Cycle status
input logic [$clog2(MASTERS):0] i_wbm_stb, // Strobe
input logic [MASTERS * 32 - 1:0] i_wbm_addr, // Address read from master
input logic [MASTERS * 32 - 1:0] i_wbm_data, // Data read from the master
// Outputs to masters
output logic [$clog2(MASTERS):0] o_wbm_err, // Error
output logic [$clog2(MASTERS):0] o_wbm_ack, // Acknowledge
output logic [$clog2(MASTERS):0] o_wbm_stall, // Stall
output logic [MASTERS * 32 - 1:0] o_wbm_data, // Data write from the master
// Outputs to channels
output logic [$clog2(CHANNELS):0] o_wbc_we, // Write enable
output logic [$clog2(CHANNELS):0] o_wbc_cyc, // Cycle status
output logic [$clog2(CHANNELS):0] o_wbc_stb, // Strobe
output logic [CHANNELS * 32 - 1:0] o_wbc_addr, // Address read from master
output logic [CHANNELS * 32 - 1:0] o_wbc_data, // Data read from the master
// Inputs from channels
input logic [$clog2(CHANNELS):0] i_wbc_err, // Error
input logic [$clog2(CHANNELS):0] i_wbc_ack, // Acknowledge
input logic [$clog2(CHANNELS):0] i_wbc_stall, // Stall
input logic [CHANNELS * 32 - 1:0] i_wbc_data, // Data write from the master
input logic [CHANNELS * MASK_SIZE - 1:0] i_wbc_mask // Mask for address space
);
logic [$clog2(CHANNELS):0] channel_in_use [$clog2(MASTERS):0];
integer m; // Master loop index
integer c; // Channel loop index
always_ff @(posedge i_clock) begin
// Loop over each master
for (m = 0; m < MASTERS; m = m + 1) begin
// New request from master m
if (i_wbm_cyc[m] == 'b1 && i_wbm_stb[m] == 'b1) begin
// Loop over each channel
for (c = 0; c < CHANNELS; c = c + 1) begin
// Found the requested channel, not in use
if (i_wbc_mask[c * MASK_SIZE + MASK_SIZE - 1:i_wbc_mask * MASK_SIZE] == i_wbm_addr[m * 32 + 32 - 1:m * 32 + (32 - MASK_SIZE)] && channel_in_use[c] == 0) begin
channel_in_use[c] <= m;
o_wbm_stall[m] <= 'b0;
o_wbm_err[m] <= 'b0;
end
// Found the requested channel, in use
else if (i_wbc_mask[c * MASK_SIZE + MASK_SIZE - 1:i_wbc_mask * MASK_SIZE] == i_wbm_addr[m * 32 + 32 - 1:m * 32 + (32 - MASK_SIZE)] && channel_in_use[c] != 0) begin
o_wbm_stall[m] <= 'b1;
o_wbm_err[m] <= 'b0;
end
// requested channel not found
else begin
o_wbm_stall[m] <= 'b0;
o_wbm_err[m] <= 'b1;
end
end
end
// No request for mater m
else if (i_wbm_cyc[m] == 'b0) begin
for (c = 0; c < CHANNELS; c = c + 1) begin
if (channel_in_use[c] == m) begin
channel_in_use[c] = 0;
end
end
end
end
// Loop over each channel
for (c = 0; c < CHANNELS; c = c + 1) begin
// Channel is addigned, connect the bus
if (channel_in_use[c] != 0) begin
o_wbc_we[c] <= i_wbm_we[channel_in_use[c]];
o_wbc_cyc[c] <= i_wbm_cyc[channel_in_use[c]];
o_wbc_stb[c] <= i_wbm_stb[channel_in_use[c]];
o_wbc_addr[c * 32 + 31:0] <= i_wbm_addr[channel_in_use[c] * 32 + 31:0];
o_wbc_data[c * 32 + 31:0] <= i_wbm_data[channel_in_use[c] * 32 + 31:0];
o_wbm_err[channel_in_use[c]] <= i_wbc_err[c];
o_wbm_ack[channel_in_use[c]] <= i_wbc_ack[c];
o_wbm_stall[channel_in_use[c]] <= i_wbc_stall[c];
o_wbm_data[channel_in_use[c] * 32 + 31:0] <= i_wbc_data[c * 32 + 31:0];
end else begin
o_wbc_we[c] <= 'b0;
o_wbc_cyc[c] <= 'b0;
o_wbc_stb[c] <= 'b0;
o_wbc_addr[c * 32 + 31:0] <= 32'b0;
o_wbc_data[c * 32 + 31:0] <= 32'b0;
o_wbm_err[channel_in_use[c]] <= 'b0;
o_wbm_ack[channel_in_use[c]] <= 'b0;
o_wbm_stall[channel_in_use[c]] <='b0;
o_wbm_data[channel_in_use[c] * 32 + 31:0] <= 32'b0;
end
end
end
endmodule