我是Verilog的開始者。我閱讀了幾種關於推薦的Verilog編碼風格的材料,如this paper和stackoverflow's questions。
現在,我從他們那裏瞭解到,建議「兩個總是擋風格」。將代碼分成兩部分,一部分是修改next
的組合塊,另一個是將其分配給state
reg的順序塊。如何用兩個狀態寄存器以兩種狀態一次寫入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;
...
這是我的問題。我發現的所有示例代碼都只有一對名爲state
和next
的寄存器。
但是,如果有多個regs保存某些種類的狀態,我應該如何編寫這個state
和next
樣式的代碼?
正在準備next
與它們相對應的regs看起來有點多餘,因爲所有regs都會加倍。
例如,請看下面寫的RS232c的UART發送器代碼。 它需要wait_count
,state
和send_buf
作爲state
regs。所以,我寫了一個組合塊的相應wait_count_next
,state_next
和send_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
其基本思想是將邏輯分爲2部分組合和排列。首先,只有2個總是沒有真正的需要。你可以有更多的,即多個總是塊可以代表你的組合邏輯部分。此外,沒有必要徹底翻轉所有信號。如果你建立一個狀態機,你只需要觸發它的輸入或輸出。沒有必要翻動其他中間信號。某些設計可能需要您觸發模塊的輸入或輸出。所以,你決定在哪裏放置這些拖鞋。 – Serge