2017-07-26 17 views
0

我是Verilog的開始者。我閱讀了幾種關於推薦的Verilog編碼風格的材料,如this paperstackoverflow's questions
現在,我從他們那裏瞭解到,建議「兩個總是擋風格」。將代碼分成兩部分,一部分是修改next的組合塊,另一個是將其分配給statereg的順序塊。如何用兩個狀態寄存器以兩種狀態一次寫入verilog代碼?

reg [1:0] state, next; 

always @(posedge clk or negedge rst_n) 
    if (!rst_n) 
     state <= IDLE; 
    else 
     state <= next; 

always @(state or go or ws) begin 
    next = 'bx; 
    rd = 1'b0; 
    ds = 1'b0; 
    case (state) 
     IDLE : if (go) next = READ; 
       else next = IDLE; 
... 

這是我的問題。我發現的所有示例代碼都只有一對名爲statenext的寄存器。
但是,如果有多個regs保存某些種類的狀態,我應該如何編寫這個statenext樣式的代碼?
正在準備next與它們相對應的regs看起來有點多餘,因爲所有regs都會加倍。

例如,請看下面寫的RS232c的UART發送器代碼。 它需要wait_count,statesend_buf作爲state regs。所以,我寫了一個組合塊的相應wait_count_next,state_nextsend_buf_next作爲next。這對我來說看起來有點多餘和麻煩。有沒有其他正確的方法?

module uart_sender #(
    parameter clock = 50_000_000, 
    parameter baudrate = 9600 
) (
    input clk, 
    input go, 
    input [7:0] data, 
    output tx, 
    output ready 
); 

parameter wait_time = clock/baudrate; 

parameter send_ready = 10'b0000000000, 
     send_start = 10'b0000000001, 
     send_stop = 10'b1000000000; 

reg [31:0] wait_count = wait_time, 
     wait_count_next = wait_time; 
reg [9:0] state = send_ready, 
     state_next = send_ready; 
reg [8:0] send_buf = 9'b111111111, 
     send_buf_next = 9'b111111111; 

always @(posedge clk) begin 
    state <= state_next; 
    wait_count <= wait_count_next; 
    send_buf <= send_buf_next; 
end 

always @(*) begin 
    state_next = state; 
    wait_count_next = wait_count; 
    send_buf_next = send_buf; 
    case (state) 
     send_ready: begin 
      if (go == 1) begin 
       state_next = send_start; 
       wait_count_next = wait_time; 
       send_buf_next = {data, 1'b0}; 
      end 
     end 
     default: begin 
      if (wait_count == 0) begin 
       if (state == send_stop) 
        state_next = send_ready; 
       else 
        state_next = {state[8:0], 1'b0}; 
       wait_count_next = wait_time; 
       send_buf_next = {1'b1, send_buf[8:1]}; 
      end 
      else begin 
       wait_count_next = wait_count - 1; 
      end 
     end 
    endcase 
end 

assign tx = send_buf[0]; 
assign ready = state == send_ready; 

endmodule 
+1

其基本思想是將邏輯分爲2部分組合和排列。首先,只有2個總是沒有真正的需要。你可以有更多的,即多個總是塊可以代表你的組合邏輯部分。此外,沒有必要徹底翻轉所有信號。如果你建立一個狀態機,你只需要觸發它的輸入或輸出。沒有必要翻動其他中間信號。某些設計可能需要您觸發模塊的輸入或輸出。所以,你決定在哪裏放置這些拖鞋。 – Serge

回答

1

我認爲你做得很好,並正確地觸發了變量。問題是沒有觸發器,你會有一個循環。也就是說,如果你寫的東西像下面這樣,模擬將循環和硅可能會燒壞:

always_comb wait_count = wait_count - 1; 

所以,你需要策劃這通過插入觸發器:

always_ff @(posedge clk) 
    wait_count <= wait_count - 1; 

或者你的情況您在使用中間wait_count_next這是一個良好的作風:

always_ff @(posedge clk) 
    wait_count_next <= wait_count; 
always_comb 
    wait_count = wait_count_next; 

你可能會或可能不會有最後一次分配的問題。您想將哪個版本的信號分配到txready?失敗的人還是不是?

是的,你可以將這些塊分成多個塊,但在這種情況下似乎沒有必要。

是的,另一種風格是將所有東西都寫在一個單獨的觸發器中。但是這會降低可讀性,會更容易出錯,並且可能存在綜合問題。

相關問題