簡體   English   中英

如何在Quartus中修復Verilog HDL的長編譯

[英]How to fix long compilation for Verilog HDL in quartus

我一直在嘗試使用Verilog HDL創建計數排序算法,但是當我嘗試對其進行編譯時,Quartus開始對其進行很長時間的編譯。 我不知道是什么問題。

module sort(reset, clk, data_in0,data_in1,data_in2,data_in3,data_in4,data_in5,data_in6,data_in7,data_in8,data_in9, data_out0, data_out1, data_out2, data_out3, data_out4, data_out5, data_out6, data_out7, data_out8, data_out9);

input wire reset, clk;

input wire [1:0] data_in0;

input wire [1:0] data_in1;

input wire [1:0] data_in2;

input wire [1:0] data_in3;

input wire [1:0] data_in4;

input wire [1:0] data_in5;

input wire [1:0] data_in6;

input wire [1:0] data_in7;

input wire [1:0] data_in8;

input wire [1:0] data_in9;

output reg [1:0] data_out0;

output reg [1:0] data_out1;

output reg [1:0] data_out2;

output reg [1:0] data_out3;

output reg [1:0] data_out4;

output reg [1:0] data_out5;

output reg [1:0] data_out6;

output reg [1:0] data_out7;

output reg [1:0] data_out8;

output reg [1:0] data_out9;

reg [1:0] mem [9:0];


reg[9:0] buff [3:0];
integer i,k,j,f,s;

always@ (posedge clk)

begin

    for(i=0; i<4; i=i+1)
    buff[i]<=0;
    if (reset == 1) begin

    for (i = 0; i < 10; i = i + 1) mem[i]<=0;
    s=0;
    f=0;


end

else begin
if (f==0)begin
mem [0] <= data_in0;
mem[1]<=data_in1;

mem[2]<=data_in2;

mem[3]<=data_in3;

mem[4]<=data_in4;

mem[5]<=data_in5;

mem[6]<=data_in6;

mem[7]<=data_in7;

mem[8]<=data_in8;

mem[9]<=data_in9;
f=1;
end
 for( i = 0; i <10 ; i=i+1)
begin
    buff[mem[i]]<=buff[mem[i]]+1;
end
if(s==0) begin
k<=0;
    for( i = 0; i <4 ; i=i+1)
    begin
        for( j = 0; j < 10 ; j = j +1)
        begin
            if(j<buff[i])
            begin
                mem[k]<=i;
                k<=k+1;
            end
        end
    end

end     s=1;    

data_out0 = mem[0];

data_out1 = mem[1];

data_out2 = mem[2];

data_out3 = mem[3];

data_out4 = mem[4];

data_out5 = mem[5];

data_out6 = mem[6];

data_out7 = mem[7];

data_out8 = mem[8];

data_out9 = mem[9];

end

end

endmodule

通過“分析和綜合”部分需要花費很長時間。 我認為這是由於此代碼中的錯誤或錯誤使用運算符引起的,但我不知道它的確切位置。

Verilog中的for循環無法按您期望的方式工作。 這不會逐步執行,但是綜合工具將嘗試展開循環,並且由於所有內容都包含在always @(posedge clk) ,它將在一個時鍾周期內完成所有展開的語句。 使用狀態機重新考慮模塊以實現順​​序。

這是解決問題的基於FSM的解決方案的一個示例。 雖然可以進行很大的改進,但這只是一個起點(並希望能起作用)。

首先,我更改了您的模塊界面。 可以使用離散輸入,但是由於該算法使用索引來在整個輸入域上運行,因此我假設有兩個外部存儲器:一個帶有輸入數據,另一個帶有存儲輸出數據。 該模塊為兩個存儲器以及寫入使能信號和數據總線驅動相應的地址總線。 還有一個busy信號,因此系統的其余部分知道該模塊尚未完成數據排序。 最后,我對16個數字進行了排序,而不是10個。

在內部,我使用了一個存儲元素count ,作為保存輸入數據直方圖的向量。 由於該內存很小,因此我已用作四個獨立的寄存器。 這使我可以在同一時鍾周期內使用多個元素“ count”,例如count[3] <= count[3] + count[2] + count[1] + count[0];

我使用的算法版本來自Wikipedia: https : //en.wikipedia.org/wiki/Counting_sort

function countingSort(array, k) is
  count ← new array of k zeros
  for i = 1 to length(array) do
    count[array[i]] ← count[array[i]] + 1
  for i = 2 to k do
    count[i] ← count[i] + count[i - 1]
  for i = length(array) downto 1 do
    output[count[array[i]]] ← array[i]
    count[array[i]] ← count[array[i]] - 1
  return output

這是Verilog模塊:

module sort (
  input wire clk,
  input wire reset,
  output reg [3:0] addr_data_in,
  input wire [1:0] data_in,
  output reg [3:0] addr_data_out,
  output reg [1:0] data_out,
  output reg write_data_out_strobe,
  output reg busy
);

