2017-02-27 130 views
0

我必須設計一個使用FPGA和Verilog的紅外發射器。verilog紅外輸出

其中一個條件是每10Hz發送一個數據包,我有一個計數器在主時鐘(100MHz)的10Hz處創建一個輔助時鐘。 該數據包包含開始間隙選擇間隙右側間隙左側間隙前向間隙後向間隙。我有一個FSM在10Hz輔助時鐘的正向邊緣進行這種轉換。 數據包中的每個塊都有其大小,Gap只是將它們分開的空白空間。方向塊選擇時尺寸較大,否則較小。 在接收器的脈衝頻率爲36kHz的條件下,我有另一個計數器,它將主時鐘減少到36kHz,我用這個計數器爲Start,Select等產生脈衝大小,並在計數器遞增時使輸出爲1到那個大小(對於開始的情況,請選擇..)和0爲間隙狀態。

但是,當我通過智能手機攝像頭查看LED時,顯示它始終處於正常狀態,這是我期望看到的,因爲它應該每秒發送數據包10次。

問題是,汽車根本不動,我的問題是這是做事情的正確邏輯還是我錯過了什麼? 感謝

請求代碼:

爲36kHz脈衝

[email protected](posedge CLK) begin 
    if(RESET) begin 
     Counter <= 0; 
     SEC_CLK <= 0; 
    end 
    else if(Counter == 2778) begin 
     Counter <= 0; 
     SEC_CLK <= 1'b1; 
    end 
    else begin 
     Counter <= Counter + 1; 
     SEC_CLK <= 1'b0; 
    end 
end 

的10Hz的計數器,計數器,不知道是好是減少36kHz或使用主時鐘,但它是一個不錯的輪數,所以我使用的主時鐘

[email protected](posedge CLK) begin 
    if(sec_counter == 100000) begin 
     sec_counter <= 0; 
     send <= 1; 
    end 
    else begin 
     sec_counter <= sec_counter +1; 
     send <= 0; 
    end 
end` 

的FSM邏輯:

[email protected](Curr_State) begin 
      case(Curr_State) 
       1'd0: begin //START 
        Next_State <= 1'd1; 
        Previous_State <= Next_State; 
        max_count <= StartBurstSize; 
        flag <= 0; 
       end 
       1'd1: begin //GAP 
        if(Previous_State <= 1'd7) 
         Next_State<=1'd0; 
        else 
         Next_State <= Previous_State +1; 
        max_count <= GapSize; 
        flag <= 1; 
             IR_LED = 1'b1; 

        if(change) 
         Curr_State <= Next_State; 
        else 
         Next_State <= Curr_State; 
       end 
       1'd2: begin //SELECT 
        Next_State <= 1'd1; 
        Previous_State <= Curr_State; 
        max_count <= CarSelectBurstSize; 
        IR_LED = 1'b0; 
        flag <= 0; 
        if(change) 
         Curr_State <= Next_State; 
        else 
         Next_State <= Curr_State; 
       end 
       1'd3: begin //RIGHT 
        if(BTNR) 
         max_count <= AsserBurstSize; 
        else 
         max_count <= DeAssertBurstSize; 
        Next_State <= 1'd1; 
        Previous_State <= Curr_State; 
        flag <= 0; 
        if(change) 
         Curr_State <= Next_State; 
        else 
         Next_State <= Curr_State; 
         IR_LED = 1'b1; 
       end 
       1'd4: begin //LEFT 
        if(BTNL) 
         max_count <= AsserBurstSize; 
        else 
         max_count <= DeAssertBurstSize; 
        Next_State <= 1'd1; 
        Previous_State <= Curr_State; 
        flag <= 0; 
        if(change) 
         Curr_State <= Next_State; 
        else 
         Next_State <= Curr_State; 
         IR_LED = 1'b1; 
       end 
       1'd5: begin //FORWARD 
        if(BTNU) 
         max_count <= AsserBurstSize; 
        else 
         max_count <= DeAssertBurstSize; 
        Next_State <= 1'd1; 
        Previous_State <= Curr_State; 
        flag <= 0; 
        if(change) 
         Curr_State <= Next_State; 
        else 
         Next_State <= Curr_State; 
         IR_LED = 1'b1; 
       end 
       1'd6: begin //Backwards 
        if(BTND) 
         max_count <= AsserBurstSize; 
        else 
         max_count <= DeAssertBurstSize; 
        Next_State <= 1'd1; 
        Previous_State <= Curr_State; 
        flag <= 0; 
        if(change) 
         Curr_State <= Next_State; 
        else 
         Next_State <= Curr_State; 
         IR_LED = 1'b1; 
       end 

      endcase 
end 

發送到紅外脈衝LED

[email protected](posedge SEC_CLK) begin 
    if(send) begin 
     if(Pcounter == max_count) begin //COUNTING BLOCK SIZE 
      Pcounter <= 0; 
      IR_LED=1'b0; 
     end 
     else begin 
      if(flag) 
       IR_LED=1'b0; //GAP 
      else 
       IR_LED=1'b1; 
      Pcounter <= Pcounter+1; 
     end 
    end 
end 
+1

很難說沒有看到您的代碼。請在問題中包含您的代碼。輸出波形(如ISim)的屏幕截圖也非常有用。 – duskwuff

回答

0

上有sec_counter沒有復位,這樣的行爲可能是不可預測的(除非你指定一個初始值,當你宣佈REG)。由於您沒有包含代碼的聲明部分,因此很難說清楚。

你的狀態機設計有點不尋常,我認爲你沒有得到你期望的行爲。通常狀態機以兩種方式編碼。一種方法將next_state計算放入一個組合塊中,其中包含所有狀態機輸入和塊的靈敏度列表中的當前狀態。代碼的第二同步總是塊(即靈敏度列表posedge clk)將next_state分配給狀態機時鐘的posedge處的current_state。第二種方法對狀態機和輸出都使用一個同步始終塊。在這種情況下,沒有next_state變量,只需將新值直接賦值給狀態變量,確保爲每個分支或if語句賦值狀態值。第二個版本可以運行得更快,因爲所有的輸出都是註冊的,第一個版本使用較少的邏輯,我個人覺得它更容易解碼。既然你的設計非常慢,我建議使用第一個版本。

由於沒有使用時鐘,您的狀態機實際上並不保持狀態 - 所以它實際上不是狀態機。嘗試從你的時鐘信號運行它。另外,請確保正確處理時鐘域交叉以避免亞穩態問題。

0

我不知道,如果你還在乎這個問題,但在你的case語句您有類似

1'd2: begin //SELECT 

甚至

Previous_State <= 1'd7 

不過,頂了表示小數數字寬度爲1位,所以它不可能與0或1不同,最高有效位只會被丟棄。

你試過模擬這個嗎?