Finite state machines

yosys> help $fsm
Simulation model (verilog)
Listing 217 simlib.v
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