编写 RTL 逻辑的问题

Issue in writing a RTL logic

假设我有一个总线 B。我想创建一个新的总线 C,如果 B 的相应索引为 1,其信号延迟与其索引成比例的幅度。让我用一个例子来解释假设我原来的总线 B(宽度为 5)的值为 10111,并且 B 永远保持在该值。现在我想让 C 变成这样:

clk 0: 00001
clk 1: 00011
clk 2: 00111
clk 3: 10111

(请注意,总线 B 中的第 3 位是 0,因此在位位置 2 之后,C 的 MSB(位位置 4)在下一个时钟中应该为高)。

下图是对应的波形


B[0] ,,,|'''''''''''''''''''''''''''''''''
B[1] ,,,|'''''''''''''''''''''''''''''''''
B[2] ,,,|'''''''''''''''''''''''''''''''''
B[3] ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
B[4] ,,,|'''''''''''''''''''''''''''''''''

clk   ,,|''|,,|''|,,|''|,,|''|,,|''|,,|''|

C[0] ,,,|'''''''''''''''''''''''''''''''''
C[1] ,,,,,,,,,|'''''''''''''''''''''''''''
C[2] ,,,,,,,,,,,,,,,|'''''''''''''''''''''
C[3] ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
C[4] ,,,,,,,,,,,,,,,,,,,,,,|''''''''''''''

我如何使用 systemverilog 在 synthesizable RTL 逻辑中对此进行建模并且总是 block.I 正在寻找与此类似的东西(这只是一个伪代码):

Logic[width-1:0][width-1:0] temp;
logic hit_zero; //This is a variable seen and modified by all the generated always blocks(I am not sure if that's allowed)
generate
   for (genvar i = 0; i < width; i++) begin
        always @(posedge clk) begin
              if (B[i] == 1) begin
                 temp[i] <= temp[i] << i;
                 if (hit_zero) begin
                   temp[i] <= temp[i] << (pos+1);
                   hit_zero <= 0;
                 end
                 pos <= i;
              end else begin
                 temp[i] <= temp[i] << i;
                 hit_zero <= 1;  
              end
              temp[i][0] <= B[i];
        end
   end
  endgenerate
  generate 
   for (genvar i = 0; i < width; i++) begin 
    assign C[i] = temp[i][i];
   end
  endgenerate

我提出了一个 always 块的示例,它似乎可以完成您想要的部分,至少在模拟中是这样。它应该是可合成的,虽然我没有尝试过。它需要一个复位信号来设置初始值。所以,你可以尝试把它作为你探索的基地。

需要pos指向当前位位置,根据B(incr)的位状态递增。

需要

done 才能使循环可综合。

  logic clk, reset;
  logic [4:0] B,C;

  reg[4:0]creg;
  int pos;
  int incr;
  bit done;

  always @(posedge clk) begin
    if (reset) begin
      pos <= 0;
      creg <= 0;
    end
    else begin
      incr = 0;
      done = 0;
      for (int i = 0; i < 5; i++) begin
        if (!done && i >= pos) begin
          incr++;
          creg[i] <= B[i];
          if (B[i])
            done = 1;
        end
      end
      pos <= pos + incr;
    end
  end

  assign C = creg;