URL
https://opencores.org/ocsvn/2d_game_console/2d_game_console/trunk
Subversion Repositories 2d_game_console
[/] [2d_game_console/] [trunk/] [Processor_ModelSim/] [Processor_Controller.v] - Rev 2
Compare with Previous | Blame | View Log
module Processor_Controller( ram_grant, instruction, clock, reset, isr_addr, int_req, v_sync, sleep, ram_q, add_overflow, add_result, sub_overflow, sub_result, mult_result, divide_quotient, divide_remain, compare_aeb, compare_agb, compare_alb, int_ack, rom_addr, opcode, reg_a_num, reg_b_num, reg_c_num, imm, rflags_index, const_bool, sprite_level, sprite_id, sprite_x, sprite_y, sprite_color, ram_addr, ram_data, ram_wren, ram_req, reg_c_val, reg_b_val, reg_a_val, current_state, next_state, program_counter, registers, rflags, v_sync_flag, stack_pointer, pc_stack, pc_stack_val, int_program_counter, int_rflags ); input [15:0] ram_q; input [15:0] isr_addr; input [31:0] instruction; input wire signed [15:0] add_result; input wire signed [15:0] sub_result; input wire signed [31:0] mult_result; input wire signed [15:0] divide_quotient; input wire signed [15:0] divide_remain; input ram_grant; input add_overflow; input sub_overflow; input compare_aeb; input compare_agb; input compare_alb; input int_req; input sleep; input v_sync; input clock; input reset; output v_sync_flag; output const_bool; output [2:0] rflags_index; output [4:0] reg_a_num; output [4:0] reg_b_num; output [4:0] reg_c_num; output [5:0] opcode; output [15:0] imm; output reg [15:0] reg_a_val; output reg [15:0] reg_b_val; output reg [15:0] reg_c_val; output reg [15:0] ram_addr; output reg [15:0] ram_data; output reg ram_wren; output reg ram_req; output reg int_ack; output reg [15:0] int_program_counter; output reg [7:0] int_rflags; output reg [15:0] rom_addr; output reg [15:0] program_counter; output reg [511:0] registers; output reg [7:0] rflags; output reg [2:0] stack_pointer; output reg [127:0] pc_stack; output reg [15:0] pc_stack_val; output reg [5:0] sprite_level; output reg [383:0] sprite_id; output reg [639:0] sprite_x; output reg [639:0] sprite_y; output reg [1023:0] sprite_color; assign opcode = instruction[31:26]; assign reg_a_num = instruction[25:21]; assign reg_b_num = instruction[20:16]; assign reg_c_num = instruction[15:11]; assign imm = instruction[15:0]; assign const_bool = instruction[17]; assign rflags_index = instruction[20:18]; // Number of Interrupt Service Routines parameter code_start_addr = 16'd4; // INSTRUCTIONS OPERATION CODE // Data Transfer Instructions parameter opcode_lw = 6'b001001; parameter opcode_sw = 6'b001010; parameter opcode_limm = 6'b001100; // Arithmetic Instructions parameter opcode_add = 6'b010001; parameter opcode_sub = 6'b010010; parameter opcode_mul = 6'b010100; parameter opcode_div = 6'b010101; // Logical Instructions parameter opcode_and = 6'b100001; parameter opcode_or = 6'b100010; parameter opcode_cmp = 6'b100100; parameter opcode_not = 6'b100101; // Control Transfer Instructions (Immediate) parameter opcode_jmp = 6'b101001; parameter opcode_brfl = 6'b101010; parameter opcode_call = 6'b101011; parameter opcode_ret = 6'b101100; parameter opcode_iret = 6'b101101; parameter opcode_nop = 6'b101110; // Control Transfer Instructions (Register) parameter opcode_jr = 6'b011001; parameter opcode_brflr = 6'b011010; parameter opcode_callr = 6'b011011; // Graphical instructions parameter opcode_sprite_id = 6'b110001; parameter opcode_sprite_color = 6'b110010; parameter opcode_sprite_pos = 6'b110100; parameter opcode_wait_vsync = 6'b110111; /*########################################################################*/ /*################# Video vertical sync edge-detection #################*/ /*########################################################################*/ reg v_sync_delay; always @ (posedge clock) begin v_sync_delay <= v_sync; end assign v_sync_flag = ~v_sync & v_sync_delay; /*########################################################################*/ /*########################################################################*/ /*########################################################################*/ /*######################## FINITE STATE MACHINE ########################*/ /*######################## PROCESSOR CONTROLLER ########################*/ /*########################################################################*/ output reg [5:0] current_state; output reg [5:0] next_state; // States parameter Reset = 6'b000000; // Reset = 0 parameter Wait_Program_Mem_1 = 6'b000001; // Wait_Program_Mem_1 = 1 parameter Decode_Instruction = 6'b000010; // Decode_Instruction = 2 parameter Wait_Operation = 6'b000011; // Wait_Operation = 3 parameter Wait_DIV_1 = 6'b000100; // Wait_DIV_1 = 4 parameter Wait_DIV_2 = 6'b000101; // Wait_DIV_2 = 5 parameter Wait_DIV_3 = 6'b000110; // Wait_DIV_3 = 6 parameter Wait_DIV_4 = 6'b000111; // Wait_DIV_4 = 7 parameter ADD = 6'b001000; // ADD = 8 parameter SUB = 6'b001001; // SUB = 9 parameter MUL = 6'b001010; // MUL = 10 parameter DIV = 6'b001011; // DIV = 11 parameter AND = 6'b001100; // AND = 12 parameter OR = 6'b001101; // OR = 13 parameter CMP = 6'b001110; // CMP = 14 parameter NOT = 6'b001111; // NOT = 15 parameter SPRITE_ID = 6'b010000; // SPRITE_ID = 16 parameter SPRITE_COLOR = 6'b010001; // SPRITE_COLOR = 17 parameter SPRITE_POS = 6'b010010; // SPRITE_POS = 18 parameter LIMM = 6'b010011; // LIMM = 19 parameter LW_Begin = 6'b010100; // LW_Begin = 20 parameter LW_Wait_1 = 6'b010101; // LW_Wait_1 = 21 parameter LW_Wait_2 = 6'b010110; // LW_Wait_2 = 22 parameter LW_End = 6'b010111; // LW_End = 23 parameter SW_Begin = 6'b011000; // SW_Begin = 24 parameter SW_End = 6'b011001; // SW_End = 25 parameter JMP = 6'b011010; // JMP = 26 parameter JR = 6'b011011; // JR = 27 parameter BRFL = 6'b011100; // BRFL = 28 parameter BRFLR = 6'b011101; // BRFL = 29 parameter NOP = 6'b011110; // NOP = 30 parameter CALL = 6'b011111; // CALL = 31 parameter CALLR = 6'b100000; // CALLR = 32 parameter RET = 6'b100001; // RET = 33 parameter WAIT_VSYNC = 6'b100010; // WAIT_VSYNC = 34 parameter Inc_Program_Counter = 6'b100011; // Inc_Program_Counter = 35 parameter Int_Req_Wait = 6'b100100; // Int_Req_Wait = 36 parameter Interrupt = 6'b100101; // Interrupt = 37 parameter IRET = 6'b100110; // IRET = 38 // Next State Decoder always @ (*) begin case (current_state) // State 0 Reset: begin next_state = Wait_Program_Mem_1; end // State 1 Wait_Program_Mem_1: begin if (sleep) next_state = Wait_Program_Mem_1; else if (int_req) next_state = Int_Req_Wait; else next_state = Decode_Instruction; end // State 2 Decode_Instruction: begin next_state = Wait_Operation; end // State 3 Wait_Operation: begin case (opcode) opcode_add: begin next_state = ADD; end opcode_sub: begin next_state = SUB; end opcode_mul: begin next_state = MUL; end opcode_div: begin next_state = Wait_DIV_1; end opcode_and: begin next_state = AND; end opcode_or: begin next_state = OR; end opcode_cmp: begin next_state = CMP; end opcode_not: begin next_state = NOT; end opcode_sprite_id: begin next_state = SPRITE_ID; end opcode_sprite_color: begin next_state = SPRITE_COLOR; end opcode_sprite_pos: begin next_state = SPRITE_POS; end opcode_limm: begin next_state = LIMM; end opcode_lw: begin next_state = LW_Begin; end opcode_sw: begin next_state = SW_Begin; end opcode_jmp: begin next_state = JMP; end opcode_jr: begin next_state = JR; end opcode_brfl: begin if (rflags[rflags_index] == const_bool) next_state = BRFL; else next_state = Inc_Program_Counter; end opcode_brflr: begin if (rflags[rflags_index] == const_bool) next_state = BRFLR; else next_state = Inc_Program_Counter; end opcode_nop: begin next_state = NOP; end opcode_call: begin next_state = CALL; end opcode_callr: begin next_state = CALLR; end opcode_ret: begin next_state = RET; end opcode_wait_vsync: begin next_state = WAIT_VSYNC; end opcode_iret: begin next_state = IRET; end default: begin next_state = Reset; end endcase end // State 4 Wait_DIV_1: begin next_state = Wait_DIV_2; end // State 5 Wait_DIV_2: begin next_state = Wait_DIV_3; end // State 6 Wait_DIV_3: begin next_state = Wait_DIV_4; end // State 7 Wait_DIV_4: begin next_state = DIV; end // State 8 ADD: begin next_state = Inc_Program_Counter; end // State 9 SUB: begin next_state = Inc_Program_Counter; end // State 10 MUL: begin next_state = Inc_Program_Counter; end // State 11 DIV: begin next_state = Inc_Program_Counter; end // State 12 AND: begin next_state = Inc_Program_Counter; end // State 13 OR: begin next_state = Inc_Program_Counter; end // State 14 CMP: begin next_state = Inc_Program_Counter; end // State 15 NOT: begin next_state = Inc_Program_Counter; end // State 16 SPRITE_ID: begin next_state = Inc_Program_Counter; end // State 17 SPRITE_COLOR: begin next_state = Inc_Program_Counter; end // State 18 SPRITE_POS: begin next_state = Inc_Program_Counter; end // State 19 LIMM: begin next_state = Inc_Program_Counter; end // State 20 LW_Begin: begin if (ram_grant) next_state = LW_Wait_1; else next_state = LW_Begin; end // State 21 LW_Wait_1: begin next_state = LW_Wait_2; end // State 22 LW_Wait_2: begin next_state = LW_End; end // State 23 LW_End: begin next_state = Inc_Program_Counter; end // State 24 SW_Begin: begin if (ram_grant) next_state = SW_End; else next_state = SW_Begin; end // State 25 SW_End: begin next_state = Inc_Program_Counter; end // State 26 JMP: begin next_state = Wait_Program_Mem_1; end // State 27 JR: begin next_state = Wait_Program_Mem_1; end // State 28 BRFL: begin next_state = Wait_Program_Mem_1; end // State 29 BRFLR: begin next_state = Wait_Program_Mem_1; end // State 30 NOP: begin next_state = Inc_Program_Counter; end // State 31 CALL: begin next_state = Wait_Program_Mem_1; end // State 32 CALLR: begin next_state = Wait_Program_Mem_1; end // State 33 RET: begin next_state = Wait_Program_Mem_1; end // State 34 WAIT_VSYNC: begin if (v_sync_flag) next_state = Inc_Program_Counter; else next_state = WAIT_VSYNC; end // State 35 Inc_Program_Counter: begin next_state = Wait_Program_Mem_1; end // State 36 Int_Req_Wait: begin if (!int_req) next_state = Interrupt; else next_state = Int_Req_Wait; end // State 37 Interrupt: begin next_state = Wait_Program_Mem_1; end // State 38 IRET: begin next_state = Wait_Program_Mem_1; end default: begin next_state = Reset; end endcase end // Output Decoder always @ (*) begin // Default Assignments pc_stack_val = pc_stack[16*stack_pointer +: 16]; reg_a_val = registers[16*reg_a_num +: 16]; reg_b_val = registers[16*reg_b_num +: 16]; reg_c_val = registers[16*reg_c_num +: 16]; sprite_level = registers[16*reg_a_num +: 6]; rom_addr = program_counter; ram_wren = 0; ram_req = 0; case (current_state) // State 0 Reset: begin end // State 1 Wait_Program_Mem_1: begin end // State 2 Decode_Instruction: begin end // State 3 Wait_Operation: begin end // State 4 Wait_DIV_1: begin end // State 5 Wait_DIV_2: begin end // State 6 Wait_DIV_3: begin end // State 7 Wait_DIV_4: begin end // State 8 ADD: begin end // State 9 SUB: begin end // State 10 MUL: begin end // State 11 DIV: begin end // State 12 AND: begin end // State 13 OR: begin end // State 14 CMP: begin end // State 15 NOT: begin end // State 16 SPRITE_ID: begin end // State 17 SPRITE_COLOR: begin end // State 18 SPRITE_POS: begin end // State 19 LIMM: begin end // State 20 LW_Begin: begin ram_req = 1; end // State 21 LW_Wait_1: begin ram_req = 1; end // State 22 LW_Wait_2: begin ram_req = 1; end // State 23 LW_End: begin ram_req = 1; end // State 24 SW_Begin: begin ram_wren = 1; ram_req = 1; end // State 25 SW_End: begin ram_wren = 1; ram_req = 1; end // State 26 JMP: begin end // State 27 JR: begin end // State 28 BRFL: begin end // State 29 BRFLR: begin end // State 30 NOP: begin end // State 31 CALL: begin end // State 32 CALLR: begin end // State 33 RET: begin end // State 34 WAIT_VSYNC: begin end // State 35 Inc_Program_Counter: begin end // State 36 Int_Req_Wait: begin end // State 37 Interrupt: begin end // State 38 IRET: begin end default: begin end endcase end // State Register and Reset Logic always @ (posedge clock) begin if (reset) begin current_state <= Reset; program_counter <= code_start_addr; stack_pointer <= 3'b000; rflags <= 8'b00000000; int_ack <= 0; end else begin current_state <= next_state; // State: ADD if (next_state == ADD) begin if (add_overflow) begin rflags[6] <= 1; //RFlags[overflow] = 1 registers[16*reg_a_num +: 16] <= 16'b1111111111111111; end else begin rflags[6] <= 0; //RFlags[overflow] = 0 registers[16*reg_a_num +: 16] <= add_result; end end // State: SUB if (next_state == SUB) begin if (sub_overflow) begin rflags[6] <= 1; //RFlags[overflow] = 1 registers[16*reg_a_num +: 16] <= 16'b1111111111111111; end else begin rflags[6] <= 0; //RFlags[overflow] = 0 registers[16*reg_a_num +: 16] <= sub_result; end end // State: MUL if (next_state == MUL) begin if ( (mult_result > 32'sd32767) || (mult_result < -32'sd32768) ) begin rflags[6] <= 1; //RFlags[overflow] = 1 registers[16*reg_a_num +: 16] <= 16'b1111111111111111; end else begin rflags[6] <= 0; //RFlags[overflow] = 0 registers[16*reg_a_num +: 16] <= mult_result[15:0]; end end // State: DIV if (next_state == DIV) begin if (reg_b_val == 16'd0) begin rflags[0] <= 1; //RFlags[error] = 1 rflags[6] <= 0; //RFlags[overflow] = 0 registers[16*reg_a_num +: 16] <= 16'b1111111111111111; end else begin rflags[0] <= 0; //RFlags[error] = 0 if ( (reg_a_val == 16'b1000000000000000) && (reg_b_val == 16'b1111111111111111) ) begin rflags[6] <= 1; //RFlags[overflow] = 1 registers[16*reg_a_num +: 16] <= 16'b1111111111111111; end else begin rflags[6] <= 0; //RFlags[overflow] = 0 registers[16*reg_a_num +: 16] <= divide_quotient; end end end // State: AND if (next_state == AND) registers[16*reg_a_num +: 16] <= reg_a_val & reg_b_val; // State: OR if (next_state == OR) registers[16*reg_a_num +: 16] <= reg_a_val | reg_b_val; // State: CMP if (next_state == CMP) begin rflags[3] <= compare_alb; //RFlags[below] rflags[4] <= compare_aeb; //RFlags[equal] rflags[5] <= compare_agb; //RFlags[above] end // State: NOT if (next_state == NOT) registers[16*reg_a_num +: 16] <= ~ reg_a_val; // State: SPRITE_ID if (next_state == SPRITE_ID) sprite_id[6*sprite_level +: 6] <= reg_b_val[5:0]; // State: SPRITE_COLOR if (next_state == SPRITE_COLOR) sprite_color[16*sprite_level +: 16] <= reg_b_val; // State: SPRITE_POS if (next_state == SPRITE_POS) begin sprite_x[10*sprite_level +: 10] <= reg_c_val[9:0]; sprite_y[10*sprite_level +: 10] <= reg_b_val[9:0]; end // State: LIMM if (next_state == LIMM) registers[16*reg_a_num +: 16] <= imm; // State: LW_Begin if (next_state == LW_Begin) begin ram_addr <= reg_b_val + imm; end // State: LW_End if (next_state == LW_End) registers[16*reg_a_num +: 16] <= ram_q; // State: SW_Begin if (next_state == SW_Begin) begin ram_addr <= reg_b_val + imm; ram_data <= reg_a_val; end // State: JMP if (next_state == JMP) program_counter <= imm; // State: JR if (next_state == JR) program_counter <= reg_a_val; // State: BRFL if (next_state == BRFL) begin program_counter <= imm; end // State: BRFLR if (next_state == BRFLR) begin program_counter <= reg_a_val; end // State: CALL if (next_state == CALL) begin pc_stack[16*stack_pointer +: 16] <= program_counter + 1'b1; program_counter <= imm; stack_pointer <= stack_pointer + 1'b1; end // State: CALLR if (next_state == CALLR) begin pc_stack[16*stack_pointer +: 16] <= program_counter + 1'b1; program_counter <= reg_a_val; stack_pointer <= stack_pointer + 1'b1; end // State: RET if (next_state == RET) begin program_counter <= pc_stack[16*(stack_pointer - 1) +: 16]; stack_pointer <= stack_pointer - 1'b1; end // State: Inc_Program_Counter if (next_state == Inc_Program_Counter) begin program_counter <= program_counter + 1'b1; end // State: Int_Req_Wait if (next_state == Int_Req_Wait) begin int_ack <= 1; end // State: Interrupt if (next_state == Interrupt) begin int_rflags <= rflags; int_program_counter <= program_counter; program_counter <= isr_addr; end // State: IRET if (next_state == IRET) begin int_ack <= 0; rflags <= int_rflags; program_counter <= int_program_counter; end end end /*########################################################################*/ /*########################################################################*/ endmodule