/*
function countingSort(array, k) is
  count ← new array of k zeros
  for i = 1 to length(array) do
    count[array[i]] ← count[array[i]] + 1
  for i = 2 to k do
    count[i] ← count[i] + count[i - 1]
  for i = length(array) downto 1 do
    output[count[array[i]]] ← array[i]
    count[array[i]] ← count[array[i]] - 1
  return output
*/
  localparam
    ZERO         = 3'd0,
    MAKEHIST1    = 3'd1,
    MAKEHIST2    = 3'd2,
    PREFIXSUM    = 3'd3,
    PLACEOUTPUT1 = 3'd4,
    PLACEOUTPUT2 = 3'd5,
    IDLE         = 3'd7
    ;

  reg [4:0] count[0:3];
  reg [2:0] state = IDLE;
  reg [1:0] data;

  always @(posedge clk) begin
    if (reset == 1'b1) begin
      state <= ZERO;
      write_data_out_strobe <= 1'b0;
      busy <= 1'b1;
    end
    else begin
      case (state)
        ZERO:
        //count ← new array of k zeros
          begin
            count[0] <= 4'd0;
            count[1] <= 4'd0;
            count[2] <= 4'd0;
            count[3] <= 4'd0;
            addr_data_in <= 4'd0;
            state <= MAKEHIST1;
          end
        MAKEHIST1:
        //for i = 1 to length(array) do
        //  count[array[i]] ← count[array[i]] + 1
          begin
            data <= data_in;
            addr_data_in <= addr_data_in + 4'd1;
            state <= MAKEHIST2;
          end
        MAKEHIST2:
          begin
            count[data] <= count[data] + 4'd1;
            if (addr_data_in == 4'd0)
              state <= PREFIXSUM;
            else
              state <= MAKEHIST1;
          end
        PREFIXSUM:
        //for i = 2 to k do
        //  count[i] ← count[i] + count[i - 1]
          begin
            count[1] <= count[1] + count[0];
            count[2] <= count[2] + count[1] + count[0];
            count[3] <= count[3] + count[2] + count[1] + count[0];
            addr_data_in <= 4'd15;
            state <= PLACEOUTPUT1;
          end
        PLACEOUTPUT1:
        //for i = length(array) downto 1 do
        //  output[count[array[i]]] ← array[i]
        //  count[array[i]] ← count[array[i]] - 1
          begin
            data <= data_in;
            addr_data_in <= addr_data_in - 4'd1;
            write_data_out_strobe <= 1'b0;
            state <= PLACEOUTPUT2;
          end
        PLACEOUTPUT2:
          begin
            addr_data_out <= count[data] - 5'd1;
            data_out <= data;
            count[data] <= count[data] - 4'd1;
            write_data_out_strobe <= 1'b1;
            if (addr_data_in == 4'd15)
              state <= IDLE;
            else
              state <= PLACEOUTPUT1;
          end
        IDLE:
          begin
            write_data_out_strobe <= 1'b0;
            busy <= 1'b0;
          end
      endcase
    end  // of else
  end  // of always
endmodule

您可以看到,由於我使用count的方式,這肯定會生成很多復用器和解碼器,只是因為在某些地方我使用寄存器值作為count []的地址。 但是,我認為合成速度會更快。 僅供參考,Yosis可以在幾秒鍾內完成。

此外,這里有一個用於上述模塊的測試台:

module tb_counting_sort;
  reg clk, reset;
  wire [3:0] addr_data_in, addr_data_out;
  wire [1:0] data_in,data_out;
  wire write_data_out_strobe, busy;

  sort uut (
    .clk(clk),
    .reset(reset),
    .addr_data_in(addr_data_in),
    .data_in(data_in),
    .addr_data_out(addr_data_out),
    .data_out(data_out),
    .write_data_out_strobe(write_data_out_strobe),
    .busy(busy)
  );

  reg [1:0] vector_in[0:15];
  reg [1:0] vector_out[0:15];
  assign data_in = vector_in[addr_data_in];
  always @(posedge clk)
    if (write_data_out_strobe == 1'b1)
      vector_out[addr_data_out] <= data_out;

  integer i;
  initial begin
    vector_in[0]  = 2'd2;
    vector_in[1]  = 2'd1;
    vector_in[2]  = 2'd0;
    vector_in[3]  = 2'd0;
    vector_in[4]  = 2'd3;
    vector_in[5]  = 2'd1;
    vector_in[6]  = 2'd0;
    vector_in[7]  = 2'd2;
    vector_in[8]  = 2'd1;
    vector_in[9]  = 2'd1;
    vector_in[10] = 2'd3;
    vector_in[11] = 2'd3;
    vector_in[12] = 2'd3;
    vector_in[13] = 2'd2;
    vector_in[14] = 2'd1;
    vector_in[15] = 2'd0;

    reset = 1'b1;
    clk = 1'b0;
    repeat (2) 
      @(posedge clk);
    reset = 1'b0;

    @(negedge busy);
    for (i=0;i<16;i=i+1)
      $write ("%1d ", vector_out[i]);
    $display("");
    $finish;
  end

  always begin
    clk = #5 ~clk;
  end
endmodule

可以在EDAPlayground上查看,模擬或合成這兩個模塊, 網址為https ://www.edaplayground.com/x/6GLj

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM