我想将每个位扩展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
我只是想知道还有更多的“美丽”方式。
答案 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
可变除数会增加时序和面积开销。根据您的设计目标,可能不是问题(仅综合优化或仿真)。