Finite state machines¶
- yosys> help $fsm¶
- Simulation model (verilog)¶
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