我是Verilog的先驱。我阅读了一些关于推荐的Verilog编码样式的材料,如this paper和stackoverflow's questions
现在,我向他们学习了“两个总是阻挡风格”的建议;将代码分成两部分,一部分是修改next
的组合块,另一部分是一个顺序块,将它分配给state
reg。就像这样。
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
相对应的wait_count
regs看起来有点多余,因为所有regs都会加倍。
例如,请查看我在下面写的RS232c的UART发送器代码。
它需要state
,send_buf
和state
作为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
。这对我来说看起来有点多余和麻烦。还有其他正确的方法吗?
DD/MM/YYYY
答案 0 :(得分: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;
您可能会或可能不会遇到上次分配的问题。您要将哪个版本的信号分配给tx
和ready
?失败的那个?
是的,您可以在多个块中拆分这些块,但在这种情况下似乎没有必要。
是的,另一种风格是在单个翻牌中写入所有内容总是阻止。但这会降低可读性,更容易出错,并可能出现综合问题。