diff --git a/cpu/processor.v b/cpu/processor.v index e96f7f3..1805e6e 100644 --- a/cpu/processor.v +++ b/cpu/processor.v @@ -36,9 +36,8 @@ always @(negedge reset) begin state=`PROC_HALT_STATE; ProgCount=0;//TODO: Reset Vector HALT=0; - reg_read=1; - reg_write=1; - reg_read_read=1; + reg_write_we=1; + reg_read_oe=1; unaligned_access=0; ALU_OUT=1; @(posedge reset) @@ -50,16 +49,13 @@ end /*** ALU and EXEC stage logic ***/ //Architectural Register file -reg [2:0] reg_addr; -reg [15:0] reg_data; -reg reg_read; -reg reg_write; -reg [2:0] reg_read_addr; +reg [3:0] reg_write_addr; +reg [15:0] reg_write_data; +reg reg_write_we; +reg [3:0] reg_read_addr; reg [15:0] reg_read_data; -reg reg_read_read; -wire [15:0] reg_data_; -assign reg_data_=reg_data; -register_file register_file(reg_addr,reg_data_,reg_read,reg_write,reg_read_addr,reg_read_data,reg_read_read); +reg reg_read_oe; +register_file register_file(reg_write_addr,reg_write_data,reg_write_we,reg_read_addr,reg_read_data,reg_read_oe); //ALU mux4 #(.WIDTH(16)) MUX16_1A( @@ -109,7 +105,7 @@ always @(negedge clock) begin `PROC_EX_STATE_EXIT:begin case(out_sel) 2'b11:begin - reg_write=0; + reg_write_we=0; state=`PROC_IF_STATE_ENTRY; end default:begin @@ -133,8 +129,8 @@ always @(posedge clock) begin external_address_bus <= ProgCount; read <= 0; write <= 1; - reg_read_read=1; - reg_write=1; + reg_read_oe=1; + reg_write_we=1; ALU_OUT=1; state=`PROC_IF_WRITE_CIR; end @@ -142,21 +138,28 @@ always @(posedge clock) begin external_address_bus <= ProgCount; state=`PROC_IF_STATE_EXTRA_FETCH; end + /* AFTER THE IF STAGE WE HAVE THE FRIST BYTE OF THE + * INSTRUCTION ADN THE ONE FOLLOWING, ALLIGNED CORRECTLY TO + * CIR */ `PROC_DE_STATE_ENTRY:begin case(CIR[15:10]) 6'b000001 : begin /* ADD, ... */ if ( CIR[9:9] == 0 )begin - /* Add Immediate to accumulator */ + /* Add Immediate word/byte to accumulator */ unaligned_access=~unaligned_access; in1_sel=2'b00; in2_sel=2'b01; out_sel=2'b11; - reg_read_addr=3'b000; - reg_addr=3'b000; - reg_read_read=0; + reg_read_addr={CIR[8:8],3'b000}; + reg_write_addr={CIR[8:8],3'b000}; + reg_read_oe=0; ALU_OUT=0; - state=`PROC_DE_LOAD_16_PARAM; + if(CIR[8:8]==1) + state=`PROC_DE_LOAD_16_PARAM; + else begin + `invalid_instruction /*do 8bit loads*/ + end end else begin `invalid_instruction end @@ -165,7 +168,7 @@ always @(posedge clock) begin /* ADD, ADC, SUB, SBB, CMP , AND, ... */ case (CIR[5:3]) 3'b000 : begin - /* Add Immediate to register/memory */ + /* Add Immediate word/byte to register/memory */ if(unaligned_access==0)begin ProgCount=ProgCount+1; external_address_bus <= ProgCount; @@ -173,11 +176,16 @@ always @(posedge clock) begin in1_sel=2'b00; in2_sel=2'b01; out_sel=CIR[7:6]; - reg_read_addr=CIR[2:0]; - reg_addr=CIR[2:0]; - reg_read_read=0; + reg_read_addr={CIR[8:8],CIR[2:0]}; + reg_write_addr={CIR[8:8],CIR[2:0]}; + reg_read_oe=0; ALU_OUT=0; state=`PROC_DE_LOAD_16_PARAM; + if(CIR[8:8]==1) + state=`PROC_DE_LOAD_16_PARAM; + else begin + `invalid_instruction /*do 8bit loads*/ + end end default:begin `invalid_instruction @@ -185,15 +193,30 @@ always @(posedge clock) begin endcase end 6'b101100, - 6'b101101, - 6'b101110, - 6'b101111 : begin - /*Move Immediate to register*/ + 6'b101101:begin + /*Move Immediate byte to register*/ + if(unaligned_access==0)begin + ProgCount=ProgCount+1; + external_address_bus <= ProgCount; + end unaligned_access=~unaligned_access; in1_sel=2'b00; in2_sel=2'b00; out_sel=2'b11; - reg_addr=CIR[10:8]; + reg_write_addr={1'b0,CIR[10:8]}; + PARAM1[7:0]=CIR[7:0]; + PARAM2=0; + ALU_OUT=0; + state=`PROC_EX_STATE_ENTRY; + end + 6'b101110, + 6'b101111 : begin + /*Move Immediate word to register*/ + unaligned_access=~unaligned_access; + in1_sel=2'b00; + in2_sel=2'b00; + out_sel=2'b11; + reg_write_addr={1'b1,CIR[10:8]}; ALU_OUT=0; PARAM2=0; state=`PROC_DE_LOAD_16_PARAM; @@ -212,9 +235,9 @@ always @(posedge clock) begin in2_sel=2'b01; out_sel=CIR[7:6]; PARAM1=1; - reg_read_addr=CIR[2:0]; - reg_addr=CIR[2:0]; - reg_read_read=0; + reg_read_addr={1'b0,CIR[2:0]}; + reg_write_addr={1'b0,CIR[2:0]}; + reg_read_oe=0; ALU_OUT=0; state=`PROC_EX_STATE_ENTRY; end @@ -263,7 +286,7 @@ always @(posedge clock) begin state=`PROC_EX_STATE_ENTRY; end `PROC_EX_STATE_ENTRY:begin - reg_data=ADDER16_1O; + reg_write_data=ADDER16_1O; state=`PROC_EX_STATE_EXIT; ERROR=0; end diff --git a/cpu/registers.v b/cpu/registers.v index 53f6af3..a382f21 100644 --- a/cpu/registers.v +++ b/cpu/registers.v @@ -1,10 +1,62 @@ -module register_file ( input [2:0]addr1, inout [15:0]data1, input wire read1, input wire write1 ,input [2:0]addr2,output [15:0]data2,input wire read2); + +/* Register address fromat: +* [W-bit] [ 3-bit address] */ +module register_file (write_port1_addr,write_port1_data,write_port1_we,read_port1_addr,read_port1_data,read_port1_oe); +input [3:0] write_port1_addr,read_port1_addr; +input [15:0] write_port1_data; +output [15:0] read_port1_data; +input read_port1_oe; +input write_port1_we; + reg [15:0] registers [7:0]; -assign data2 = !read2 ? registers[addr2] : 'hz; -assign data1 = !read1 ? registers[addr1] : 'hz; -always @(negedge write1) begin - registers[addr1] = data1; - //$display("registers: 0:%04x 1:%04x 2:%04x",registers[0],registers[1],registers[2]); - $display("register %d update to %04x (data bus %04x)",addr1,registers[addr1],data1); + +assign read_port1_data = !read_port1_oe ? + ( read_port1_addr[3:3] ? registers[read_port1_addr[2:0]] : + ( read_port1_addr[2:2] ? {8'b0,registers[read_port1_addr[2:0]][15:8]} : {8'b0,registers[read_port1_addr[2:0]][7:0]} ) ) : 'hz; + +`define DEBUG_REG_WRITES + +`ifdef DEBUG_REG_WRITES + string debug_name; + logic[15:0] debug_value; +`endif + +always @(negedge write_port1_we) begin + if(write_port1_addr[3:3]==1)begin + /* Word : AX,CX,DX,BX,SP,BP,SI,DI */ + registers[write_port1_addr[2:0]]=write_port1_data; + end else begin + /* Byte : AL,CL,DL,BL,AX,CX,DX,BX */ + if(write_port1_addr[2:2]==1)begin + /* Byte */ + registers[write_port1_addr[2:0]][15:8]=write_port1_data[7:0]; + end else begin + /* Byte */ + registers[write_port1_addr[2:0]][7:0]=write_port1_data[7:0]; + end + end + + `ifdef DEBUG_REG_WRITES + if(write_port1_addr[3:2]==2'b11)begin + case(write_port1_addr[1:0]) + 2'b00: debug_name="sp"; + 2'b01: debug_name="bp"; + 2'b10: debug_name="si"; + 2'b11: debug_name="di"; + endcase + debug_value=registers[write_port1_addr[2:0]]; + end else begin + case(write_port1_addr[1:0]) + 2'b00: debug_name="ax"; + 2'b01: debug_name="cx"; + 2'b10: debug_name="dx"; + 2'b11: debug_name="bx"; + endcase + debug_value=registers[write_port1_addr[2:0]]; + end + + + $display("register %%%s update to $0x%04x",debug_name,debug_value); + `endif end endmodule