Hi,
I have a struct:
typedef struct packed {
logic [2:0] irq1;
logic [2:0] irq2;
logic [2:0] irq3;
logic irq4;
logic irq5;
logic irq6;
} interrupts_struct;
Then I define this set of parameters:
parameter int IRQ_SERIALIZED_DATA_WIDTH = 8;
parameter int IRQ_BUS_WIDTH = $bits(interrupts_struct);
parameter int IRQ_BUS_TRANSMIT_RESIDUE = IRQ_BUS_WIDTH % IRQ_SERIALIZED_DATA_WIDTH;
The parameter IRQ_BUS_TRANSMIT_RESIDUE can get in some cases zero value.
When this happen, I get compilation error on this code:
if ((IRQ_BUS_TRANSMIT_RESIDUE != 0) & (duration_counter == SERIALIZATION_DURATION-1))
data[IRQ_BUS_TRANSMIT_RESIDUE-1:0] <= irq_struct_sampled[duration_counter*IRQ_SERIALIZED_DATA_WIDTH +: IRQ_BUS_TRANSMIT_RESIDUE];
else
data <= irq_struct_sampled[duration_counter*IRQ_SERIALIZED_DATA_WIDTH +:IRQ_SERIALIZED_DATA_WIDTH];
because then the part select don’t make sense. it gets data[-1:0] .
Any way I can get it to work?
I mean, without giving up on the $bits that gets the size of struct during compilation.
In reply to yakir_mishli :
If you can separate this code into a generate-if construct, you could write
if (IRQ_BUS_TRANSMIT_RESIDUE != 0)
always @(posedge clk) if (duration_counter == SERIALIZATION_DURATION-1)
data[IRQ_BUS_TRANSMIT_RESIDUE-1:0] <= irq_struct_sampled[duration_counter*IRQ_SERIALIZED_DATA_WIDTH +: IRQ_BUS_TRANSMIT_RESIDUE];
else
data <= irq_struct_sampled[duration_counter*IRQ_SERIALIZED_DATA_WIDTH +:IRQ_SERIALIZED_DATA_WIDTH];
else
always @(posedge clk)
data <= irq_struct_sampled[duration_counter*IRQ_SERIALIZED_DATA_WIDTH +:IRQ_SERIALIZED_DATA_WIDTH];
Otherwise you could write
parameter int IRQ_SERIALIZED_DATA_WIDTH = 8;
parameter int IRQ_BUS_WIDTH = $bits(interrupts_struct);
parameter int IRQ_BUS_TRANSMIT_RESIDUE = IRQ_BUS_WIDTH % IRQ_SERIALIZED_DATA_WIDTH;
parameter int ADJUSTED_RESIDUE = IRQ_BUS_TRANSMIT_RESIDUE ? IRQ_BUS_TRANSMIT_RESIDUE : 1;
if ((IRQ_BUS_TRANSMIT_RESIDUE != 0) & (duration_counter == SERIALIZATION_DURATION-1))
data[ADJUSTED_RESIDUE-1:0] <= irq_struct_sampled[duration_counter*IRQ_SERIALIZED_DATA_WIDTH +: ADJUSTED_RESIDUE];
else
data <= irq_struct_sampled[duration_counter*IRQ_SERIALIZED_DATA_WIDTH +:IRQ_SERIALIZED_DATA_WIDTH];
In reply to dave_59 :
Thanks Dave!
Both options solved the problem.
I took the 2nd because it’s less code lines.
Desam
May 17, 2021, 2:45pm
4
In reply to yakir_mishli :
Can you plz help me to understand why “The parameter IRQ_BUS_TRANSMIT_RESIDUE can get in some cases zero value”?
In reply to Desam :
Sure.
This struct is often changed during development. We add/remove signal and so his size is changing.
typedef struct packed {
logic [2:0] irq1;
logic [2:0] irq2;
logic [2:0] irq3;
logic irq4;
logic irq5;
logic irq6;
} interrupts_struct;
if, for example, $bits(interrupts_struct) will evaluate to 16,
then IRQ_BUS_TRANSMIT_RESIDUE = 16 % 8 = 0 .
parameter int IRQ_SERIALIZED_DATA_WIDTH = 8;
parameter int IRQ_BUS_WIDTH = $bits(interrupts_struct);
parameter int IRQ_BUS_TRANSMIT_RESIDUE = IRQ_BUS_WIDTH % IRQ_SERIALIZED_DATA_WIDTH;
I tried to write my code in a way that changing the struct won’t affect the logic that handle it. For easy scaling. so this is the most elegant way I managed to do it.
The drawback was a specific case that the residue gets zero.
But dave solved this.