Finite state machines¶
- yosys> help $fsm¶
- Simulation model (verilog)¶
2567module \$fsm (CLK, ARST, CTRL_IN, CTRL_OUT); 2568 2569 parameter NAME = ""; 2570 2571 parameter CLK_POLARITY = 1'b1; 2572 parameter ARST_POLARITY = 1'b1; 2573 2574 parameter CTRL_IN_WIDTH = 1; 2575 parameter CTRL_OUT_WIDTH = 1; 2576 2577 parameter STATE_BITS = 1; 2578 parameter STATE_NUM = 1; 2579 parameter STATE_NUM_LOG2 = 1; 2580 parameter STATE_RST = 0; 2581 parameter STATE_TABLE = 1'b0; 2582 2583 parameter TRANS_NUM = 1; 2584 parameter TRANS_TABLE = 4'b0x0x; 2585 2586 input CLK, ARST; 2587 input [CTRL_IN_WIDTH-1:0] CTRL_IN; 2588 output reg [CTRL_OUT_WIDTH-1:0] CTRL_OUT; 2589 2590 wire pos_clk = CLK == CLK_POLARITY; 2591 wire pos_arst = ARST == ARST_POLARITY; 2592 2593 reg [STATE_BITS-1:0] state; 2594 reg [STATE_BITS-1:0] state_tmp; 2595 reg [STATE_BITS-1:0] next_state; 2596 2597 reg [STATE_BITS-1:0] tr_state_in; 2598 reg [STATE_BITS-1:0] tr_state_out; 2599 reg [CTRL_IN_WIDTH-1:0] tr_ctrl_in; 2600 reg [CTRL_OUT_WIDTH-1:0] tr_ctrl_out; 2601 2602 integer i; 2603 2604 task tr_fetch; 2605 input [31:0] tr_num; 2606 reg [31:0] tr_pos; 2607 reg [STATE_NUM_LOG2-1:0] state_num; 2608 begin 2609 tr_pos = (2*STATE_NUM_LOG2+CTRL_IN_WIDTH+CTRL_OUT_WIDTH)*tr_num; 2610 tr_ctrl_out = TRANS_TABLE >> tr_pos; 2611 tr_pos = tr_pos + CTRL_OUT_WIDTH; 2612 state_num = TRANS_TABLE >> tr_pos; 2613 tr_state_out = STATE_TABLE >> (STATE_BITS*state_num); 2614 tr_pos = tr_pos + STATE_NUM_LOG2; 2615 tr_ctrl_in = TRANS_TABLE >> tr_pos; 2616 tr_pos = tr_pos + CTRL_IN_WIDTH; 2617 state_num = TRANS_TABLE >> tr_pos; 2618 tr_state_in = STATE_TABLE >> (STATE_BITS*state_num); 2619 tr_pos = tr_pos + STATE_NUM_LOG2; 2620 end 2621 endtask 2622 2623 always @(posedge pos_clk, posedge pos_arst) begin 2624 if (pos_arst) begin 2625 state_tmp = STATE_TABLE[STATE_BITS*(STATE_RST+1)-1:STATE_BITS*STATE_RST]; 2626 for (i = 0; i < STATE_BITS; i = i+1) 2627 if (state_tmp[i] === 1'bz) 2628 state_tmp[i] = 0; 2629 state <= state_tmp; 2630 end else begin 2631 state_tmp = next_state; 2632 for (i = 0; i < STATE_BITS; i = i+1) 2633 if (state_tmp[i] === 1'bz) 2634 state_tmp[i] = 0; 2635 state <= state_tmp; 2636 end 2637 end 2638 2639 always @(state, CTRL_IN) begin 2640 next_state <= STATE_TABLE[STATE_BITS*(STATE_RST+1)-1:STATE_BITS*STATE_RST]; 2641 CTRL_OUT <= 'bx; 2642 // $display("---"); 2643 // $display("Q: %b %b", state, CTRL_IN); 2644 for (i = 0; i < TRANS_NUM; i = i+1) begin 2645 tr_fetch(i); 2646 // $display("T: %b %b -> %b %b [%d]", tr_state_in, tr_ctrl_in, tr_state_out, tr_ctrl_out, i); 2647 casez ({state, CTRL_IN}) 2648 {tr_state_in, tr_ctrl_in}: begin 2649 // $display("-> %b %b <- MATCH", state, CTRL_IN); 2650 {next_state, CTRL_OUT} <= {tr_state_out, tr_ctrl_out}; 2651 end 2652 endcase 2653 end 2654 end 2655 2656endmodule