From a5571fda122c9552c6b48e6bff6f2bee0db26c5d Mon Sep 17 00:00:00 2001 From: "(Tim) Efthimis Kritikos" Date: Thu, 9 Feb 2023 20:16:50 +0000 Subject: [PATCH] Added a very basic execution stage, registers and a very crude adder for ALU. It finally executes instructions! --- cpu/alu.v | 9 ++++ cpu/gtkwave_savefile.gtkw | 44 ++++++++++++++----- cpu/proc_state_def.v | 1 + cpu/processor.v | 89 +++++++++++++++++++++++++++++++-------- cpu/registers.v | 21 +++++++++ cpu/testbench.v | 1 + 6 files changed, 137 insertions(+), 28 deletions(-) create mode 100644 cpu/alu.v create mode 100644 cpu/registers.v diff --git a/cpu/alu.v b/cpu/alu.v new file mode 100644 index 0000000..9d8043c --- /dev/null +++ b/cpu/alu.v @@ -0,0 +1,9 @@ +module ADDER16(input [15:0]A,input [15:0]B, input oe,output [15:0]OUT, output carry); +wire c; +wire [15:0]sum; +assign {c,sum} = A+B; + +assign OUT = !oe ? sum : 16'hz; +assign carry = !oe ? c : 'hz; + +endmodule diff --git a/cpu/gtkwave_savefile.gtkw b/cpu/gtkwave_savefile.gtkw index 00d6bbe..bcc765e 100644 --- a/cpu/gtkwave_savefile.gtkw +++ b/cpu/gtkwave_savefile.gtkw @@ -1,34 +1,56 @@ [*] [*] GTKWave Analyzer v3.3.104 (w)1999-2020 BSI -[*] Thu Feb 9 14:44:08 2023 +[*] Thu Feb 9 20:13:04 2023 [*] [dumpfile] "/home/user/UNI_DATA/COMS30046_2022_TB-2/projects/9086/cpu/test.lx2" -[dumpfile_mtime] "Thu Feb 9 14:43:59 2023" -[dumpfile_size] 757 +[dumpfile_mtime] "Thu Feb 9 20:10:34 2023" +[dumpfile_size] 1043 [savefile] "/home/user/UNI_DATA/COMS30046_2022_TB-2/projects/9086/cpu/gtkwave_savefile.gtkw" [timestart] 0 -[size] 1630 1059 +[size] 1438 1059 [pos] -1 -1 -*-22.795050 2010000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +*-22.795050 6163000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 [treeopen] tb. +[treeopen] tb.p. +[treeopen] tb.p.exec_units. [sst_width] 221 [signals_width] 293 [sst_expanded] 1 [sst_vpaned_height] 313 -@29 -tb.p.clock[0] @28 +tb.p.clock[0] tb.p.reset[0] -@22 tb.p.state[3:0] +@22 tb.p.external_address_bus[19:0] tb.p.external_data_bus[15:0] tb.p.CIR[15:0] @28 tb.p.EXCEPTION[0] -tb.p.ADD_INST[0] -tb.p.INC_INST[0] +@c00022 +tb.p.exec_units.ADDER16_1.A[15:0] +@28 +(0)tb.p.exec_units.ADDER16_1.A[15:0] +(1)tb.p.exec_units.ADDER16_1.A[15:0] +(2)tb.p.exec_units.ADDER16_1.A[15:0] +(3)tb.p.exec_units.ADDER16_1.A[15:0] +(4)tb.p.exec_units.ADDER16_1.A[15:0] +(5)tb.p.exec_units.ADDER16_1.A[15:0] +(6)tb.p.exec_units.ADDER16_1.A[15:0] +(7)tb.p.exec_units.ADDER16_1.A[15:0] +(8)tb.p.exec_units.ADDER16_1.A[15:0] +(9)tb.p.exec_units.ADDER16_1.A[15:0] +(10)tb.p.exec_units.ADDER16_1.A[15:0] +(11)tb.p.exec_units.ADDER16_1.A[15:0] +(12)tb.p.exec_units.ADDER16_1.A[15:0] +(13)tb.p.exec_units.ADDER16_1.A[15:0] +(14)tb.p.exec_units.ADDER16_1.A[15:0] +(15)tb.p.exec_units.ADDER16_1.A[15:0] +@1401200 +-group_end @22 -tb.p.PARAM1[15:0] +tb.p.exec_units.ADDER16_1.B[15:0] +@29 +tb.p.exec_units.register_file.write1[0] [pattern_trace] 1 [pattern_trace] 0 diff --git a/cpu/proc_state_def.v b/cpu/proc_state_def.v index ae01d09..2b56942 100644 --- a/cpu/proc_state_def.v +++ b/cpu/proc_state_def.v @@ -10,3 +10,4 @@ /*EXECUTE STATE*/ `define PROC_EX_STATE_ENTRY 4'b1000 +`define PROC_EX_STATE_EXIT 4'b1001 diff --git a/cpu/processor.v b/cpu/processor.v index e04f6fb..fe369bb 100644 --- a/cpu/processor.v +++ b/cpu/processor.v @@ -1,6 +1,38 @@ `include "proc_state_def.v" +module exec_units ( input [15:0]PARAM1, input [15:0]PARAM2, input [1:0]in1_sel, input [1:0]in2_sel, input [1:0]out_sel , input EXEC); +/*Architectural Register file*/ +wire [2:0] reg_addr; +wire [15:0] reg_data; +wire reg_read; +wire reg_write; +wire [2:0] reg_read_addr; +wire [15:0] reg_read_data; +wire reg_read_read; +register_file register_file(reg_addr,reg_data,reg_read,reg_write,reg_read_addr,reg_read_data,reg_read_read); + +/*Exec Unts*/ +wire [15:0] ADDER16_1A; +wire [15:0] ADDER16_1B; +wire [15:0] ADDER16_1O; +wire ADDER16_1C; +ADDER16 ADDER16_1(ADDER16_1A,ADDER16_1B,EXEC,ADDER16_1O,ADDER16_1C); + +/*logic*/ +assign reg_addr=PARAM2[5:3]; +assign reg_read=EXEC; +assign reg_write=EXEC; +assign reg_read_read=0; +assign reg_read_addr=PARAM2[2:0]; +assign ADDER16_1A= (in1_sel==2'b00) ? PARAM1 : 16'b1010101010101010; +assign ADDER16_1B= (in2_sel==2'b01) ? reg_read_data : 16'b1010101010101010; +//assign reg_data = (out_sel==2'b01) ? ADDER16_1O : 'hz; +//assign reg_data = (out_sel==2'b01) ? ADDER16_1O : ADDER16_1O; +assign reg_data = ADDER16_1O; +endmodule + module processor ( input clock, input reset , output reg [19:0] external_address_bus, inout [15:0] external_data_bus,output reg read, output reg write, output reg HALT); + /* State */ reg [3:0] state; reg instruction_finished; @@ -11,24 +43,30 @@ reg [15:0] CIR; reg [15:0] PARAM1; reg [15:0] PARAM2; +/* Execution units*/ +reg [1:0] in1_sel; +reg [1:0] in2_sel; +reg [1:0] out_sel; +reg exec_unit_execute; +exec_units exec_units(PARAM1,PARAM2,in1_sel,in2_sel,out_sel,exec_unit_execute); + /* RESET LOGIC */ always @(negedge reset) begin if (reset==0) begin @(posedge clock); ProgCount=0;//TODO: Reset Vector - ADD_INST=0; EXCEPTION=0; - INC_INST=0; HALT=0; + exec_unit_execute=1; @(negedge clock); @(posedge clock); state=`PROC_IF_STATE_ENTRY; end end -/* Processor stages */ -reg ADD_INST,EXCEPTION,INC_INST; +reg EXCEPTION; +/* Processor stages */ always @(negedge clock) begin case(state) `PROC_IF_WRITE_CIR:begin @@ -36,14 +74,21 @@ always @(negedge clock) begin ProgCount=ProgCount+1; state=`PROC_DE_STATE_ENTRY; end + `PROC_EX_STATE_EXIT:begin + exec_unit_execute=1; + state=`PROC_IF_STATE_ENTRY; + end endcase end +`define invalid_instruction state=`PROC_IF_STATE_ENTRY;EXCEPTION=1; + always @(posedge clock) begin case(state) `PROC_HALT_STATE: HALT=1; `PROC_IF_STATE_ENTRY:begin + EXCEPTION=0; external_address_bus <= ProgCount; read <= 0; write <= 1; @@ -53,37 +98,46 @@ always @(posedge clock) begin external_address_bus <= ProgCount; /*Remenance from IF*/ case(CIR[15:10]) 6'b100000 : begin + /* ADD, ADC, SUB, SBB, CMP , AND, ... */ case (CIR[5:3]) - 3'b000 :begin - ADD_INST=1; + 3'b000 : begin + /* Add Immediate to register/memory */ + in1_sel=2'b00; + in2_sel=2'b01; + out_sel=2'b01; + PARAM2[2:0]=CIR[2:0]; + PARAM2[5:3]=CIR[2:0]; state=`PROC_DE_LOAD_16_PARAM; end default:begin - EXCEPTION=1; - state=`PROC_EX_STATE_ENTRY; + `invalid_instruction end endcase end 6'b111111 : begin + /* INC */ if (CIR[9:9] == 1 ) begin case (CIR[5:3]) 3'b000 :begin - INC_INST=1; + /* Increment Register or Memmory */ + in1_sel=2'b00; + in2_sel=2'b01; + out_sel=2'b01; + PARAM1=1; + PARAM2[2:0]=CIR[2:0]; + PARAM2[5:3]=CIR[2:0]; state=`PROC_EX_STATE_ENTRY; end default:begin - EXCEPTION=1; - state=`PROC_EX_STATE_ENTRY; + `invalid_instruction end endcase end else begin - EXCEPTION=1; - state=`PROC_EX_STATE_ENTRY; + `invalid_instruction end end default:begin - EXCEPTION=1; - state=`PROC_EX_STATE_ENTRY; + `invalid_instruction end endcase end @@ -93,8 +147,9 @@ always @(posedge clock) begin state=`PROC_EX_STATE_ENTRY; end `PROC_EX_STATE_ENTRY:begin - EXCEPTION=0;ADD_INST=0;INC_INST=0; - state=`PROC_IF_STATE_ENTRY; + EXCEPTION=0; + exec_unit_execute=0; + state=`PROC_EX_STATE_EXIT; end endcase end diff --git a/cpu/registers.v b/cpu/registers.v new file mode 100644 index 0000000..f4f8cc3 --- /dev/null +++ b/cpu/registers.v @@ -0,0 +1,21 @@ +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); +reg [15:0] registers [7:0]; +assign data2 = !read2 ? registers[0] : 'b1111000011110000 ; +//assign data2 = !read2 ? registers[addr2]: 'b1111000011110000; +assign data1 = !read1 ? registers[addr1]: 'hz; +initial begin + registers['b000]=0; + registers['b001]=0; + registers['b010]=0; + registers['b011]=0; + registers['b100]=0; + registers['b101]=0; + registers['b110]=0; + registers['b111]=0; // TODO Don't clear. Remove after we implement the MOV instruction +end +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); +end +endmodule diff --git a/cpu/testbench.v b/cpu/testbench.v index 30df6ef..7a8d9fc 100644 --- a/cpu/testbench.v +++ b/cpu/testbench.v @@ -27,6 +27,7 @@ initial begin #(`CPU_SPEED) reset = 1; #(`CPU_SPEED*30) + //$writememh("register_dump.txt", registers); #50 $finish; end