Finite state machines¶
- yosys> help $fsm¶
- Simulation model (verilog)¶
2712module \$fsm (CLK, ARST, CTRL_IN, CTRL_OUT); 2713 2714 parameter NAME = ""; 2715 2716 parameter CLK_POLARITY = 1'b1; 2717 parameter ARST_POLARITY = 1'b1; 2718 2719 parameter CTRL_IN_WIDTH = 1; 2720 parameter CTRL_OUT_WIDTH = 1; 2721 2722 parameter STATE_BITS = 1; 2723 parameter STATE_NUM = 1; 2724 parameter STATE_NUM_LOG2 = 1; 2725 parameter STATE_RST = 0; 2726 parameter STATE_TABLE = 1'b0; 2727 2728 parameter TRANS_NUM = 1; 2729 parameter TRANS_TABLE = 4'b0x0x; 2730 2731 input CLK, ARST; 2732 input [CTRL_IN_WIDTH-1:0] CTRL_IN; 2733 output reg [CTRL_OUT_WIDTH-1:0] CTRL_OUT; 2734 2735 wire pos_clk = CLK == CLK_POLARITY; 2736 wire pos_arst = ARST == ARST_POLARITY; 2737 2738 reg [STATE_BITS-1:0] state; 2739 reg [STATE_BITS-1:0] state_tmp; 2740 reg [STATE_BITS-1:0] next_state; 2741 2742 reg [STATE_BITS-1:0] tr_state_in; 2743 reg [STATE_BITS-1:0] tr_state_out; 2744 reg [CTRL_IN_WIDTH-1:0] tr_ctrl_in; 2745 reg [CTRL_OUT_WIDTH-1:0] tr_ctrl_out; 2746 2747 integer i; 2748 2749 task tr_fetch; 2750 input [31:0] tr_num; 2751 reg [31:0] tr_pos; 2752 reg [STATE_NUM_LOG2-1:0] state_num; 2753 begin 2754 tr_pos = (2*STATE_NUM_LOG2+CTRL_IN_WIDTH+CTRL_OUT_WIDTH)*tr_num; 2755 tr_ctrl_out = TRANS_TABLE >> tr_pos; 2756 tr_pos = tr_pos + CTRL_OUT_WIDTH; 2757 state_num = TRANS_TABLE >> tr_pos; 2758 tr_state_out = STATE_TABLE >> (STATE_BITS*state_num); 2759 tr_pos = tr_pos + STATE_NUM_LOG2; 2760 tr_ctrl_in = TRANS_TABLE >> tr_pos; 2761 tr_pos = tr_pos + CTRL_IN_WIDTH; 2762 state_num = TRANS_TABLE >> tr_pos; 2763 tr_state_in = STATE_TABLE >> (STATE_BITS*state_num); 2764 tr_pos = tr_pos + STATE_NUM_LOG2; 2765 end 2766 endtask 2767 2768 always @(posedge pos_clk, posedge pos_arst) begin 2769 if (pos_arst) begin 2770 state_tmp = STATE_TABLE[STATE_BITS*(STATE_RST+1)-1:STATE_BITS*STATE_RST]; 2771 for (i = 0; i < STATE_BITS; i = i+1) 2772 if (state_tmp[i] === 1'bz) 2773 state_tmp[i] = 0; 2774 state <= state_tmp; 2775 end else begin 2776 state_tmp = next_state; 2777 for (i = 0; i < STATE_BITS; i = i+1) 2778 if (state_tmp[i] === 1'bz) 2779 state_tmp[i] = 0; 2780 state <= state_tmp; 2781 end 2782 end 2783 2784 always @(state, CTRL_IN) begin 2785 next_state <= STATE_TABLE[STATE_BITS*(STATE_RST+1)-1:STATE_BITS*STATE_RST]; 2786 CTRL_OUT <= 'bx; 2787 // $display("---"); 2788 // $display("Q: %b %b", state, CTRL_IN); 2789 for (i = 0; i < TRANS_NUM; i = i+1) begin 2790 tr_fetch(i); 2791 // $display("T: %b %b -> %b %b [%d]", tr_state_in, tr_ctrl_in, tr_state_out, tr_ctrl_out, i); 2792 casez ({state, CTRL_IN}) 2793 {tr_state_in, tr_ctrl_in}: begin 2794 // $display("-> %b %b <- MATCH", state, CTRL_IN); 2795 {next_state, CTRL_OUT} <= {tr_state_out, tr_ctrl_out}; 2796 end 2797 endcase 2798 end 2799 end 2800 2801endmodule