Reputation: 5449
I am trying to parameterize some code I have written. The non parameterized version below is written for WIDTH = 4. I have a reg digits
that cycles a zero. Based on where this zero is I want to output a particular vector to segments
from my array SS
(I assign values to it elsewhere).
reg [6:0] SS [3:0];
always @(posedge clk)
if (reset) digits <= 4'b1110;
else digits <= { digits[2:0], digits[3] };
always @(*)
if (reset) segments <= ~7'h0;
else case(~digits)
4'b1 : segments[6:0] <= ~SS[0];
4'b10 : segments[6:0] <= ~SS[1];
4'b100 : segments[6:0] <= ~SS[2];
4'b1000 : segments[6:0] <= ~SS[3];
default : segments[6:0] <= 7'h0;
endcase
How can I parameterize this case statement for a different width of digits
? I've tried using a for
loop instead of a case statement like this:
for (genvar i = 0; i < WIDTH; i = i+1) begin
if (~digits[i]) segments[6:0] <= ~SS[i];
end
But it won't synthesize because it says segments
has multiple drivers and if I do it in a different way like below it says digits
is not constant so it can't synthesize:
for (genvar i = 0; i < WIDTH; i = i+1) begin
if (~digits == (1 << i)) segments[6:0] <= ~SS[i];
end
How can I do this? I have thought of taking the log base 2 of ~digits
and checking if that is equal to i
within the loop but I'm not sure how to do that in hardware. Is there a better way?
Upvotes: 1
Views: 495
Reputation: 2685
You can do a loop and take advantage of the "last assignment wins". See below. I used some SystemVerilog syntax here, but you could do it without it.
PARAMETER SS_SIZE = 4
logic [6:0] SS [SS_SIZE];
logic [SS_SIZE-1:0] digits;
always_ff @(posedge clk or posedge reset)
if (reset) digits <= {{(SS_SIZE-1){1'b1}},1'b0};
else digits <= { digits[SS_SIZEE-2:0], digits[SS_SIZE-1] };
always_comb begin
segments = '0;
for(int i=0; i<SS_SIZE; i++) begin
if(digits[i]==1'b0) begin
segments = ~SS[i];
end
end
end
I would go further and replace the shift register with a binary counter:
PARAMETER SS_SIZE = 4
logic [6:0] SS [SS_SIZE];
logic [$clog2(SS_SIZE)-1:0] count;
always_ff @(posedge clk or posedge reset)
if (reset) count <= '0;
else if(count == (SS_SIZE-1)) count <= '0
else count <= count+1;
assign segments = ~SS[count];
Upvotes: 1