How to write a verilog code in two-always-block style with multiple state regs? -
i'm begginer of verilog. read several materials recommended verilog coding styles this paper , stackoverflow's questions.
now, learned them "two block style" recommended; separate code 2 parts, 1 combinational block modifies next, , sequential block assigns state reg this.
reg [1:0] state, next; @(posedge clk or negedge rst_n) if (!rst_n) state <= idle; else state <= next; @(state or go or ws) begin next = 'bx; rd = 1'b0; ds = 1'b0; case (state) idle : if (go) next = read; else next = idle; ... and here question. example codes found have 1 pair of registers named state , next.
however, if there multiple regs preserve kinds of state, how should write codes in state-and-next style?
preparing next regs corresponding each of them looks little redundant because regs doubled.
for instance, please @ uart sender code of rs232c wrote below. needed wait_count, state , send_buf state regs. so, wrote corresponding wait_count_next, state_next , send_buf_next next combinational block. looks bit redundant , troublesome me. there other proper way?
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; @(posedge clk) begin state <= state_next; wait_count <= wait_count_next; send_buf <= send_buf_next; end @(*) 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
i think did job , correctly flopped variables. issue without flops have loop. i.e. if write following, simulation loop , silicon burn out:
always_comb wait_count = wait_count - 1; so, need stage inserting flop:
always_ff @(posedge clk) wait_count <= wait_count - 1; or in case you used intermediate wait_count_next style:
always_ff @(posedge clk) wait_count_next <= wait_count; always_comb wait_count = wait_count_next; you might or might not have issue last assignments. version of signals want assign tx , ready? flopped 1 or not?
and yes, can split theses blocks in multiple blocks, in case there seems no need.
and yes, other style write in single flop block. reduce readability, more prone errors , might have synthesis issues.
Comments
Post a Comment