Finite state machines

yosys> help $fsm
Simulation model (verilog)
Listing 203 simlib.v
2681module \$fsm (CLK, ARST, CTRL_IN, CTRL_OUT);
2682
2683    parameter NAME = "";
2684
2685    parameter CLK_POLARITY = 1'b1;
2686    parameter ARST_POLARITY = 1'b1;
2687
2688    parameter CTRL_IN_WIDTH = 1;
2689    parameter CTRL_OUT_WIDTH = 1;
2690
2691    parameter STATE_BITS = 1;
2692    parameter STATE_NUM = 1;
2693    parameter STATE_NUM_LOG2 = 1;
2694    parameter STATE_RST = 0;
2695    parameter STATE_TABLE = 1'b0;
2696
2697    parameter TRANS_NUM = 1;
2698    parameter TRANS_TABLE = 4'b0x0x;
2699
2700    input CLK, ARST;
2701    input [CTRL_IN_WIDTH-1:0] CTRL_IN;
2702    output reg [CTRL_OUT_WIDTH-1:0] CTRL_OUT;
2703
2704    wire pos_clk = CLK == CLK_POLARITY;
2705    wire pos_arst = ARST == ARST_POLARITY;
2706
2707    reg [STATE_BITS-1:0] state;
2708    reg [STATE_BITS-1:0] state_tmp;
2709    reg [STATE_BITS-1:0] next_state;
2710
2711    reg [STATE_BITS-1:0] tr_state_in;
2712    reg [STATE_BITS-1:0] tr_state_out;
2713    reg [CTRL_IN_WIDTH-1:0] tr_ctrl_in;
2714    reg [CTRL_OUT_WIDTH-1:0] tr_ctrl_out;
2715
2716    integer i;
2717
2718    task tr_fetch;
2719        input [31:0] tr_num;
2720        reg [31:0] tr_pos;
2721        reg [STATE_NUM_LOG2-1:0] state_num;
2722        begin
2723            tr_pos = (2*STATE_NUM_LOG2+CTRL_IN_WIDTH+CTRL_OUT_WIDTH)*tr_num;
2724            tr_ctrl_out = TRANS_TABLE >> tr_pos;
2725            tr_pos = tr_pos + CTRL_OUT_WIDTH;
2726            state_num = TRANS_TABLE >> tr_pos;
2727            tr_state_out = STATE_TABLE >> (STATE_BITS*state_num);
2728            tr_pos = tr_pos + STATE_NUM_LOG2;
2729            tr_ctrl_in = TRANS_TABLE >> tr_pos;
2730            tr_pos = tr_pos + CTRL_IN_WIDTH;
2731            state_num = TRANS_TABLE >> tr_pos;
2732            tr_state_in = STATE_TABLE >> (STATE_BITS*state_num);
2733            tr_pos = tr_pos + STATE_NUM_LOG2;
2734        end
2735    endtask
2736
2737    always @(posedge pos_clk, posedge pos_arst) begin
2738        if (pos_arst) begin
2739            state_tmp = STATE_TABLE[STATE_BITS*(STATE_RST+1)-1:STATE_BITS*STATE_RST];
2740            for (i = 0; i < STATE_BITS; i = i+1)
2741                if (state_tmp[i] === 1'bz)
2742                    state_tmp[i] = 0;
2743            state <= state_tmp;
2744        end else begin
2745            state_tmp = next_state;
2746            for (i = 0; i < STATE_BITS; i = i+1)
2747                if (state_tmp[i] === 1'bz)
2748                    state_tmp[i] = 0;
2749            state <= state_tmp;
2750        end
2751    end
2752
2753    always @(state, CTRL_IN) begin
2754        next_state <= STATE_TABLE[STATE_BITS*(STATE_RST+1)-1:STATE_BITS*STATE_RST];
2755        CTRL_OUT <= 'bx;
2756        // $display("---");
2757        // $display("Q: %b %b", state, CTRL_IN);
2758        for (i = 0; i < TRANS_NUM; i = i+1) begin
2759            tr_fetch(i);
2760            // $display("T: %b %b -> %b %b [%d]", tr_state_in, tr_ctrl_in, tr_state_out, tr_ctrl_out, i);
2761            casez ({state, CTRL_IN})
2762                {tr_state_in, tr_ctrl_in}: begin
2763                    // $display("-> %b %b <-   MATCH", state, CTRL_IN);
2764                    {next_state, CTRL_OUT} <= {tr_state_out, tr_ctrl_out};
2765                end
2766            endcase
2767        end
2768    end
2769
2770endmodule