Finite state machines

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