diff options
Diffstat (limited to 'src/statemachine.sv')
| -rw-r--r-- | src/statemachine.sv | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/src/statemachine.sv b/src/statemachine.sv new file mode 100644 index 0000000..1a5beb1 --- /dev/null +++ b/src/statemachine.sv @@ -0,0 +1,246 @@ +`define STATE_RESET 3'b000 +`define STATE_HALT 3'b001 +`define STATE_IF 3'b010 +`define STATE_DECODE 3'b011 +`define STATE_EXEC 3'b100 +`define STATE_MEM 3'b101 +`define STATE_WRITEBACK 3'b110 + +module statemachine(clk, reset, opcode, op, pc_reset, pc_load, pc_sel, ir_load, + addr_sel, mem_cmd, reg_w_sel, reg_a_sel, reg_b_sel, write, + loada, loadb, loadc, loads, loadm, asel, bsel, csel, vsel, + halt); + input clk, reset; + input [1:0] op; + input [2:0] opcode; + output reg pc_reset, pc_load, ir_load, addr_sel, write, loada, loadb, + loadc, loads, loadm, asel, bsel, csel, halt; + output reg [1:0] pc_sel, mem_cmd; + output reg [2:0] reg_w_sel, reg_a_sel, reg_b_sel; + output reg [3:0] vsel; + + reg [3:0] state; + + always_comb begin + {pc_reset, pc_load, pc_sel, ir_load, addr_sel, mem_cmd, + reg_w_sel, reg_a_sel, reg_b_sel, write, loada, loadb, + loadc, loads, loadm, asel, bsel, csel, vsel, halt} + = 31'b0; + + casex ({state, opcode, op}) + /* Reset state. */ + {`STATE_RESET, 5'bxxx_xx}: + {pc_reset, pc_load, addr_sel, mem_cmd} + = 5'b111_10; + + /* Instruction fetch. */ + {`STATE_IF, 5'bxxx_xx}: + {pc_load, ir_load, addr_sel, mem_cmd} = 5'b111_10; + + /* MOV immediate to register. */ + {`STATE_DECODE, 5'b110_10}: + {addr_sel, mem_cmd, reg_w_sel, write, vsel} + = 11'b1_10_100_1_0100; + + /* MOV register to register. */ + {`STATE_DECODE, 5'b110_00}: + {reg_b_sel, loadb} = 4'b001_1; + {`STATE_EXEC, 5'b110_00}: + {loadc, asel} = 2'b11; + {`STATE_WRITEBACK, 5'b110_00}: + {addr_sel, mem_cmd, reg_w_sel, write, vsel} + = 11'b1_10_010_1_0001; + + /* General ALU operations. */ + {`STATE_DECODE, 5'b101_xx}: + {reg_a_sel, reg_b_sel, loada, loadb} = 8'b100_001_11; + + /* ADD. */ + {`STATE_EXEC, 5'b101_00}: + loadc = 1'b1; + {`STATE_WRITEBACK, 5'b101_00}: + {addr_sel, mem_cmd, reg_w_sel, write, vsel} + = 11'b1_10_010_1_0001; + + /* CMP. */ + {`STATE_EXEC, 5'b101_01}: + {addr_sel, mem_cmd, loads} = 4'b1_10_1; + + /* AND. */ + {`STATE_EXEC, 5'b101_10}: + loadc = 1'b1; + {`STATE_WRITEBACK, 5'b101_10}: + {addr_sel, mem_cmd, reg_w_sel, write, vsel} + = 11'b1_10_010_1_0001; + + /* MVN. */ + {`STATE_EXEC, 5'b101_11}: + loadc = 1'b1; + {`STATE_WRITEBACK, 5'b101_11}: + {addr_sel, mem_cmd, reg_w_sel, write, vsel} + = 11'b1_10_010_1_0001; + + /* LDR. */ + {`STATE_DECODE, 5'b011_xx}: + {reg_a_sel, loada} = 4'b100_1; + {`STATE_EXEC, 5'b011_xx}: + {loadm, bsel} = 2'b11; + {`STATE_MEM, 5'b011_xx}: + mem_cmd = 2'b10; + {`STATE_WRITEBACK, 5'b011_xx}: + {addr_sel, mem_cmd, reg_w_sel, write, vsel} + = 11'b1_10_010_1_0010; + + /* STR. */ + {`STATE_DECODE, 5'b100_xx}: + {reg_a_sel, reg_b_sel, csel, loada, loadc} + = 9'b100_010_111; + {`STATE_EXEC, 5'b100_xx}: + {loadm, bsel} = 2'b11; + {`STATE_MEM, 5'b100_xx}: + mem_cmd = 2'b01; + {`STATE_WRITEBACK, 5'b100_xx}: + {addr_sel, mem_cmd} = 3'b1_10; + + /* B, BEQ, BNE, BLT, BLE. */ + {`STATE_DECODE, 5'b001_xx}: + {pc_load, pc_sel} = 3'b1_01; + {`STATE_EXEC, 5'b001_xx}: + {addr_sel, mem_cmd} = 3'b1_10; + + /* BL. */ + {`STATE_DECODE, 5'b010_11}: + {pc_load, pc_sel, reg_w_sel, write, vsel} + = 11'b1_11_100_1_1000; + {`STATE_EXEC, 5'b010_11}: + {addr_sel, mem_cmd} = 3'b1_10; + + /* BX, BLX. */ + {`STATE_DECODE, 5'b010_xx}: + {reg_b_sel, loadc, csel} = 5'b010_11; + + /* BX. */ + {`STATE_EXEC, 5'b010_00}: + {pc_load, pc_sel} = 3'b1_10; + {`STATE_WRITEBACK, 5'b010_00}: + {addr_sel, mem_cmd} = 3'b1_10; + + /* BLX. */ + {`STATE_EXEC, 5'b010_10}: + {pc_load, pc_sel, reg_w_sel, write, vsel} + = 11'b1_10_100_1_1000; + {`STATE_WRITEBACK, 5'b010_10}: + {addr_sel, mem_cmd} + = 3'b1_10; + + {`STATE_HALT, 5'bxxx_xx}: + halt = 1'b1; + + default: begin end + endcase + end + + always_ff @(posedge clk) casex ({reset, state, opcode, op}) + /* Reset. */ + 10'b1_xxxx_xxx_xx: + state <= `STATE_RESET; + {1'b0, `STATE_RESET, 5'bxxx_xx}: + state <= `STATE_IF; + + /* Beginning of instruction cycle. */ + {1'b0, `STATE_IF, 5'bxxx_xx}: + state <= `STATE_DECODE; + + /* HALT. */ + {1'b0, `STATE_DECODE, 5'b111_xx}: + state <= `STATE_HALT; + {1'b0, `STATE_HALT, 5'bxxx_xx}: + state <= `STATE_HALT; + + /* MOV immediate to register. */ + {1'b0, `STATE_DECODE, 5'b110_10}: + state <= `STATE_IF; + + /* MOV register to register. */ + {1'b0, `STATE_DECODE, 5'b110_00}: + state <= `STATE_EXEC; + {1'b0, `STATE_EXEC, 5'b110_00}: + state <= `STATE_WRITEBACK; + {1'b0, `STATE_WRITEBACK, 5'b110_00}: + state <= `STATE_IF; + + /* ADD. */ + {1'b0, `STATE_DECODE, 5'b101_00}: + state <= `STATE_EXEC; + {1'b0, `STATE_EXEC, 5'b101_00}: + state <= `STATE_WRITEBACK; + {1'b0, `STATE_WRITEBACK, 5'b101_00}: + state <= `STATE_IF; + + /* CMP. */ + {1'b0, `STATE_DECODE, 5'b101_01}: + state <= `STATE_EXEC; + {1'b0, `STATE_EXEC, 5'b101_01}: + state <= `STATE_IF; + + /* AND. */ + {1'b0, `STATE_DECODE, 5'b101_10}: + state <= `STATE_EXEC; + {1'b0, `STATE_EXEC, 5'b101_10}: + state <= `STATE_WRITEBACK; + {1'b0, `STATE_WRITEBACK, 5'b101_10}: + state <= `STATE_IF; + + /* MVN. */ + {1'b0, `STATE_DECODE, 5'b101_11}: + state <= `STATE_EXEC; + {1'b0, `STATE_EXEC, 5'b101_11}: + state <= `STATE_WRITEBACK; + {1'b0, `STATE_WRITEBACK, 5'b101_11}: + state <= `STATE_IF; + + /* LDR. */ + {1'b0, `STATE_DECODE, 5'b011_xx}: + state <= `STATE_EXEC; + {1'b0, `STATE_EXEC, 5'b011_xx}: + state <= `STATE_MEM; + {1'b0, `STATE_MEM, 5'b011_xx}: + state <= `STATE_WRITEBACK; + {1'b0, `STATE_WRITEBACK, 5'b011_xx}: + state <= `STATE_IF; + + /* STR. */ + {1'b0, `STATE_DECODE, 5'b100_xx}: + state <= `STATE_EXEC; + {1'b0, `STATE_EXEC, 5'b100_xx}: + state <= `STATE_MEM; + {1'b0, `STATE_MEM, 5'b100_xx}: + state <= `STATE_WRITEBACK; + {1'b0, `STATE_WRITEBACK, 5'b100_xx}: + state <= `STATE_IF; + + /* B, BEQ, BNE, BLT, BLE. */ + {1'b0, `STATE_DECODE, 5'b001_xx}: + state <= `STATE_EXEC; + {1'b0, `STATE_EXEC, 5'b001_xx}: + state <= `STATE_IF; + + /* BL. */ + {1'b0, `STATE_DECODE, 5'b010_11}: + state <= `STATE_EXEC; + {1'b0, `STATE_EXEC, 5'b010_11}: + state <= `STATE_IF; + + /* BX, BLX. */ + {1'b0, `STATE_DECODE, 5'b010_xx}: + state <= `STATE_EXEC; + {1'b0, `STATE_EXEC, 5'b010_xx}: + state <= `STATE_WRITEBACK; + {1'b0, `STATE_WRITEBACK, 5'b010_xx}: + state <= `STATE_IF; + + /* Should not happen. Otherwise, an error occurred. */ + default: + state <= `STATE_RESET; + endcase +endmodule: statemachine |