重写长异或语句

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