Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Verilog expand each bit n times

I want to expand each bit n times. For example,

// n = 2
5'b10101 -> 10'b1100110011
// n = 3
5'b10101 -> 15'b111000111000111

Is there any simple way (i.e., not using generate block) in Verilog or SystemVerilog?

EDIT 19.02.21

Actually, I'm doing 64bit mask to 512bit mask conversion, but it is different from {8{something}}. My current code is the following:

logic [63 : 0] x;
logic [511 : 0] y;
genvar i;
for (i = 0; i < 64; i = i + 1) begin
    always_comb begin
        y[(i + 1) * 8 - 1 : i * 8] = x[i] ? 8'hFF : 8'h00;
    end
end

I just wonder there exists more "beautiful" way.

like image 596
csehydrogen Avatar asked Jan 19 '26 13:01

csehydrogen


2 Answers

I think that your method is a good one. You cannot do it without some kind of a loop (unless you want to type all the iterations manually). There might be several variants for implementing it.

For example, using '+:' operator instead of an expression, which simplifies it a bit.

genvar i;
for (i = 0; i < 64; i = i + 1) begin
 always_comb begin
  y[i * 8 +: 8] = x[i] ? 8'hFF : 8'h00;
 end
end

Thew above method actually generated 64 always blocks (as in your original one). Though sensitivity list of every block will be just a single bit from 'x'.

You can move the for loop inside an always block:

always @* begin
 for (int j = 0; j < 64; j++) begin
  y3[j * 8 +: 8] = x[j] ? 8'hFF : 8'h00;
 end
end

this will end up as a single always block, but sensitivity list will include all bits of 'x'.

If this operation is used multiple times, you can use a function :

function logic [511 : 0] transform(input logic [63 : 0] x);
 for (int j = 0; j < 64; j++) begin
  transform[j * 8 +: 8] = x[j] ? 8'hFF : 8'h00;
 end
endfunction
...
always @* begin
 y = transform(x);
end
like image 102
Serge Avatar answered Jan 22 '26 04:01

Serge


If n is a parameter you can do:

always_comb begin
  y = '0;
  for(int idx=0; idx<($bits(y)/n) && idx<$bits(x); idx++) begin
    y[idx*n +: n] = {n{x[idx]}};
  end
end

If n is a signal you have to assign each bit:

always_comb begin
  y = '0;
  foreach(y[idx]) begin
    y[idx] = x[ idx/n ];
  end
end

A variable divisor will add timing and area overhead. Depending on your design target, it may or may not be an issue (synthesis optimization or simulation only).

like image 23
Greg Avatar answered Jan 22 '26 06:01

Greg