Verilog每位扩展n次

时间:2019-02-20 09:49:06

标签: verilog system-verilog

我想将每个位扩展n次。 例如,

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

在Verilog或SystemVerilog中是否有任何简单的方法(即不使用generate block)?

编辑19.02.21

实际上,我正在将64位掩码转换为512位掩码,但这与{8 {something}}不同。我当前的代码如下:

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

我只是想知道还有更多的“美丽”方式。

3 个答案:

答案 0 :(得分:3)

我认为您的方法不错。没有某种循环就无法做到这一点(除非您想手动键入所有迭代)。实现它可能有几种变体。

例如,使用'+:'运算符而不是表达式,这使它有点简化。

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

以上方法实际上生成的64始终会阻塞(与您的原始方法一样)。虽然每个块的敏感度列表仅是'x'的一位。

您可以将for循环移动到Always块内:

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

这将最终成为一个始终阻止的块,但灵敏度列表将包括“ x”的所有位。

如果多次使用此操作,则可以使用函数:

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

答案 1 :(得分:1)

我的答案可能不是最好的答案,但是如果我是你,我会做下面的事情(假设x和y是模块中将用于同步设计的寄存器):

// your module name and ports

reg [63:0] x;
reg [511:0] y;

// your initializations

always@(posedge clk) begin

y[0+:8] <= x[0] ? 8'hff : 8'h00;
y[8+:8] <= x[1] ? 8'hff : 8'h00;
y[16+:8] <= x[2] ? 8'hff : 8'h00;
y[24+:8] <= x[3] ? 8'hff : 8'h00;
y[32+:8] <= x[4] ? 8'hff : 8'h00;
              *
              *
              *
y[504+:8] <= x[63] ? 8'hff : 8'h00;
end

对于始终不同的条件:

// your module name and ports

reg [63:0] x;
reg [511:0] y;

// your initializations

always@('some sensitivity conditions') begin

y[0+:8] <= x[0] ? 8'hff : 8'h00;
y[8+:8] <= x[1] ? 8'hff : 8'h00;
y[16+:8] <= x[2] ? 8'hff : 8'h00;
y[24+:8] <= x[3] ? 8'hff : 8'h00;
y[32+:8] <= x[4] ? 8'hff : 8'h00;
              *
              *
              *
y[504+:8] <= x[63] ? 8'hff : 8'h00;
end

但是,如果我想要一个单独的模块来输入x和输出y,则可以执行以下操作:

module mask_conversion(

input [63:0] x;
output [511:0] y;

);

assign y[0+:8] = x[0] ? 8'hff : 8'h00;
assign y[8+:8] = x[1] ? 8'hff : 8'h00;
assign y[16+:8] = x[2] ? 8'hff : 8'h00;
assign y[24+:8] = x[3] ? 8'hff : 8'h00;
assign y[32+:8] = x[4] ? 8'hff : 8'h00;
              *
              *
              *
assign y[504+:8] = x[63] ? 8'hff : 8'h00;

endmodule

键入所有这些并不难,您只需复制和粘贴并手动更改数字。这样一来,您将获得可以保证执行所需功能的代码。

答案 2 :(得分:1)

如果n是参数,则可以执行以下操作:

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

如果n是信号,则必须分配每个位:

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

可变除数会增加时序和面积开销。根据您的设计目标,可能不是问题(仅综合优化或仿真)。