3

Look at the following statement. c_r gets assigned an xor versioned of all 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

The design works, however is there a possibility to refactor the statement for easier maintenance and readability?

Note: c is defined as logic [7:0] c[16][16];

mcleod_ideafix
  • 11,128
  • 2
  • 24
  • 32
Razer
  • 7,843
  • 16
  • 55
  • 103

3 Answers3

2

I would propose the following:

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

The foreach will iterate through all selected indexes. See 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.

Greg
  • 18,111
  • 5
  • 46
  • 68
  • 1
    Not related to the question, so I will leave this as a comment: I prefer keeping my sequential logic as simple assignments. This way all the code for calculations are group together. I find this helps with code readability as i don't have to jump to another always block to see final calculation. Having an `next_*` is a tittle more typing but well worth it when debugging. – Greg Aug 21 '15 at 17:24
1

You could try using a for loop inside to compute the XOR result and assign that to the c_r slice:

  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

I'm not sure how well this will synthesize with your tool, but I've seen my colleagues use these kind of tricks (in VHDL) all the time.

Tudor Timi
  • 7,453
  • 1
  • 24
  • 53
  • This solution achieves the goal of easier maintenance, because c[k][0] to c[k][15] are not listed out manually so it is easier to change the number "16" in the future, if need be. However, I think some synthesis tools won't know how to best rearrange the chain of xors to reduce logic depth, whereas with a reduction-xor operator the tool has more flexibility in choosing the xor topology. In these types of scenarios in the past, I've used a loop to rearrange the array indices in such a way that a reduction operator can be used. – mattgately Aug 21 '15 at 14:28
  • 2
    @Morgan It's in section 11.3 Operators of the IEEE 1800-2012 standard. – Tudor Timi Aug 21 '15 at 15:13
0

Reduction operators are useful for this, a short example:

wire result;
wire [3:0] bus;

//assign result = bus[0] ^ bus[1] ^ bus[2] ^ bus[3];
assign result = ^bus;

So the unary ^ collapses the bus to a single bit, this also works for & and |.

In your case I believe that this should work:

always_ff @ (posedge clk_i)
begin
  for(k = 0; k < 16; k++)
    c_r[k*8 +: 8] <= ^c[k];
end

If this is not possible embedding a second loop (which is extracted to a combinatorial section):

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

You are effectively describing 16 sets of XOR logic in parallel.

Morgan
  • 19,934
  • 8
  • 58
  • 84
  • Thanks for that. Unfortunately, this does not work yet. `c` is defined as `logic [7:0] c[16][16];`. With the proposed solutio, I get following error message: `Error-[IMEMCT] Invalid memory usage design.sv, 17 Memory or memory slice is not permitted to be used in following contexts: 1. conditional expression in if/case/while statements and so on 2. source or target expression of assignment statements 3. operand of equality operator Expression : (^c[k])` – Razer Aug 21 '15 at 08:21
  • How would such a loop look like? I'm confused because it would be something like `c_xor[k] = c_xor[k] ^ c[k][l]` right? – Razer Aug 21 '15 at 08:38
  • We are not here for the easy things ;-). I don't understand the inner loop. Wouldn't that be a combinatorial loop? – Razer Aug 21 '15 at 09:06
  • Yes. That would be one possibility. However, I think it would not improve the readability. – Razer Aug 21 '15 at 09:12