2017-10-22 112 views
1

我試圖設計將產生以下序列的硬件,F =前N個整數的和,即1 + 2 ... + N。 (例如,如果N = 3,則F = 1 + 2 + 3 = 6)。我正在實現一個模塊,只要輸入N改變,它就會在最後N個時鐘週期後產生F. N將是任何4位數字(意味着F必須是7位長)。當新的F被計算時,N不會改變。這裏是我的嘗試:在Verilog中實現最大爲N的整數求和

module Fib (clock, reset, N, Fib); 

input clock, reset; input [3:0] N; 
output [6:0] Fib; 

reg [6:0] Fib; 
// local vars 
reg [2:0] Nprev; 
reg [2:0] count; 
reg state, next_state; 

// control lines 
reg [1:0] Fmux, Cmux; 

//status line 
wire zero, equal; 

parameter wait4newN=1'b0, 
    wait4Zero=1'b1; 

// Datapath 
[email protected](posedge clock) 
    case(Fmux) 
    2'h0 : Fib <= N; 
    2'h1 : Fib <= Fib + count; 
    endcase 

[email protected](posedge clock) 
case (Cmux) 
    2'h0 : count <= N-1; 
    2'h1 : count <= count - 1; 
    endcase 

assign zero = (count == 0); 
assign equal = (Nprev==N); 

// Controller 
[email protected](posedge clock) 
    Nprev <= N; 

[email protected](posedge clock) 
    if (reset) state <= wait4newN; 
    else 
     state <= next_state; 

[email protected](*) 
    begin 
    Fmux = 0; Cmux = 0; 
    case (state) // synopsys full_case parallel_case 
     wait4newN : 
      if (!equal) 
      begin 
       Fmux = 0; Cmux = 0; 
       next_state=wait4newN; 
      end 
      else 
       begin 
       Fmux = 1; Cmux = 1; 
       next_state=wait4Zero; 
       end 
     wait4Zero : 
      if(!zero) 
       begin 
        Fmux = 1; Cmux = 1; 
        next_state = wait4Zero; 
       end 
      else 
      begin 
       Fmux = 0; Cmux =0; 
       next_state =wait4newN; 
      end 
     default: 
     $display("why am I here?"); 
     endcase 
    end 
endmodule 

我的測試夾具是

// Testbench 
module test; 

reg clk, reset; 
reg [3:0] N; 
reg [6:0] Fib; 

    // Instantiate device under test 
Fib fibInstance(.clock(clk),.reset(reset), .N(N), .Fib(Fib)); 

    initial begin 
    // Dump waves 
    $dumpfile("dump.vcd"); 
    $dumpvars(1, test); 

    clk = 0; 
    reset = 1; 
    N = 5; 
    $display("wait4newN N: %0h, Fib: %0h", 
     N, Fib); 

    toggle_clk; 
    $display("wait4Zero N: %0h, Fib: %0h", 
     N, Fib); 

    toggle_clk; 
    $display("wait4Zero N: %0h, Fib: %0h", 
     N, Fib); 

    toggle_clk; 
    $display("wait4Zero N: %0h, Fib: %0h", 
     N, Fib); 

    toggle_clk; 
    $display("wait4Zero N: %0h, Fib: %0h", 
     N, Fib); 

    toggle_clk; 
    $display("wait4Zero N: %0h, Fib: %0h", 
     N, Fib); 

    toggle_clk; 
    $display("wait4newN N: %0h, Fib: %0h", 
     N, Fib); 
    end 

    task toggle_clk; 
    begin 
     #5 clk = ~clk; 
     #5 clk = ~clk; 
    end 
    endtask 

endmodule 

模擬的結果是XX爲F.

[2017-10-21 20:17:23 EDT] iverilog '-Wall' '-g2012' design.sv testbench.sv && unbuffer vvp a.out 
VCD info: dumpfile dump.vcd opened for output. 
wait4newN N: 5, Fib: xx 
wait4Zero N: 5, Fib: xx 
wait4Zero N: 5, Fib: xx 
wait4Zero N: 5, Fib: xx 
wait4Zero N: 5, Fib: xx 
wait4Zero N: 5, Fib: xx 
wait4newN N: 5, Fib: xx 
Done 

什麼我做錯了嗎?

非常感謝您爲我們提前準備的時間。

+0

有一件事是你忘了在你的測試平臺上清除'reset'信號,所以它會導致* wat4newN *和* wait4Zero *之間來回切換。此外,由於復位信號行爲,它看起來像* Fmux *和* clock *之間的競賽,使其在posedge處爲'0'。 – Serge

回答

2

該問題似乎歸因於重設。這裏是正在發生的事情一個普通的解釋:

在你FIB模塊,你不上初始化變量重置。當應用重置時,狀態從'X'變爲'wait4newN'。現在組合塊被同一時鐘觸發並且case語句被執行。由此FMux直接X-> 1。其結果是,方程 「Fib的< =蛋白原+計數」 總是產生 'X',因爲Fib的從未初始化爲零

除此之外,你是從不否認重置爲零從您的測試臺。所以FSM狀態永遠不會改變。

Fib模塊中,使用順序塊中的復位。

always @(posedge clk) begin // Assuming synchronous reset 
    if(reset) begin 
    // Reset variables 
    end else begin 
    // other logic 
    end 
end 

有關處理復位的更多信息,請this siteCummings Reset related Paper

+0

完美。非常感謝您的澄清和鏈接! – chikitin