重写长异或语句
Rewrite long xor statement
看下面的说法。 c_r
被分配了所有 c[k]
.
的异或版本
always_ff @ (posedge clk_i)
begin
for(k = 0; k < 16; k++)
c_r[k*8 +: 8] <= c[k][0] ^ c[k][1] ^ c[k][2] ^ c[k][3] ^ c[k][4] ^ c[k][5] ^ c[k][6] ^ c[k][7] ^ c[k][8] ^ c[k][9] ^ c[k][10] ^ c[k][11] ^ c[k][12] ^ c[k][13] ^ c[k][14] ^ c[k][15];
end
设计可行,但是是否可以重构语句以便于维护和提高可读性?
注:c
定义为logic [7:0] c[16][16];
归约运算符对此很有用,一个简短的例子:
wire result;
wire [3:0] bus;
//assign result = bus[0] ^ bus[1] ^ bus[2] ^ bus[3];
assign result = ^bus;
所以一元 ^
将总线折叠成一位,这也适用于 &
和 |
。
对于你的情况,我认为这应该有效:
always_ff @ (posedge clk_i)
begin
for(k = 0; k < 16; k++)
c_r[k*8 +: 8] <= ^c[k];
end
如果这不可能嵌入第二个循环(提取到组合部分):
logic [15:0] parity_bus;
always_comb begin
for(k = 0; k < 16; k++) begin
parity_bus[k] = 1'b0;
for(int i = 0; i < 16; i++) begin
parity_bus[k] = parity_bus[k] ^c[k][i];
end
end
end
always_ff @ (posedge clk_i) begin
for(k = 0; k < 16; k++) begin
c_r[k*8 +: 8] <= parity_bus[k];
end
end
您有效地并行描述了 16 组 XOR 逻辑。
您可以尝试在内部使用 for
循环来计算异或结果并将其分配给 c_r
切片:
always_ff @ (posedge clk_i)
begin
for(int k = 0; k < 16; k++) begin
logic [7:0] xor_result;
for (int i = 0; i < 16; i++)
xor_result ^= c[k][i];
c_r[k*8 +: 8] <= xor_result;
end
end
我不确定用你的工具综合起来效果如何,但我看到我的同事一直在使用这些技巧(在 VHDL 中)。
我会提出以下建议:
logic [16*8-1:0] c_r, next_c_r;
logic [7:0] c[16][16];
always_comb begin
next_c_r = '0;
foreach(c[idx0,idx1]) begin
next_c_r[idx0*8 +: 8] ^= c[idx0][idx1];
end
end
always_ff @ (posedge clk_i)
begin
c_r <= next_c_r;
end
foreach
将遍历所有选定的索引。参见 IEEE Std 1800-2012 § 12.7.3 The foreach-loop for full syntax usage and functionality. ^=
is a binary bitwise assignment operators, refer to IEEE Std 1800-2012 § 11.4 Operator descriptions. There are various code examples for foreach
and ^=
throughout the LRM。
看下面的说法。 c_r
被分配了所有 c[k]
.
always_ff @ (posedge clk_i)
begin
for(k = 0; k < 16; k++)
c_r[k*8 +: 8] <= c[k][0] ^ c[k][1] ^ c[k][2] ^ c[k][3] ^ c[k][4] ^ c[k][5] ^ c[k][6] ^ c[k][7] ^ c[k][8] ^ c[k][9] ^ c[k][10] ^ c[k][11] ^ c[k][12] ^ c[k][13] ^ c[k][14] ^ c[k][15];
end
设计可行,但是是否可以重构语句以便于维护和提高可读性?
注:c
定义为logic [7:0] c[16][16];
归约运算符对此很有用,一个简短的例子:
wire result;
wire [3:0] bus;
//assign result = bus[0] ^ bus[1] ^ bus[2] ^ bus[3];
assign result = ^bus;
所以一元 ^
将总线折叠成一位,这也适用于 &
和 |
。
对于你的情况,我认为这应该有效:
always_ff @ (posedge clk_i)
begin
for(k = 0; k < 16; k++)
c_r[k*8 +: 8] <= ^c[k];
end
如果这不可能嵌入第二个循环(提取到组合部分):
logic [15:0] parity_bus;
always_comb begin
for(k = 0; k < 16; k++) begin
parity_bus[k] = 1'b0;
for(int i = 0; i < 16; i++) begin
parity_bus[k] = parity_bus[k] ^c[k][i];
end
end
end
always_ff @ (posedge clk_i) begin
for(k = 0; k < 16; k++) begin
c_r[k*8 +: 8] <= parity_bus[k];
end
end
您有效地并行描述了 16 组 XOR 逻辑。
您可以尝试在内部使用 for
循环来计算异或结果并将其分配给 c_r
切片:
always_ff @ (posedge clk_i)
begin
for(int k = 0; k < 16; k++) begin
logic [7:0] xor_result;
for (int i = 0; i < 16; i++)
xor_result ^= c[k][i];
c_r[k*8 +: 8] <= xor_result;
end
end
我不确定用你的工具综合起来效果如何,但我看到我的同事一直在使用这些技巧(在 VHDL 中)。
我会提出以下建议:
logic [16*8-1:0] c_r, next_c_r;
logic [7:0] c[16][16];
always_comb begin
next_c_r = '0;
foreach(c[idx0,idx1]) begin
next_c_r[idx0*8 +: 8] ^= c[idx0][idx1];
end
end
always_ff @ (posedge clk_i)
begin
c_r <= next_c_r;
end
foreach
将遍历所有选定的索引。参见 IEEE Std 1800-2012 § 12.7.3 The foreach-loop for full syntax usage and functionality. ^=
is a binary bitwise assignment operators, refer to IEEE Std 1800-2012 § 11.4 Operator descriptions. There are various code examples for foreach
and ^=
throughout the LRM。