Finite state machines

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