From f665f0ff80397ab10dbbea6cfcb302bb131f9719 Mon Sep 17 00:00:00 2001 From: kryptoish Date: Tue, 3 Dec 2024 16:58:07 -0800 Subject: added files --- cpu.sv | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 cpu.sv (limited to 'cpu.sv') diff --git a/cpu.sv b/cpu.sv new file mode 100644 index 0000000..36c0bf2 --- /dev/null +++ b/cpu.sv @@ -0,0 +1,150 @@ +`define RST 5'b00000 +`define GetA 5'b00001 +`define GetB 5'b00010 +`define operation 5'b00011 +`define WriteReg 5'b00100 +`define GetACMP 5'b00101 +`define GetBCMP 5'b00110 +`define GetBonly 5'b00111 +`define IF1 5'b01000 +`define IF2 5'b01001 +`define UpdatePC 5'b01010 +`define GetAddr 5'b01011 +`define LoadAddr 5'b01100 +`define StoreAddr 5'b01101 +`define Dout 5'b01110 +`define Dout2 5'b01111 +`define Dout3 5'b10000 +`define Dout4 5'b10001 + +`define MNONE 2'b00 +`define MREAD 2'b01 +`define MWRITE 2'b10 + +module cpu(clk,reset,read_data,write_data,mem_addr,mem_cmd,N,V,Z); + input clk, reset; + input [15:0] read_data; + output reg [15:0] write_data; + output reg [8:0] mem_addr; + output reg [1:0] mem_cmd; + output reg N, V, Z; + + reg [15:0] inst_reg = 16'bx; + reg [15:0] next_inst_reg, datapath_out; + reg [2:0] opcode, readnum, writenum, Z_out; + reg [1:0] op, nsel, shift, ALUop, vsel; + reg loada, loadb, loadc, loads, write, asel, bsel, + load_ir, load_pc, reset_pc, addr_sel, load_addr; + reg [15:0] sximm8; + reg [15:0] sximm5; + reg [4:0] present_state; + + reg [15:0] mdata; + reg [8:0] PC, next_pc = 9'b0; + reg [8:0] data_addr, next_data_addr; + + //three more internal wires + //later change some of these to wires to make less expensive + + datapath DP(clk, readnum, vsel, loada, loadb, shift, asel, bsel, ALUop, + loadc, loads, writenum, write, Z_out, datapath_out, sximm5, sximm8, mdata); + + //if nsel == 00 -> rm nsel == 01 -> rd, nsel == 10 -> rn + always_comb begin + + {opcode, op} = inst_reg[15:11]; //decodin like crazy here + if (opcode == 3'b100) shift = 2'b00; + else shift = inst_reg[4:3]; + sximm5 = {{11{inst_reg[4]}}, inst_reg[4:0]}; + sximm8 = {{8{inst_reg[7]}} , inst_reg[7:0]}; //fix this back + ALUop = op; + + case (nsel) + 2'b00: {readnum, writenum} = {2{inst_reg[2:0]}}; //Rm + 2'b01: {readnum, writenum} = {2{inst_reg[7:5]}}; //Rd + 2'b10: {readnum, writenum} = {2{inst_reg[10:8]}}; //Rn + default: {readnum, writenum} = {writenum, readnum}; + endcase + + {Z, V, N} = Z_out; //give out all values + write_data = datapath_out; + + mdata = read_data; + next_inst_reg = load_ir ? read_data : inst_reg; //load for instructions + + next_pc = reset_pc ? 9'b0 : (PC + 1'b1); + mem_addr = addr_sel ? PC : data_addr; + next_data_addr = load_addr ? datapath_out[8:0] : data_addr; + end + + // next: first, second and third bit: nsel, second bit loada, third bit loadB, fouth bit asel, + // fifth bit bsel, sixth and 7th bit shift, 8th and 9th bit aluop, 10th bit loadc, 11bit vsel, + // 12bit write + always_ff @(posedge clk) begin + inst_reg = next_inst_reg; + data_addr = next_data_addr; + if (load_pc) PC = next_pc; + + casex ({present_state, reset}) + //all roads lead to rome (`wait) + {4'bxxxx, 1'b1} : {present_state, write, load_pc, reset_pc, load_ir} = {`RST, 4'b0110}; + {`RST, 1'b0} : {present_state, write, addr_sel, load_pc, reset_pc, mem_cmd} = {`IF1, 4'b0100, `MREAD}; + {`IF1, 1'b0} : {present_state, load_ir} = {`IF2, 1'b1}; + {`IF2, 1'b0} : {present_state, addr_sel, load_pc, load_ir, mem_cmd} = {`UpdatePC, 3'b010, `MNONE}; + //make IF1 states+, last state before below is UpdatePC + + {`UpdatePC, 1'b0} : begin + casex ({opcode, op}) //op since ALUop == op + //move instructions + 5'b11010: {present_state, nsel, vsel, write, load_pc} = {`WriteReg, 6'b101010}; // 2 clk cycles + 5'b11000: {present_state, nsel, loada, loadb, load_pc} = {`GetBonly, 5'b00010}; // 3 clk cycles + //alu instructions + 5'b101x0: {present_state, nsel, loada, load_pc} = {`GetA, 4'b1010}; //ADD & AND ---> 4 clk cycles //loads A + 5'b10101: {present_state, nsel, loada, load_pc} = {`GetACMP, 4'b1010}; //CMP ---> 3 clk cycles //loads A + 5'b10111: {present_state, nsel, loada, loadb, load_pc} = {`GetBonly, 5'b00010}; //MVN ---> 3 clk cycles //loads to B + //memory instructions + 5'b01100: {present_state, nsel, loada, loadb, asel, bsel, load_pc, mem_cmd} = {`GetAddr, 7'b1010010, `MREAD}; //LDR + 5'b10000: {present_state, nsel, loada, loadb, asel, bsel, load_pc} = {`GetAddr, 7'b1010010}; //STR + //HALT instruction + 5'b111xx: {present_state, load_pc} = {`UpdatePC, 1'b0}; //will be stuck here until reset + endcase + end + + //ADD & AND branch + {`GetA, 1'b0} : {present_state, nsel, loadb, loada} = {`GetB, 4'b0010}; //loads B + {`GetB, 1'b0} : {present_state, asel, bsel, loadc, loads} = {`operation, 4'b0010}; //performs operations + + //for writing only from B to Rd + {`GetBonly, 1'b0} : {present_state, asel, bsel, loadc, loads} = {`operation, 4'b1010}; + + //Get the (shifted) memory address (LDR) + {`GetAddr, 1'b0} : begin + case (opcode) + 3'b011: {present_state, loada, loadb, loadc, load_addr, addr_sel, mem_cmd} = {`Dout, 5'b00110, `MREAD}; //might need an extra state for dout + 3'b100: {present_state, loada, loadb, loadc, load_addr, addr_sel} = {`StoreAddr, 5'b00110}; + endcase + end + {`Dout, 1'b0} : begin //wait for RAM + case (opcode) + 3'b011: present_state = `Dout2; + 3'b100: {present_state, loada, loadb, loadc, load_addr, mem_cmd} = {`Dout4, 4'b0010, `MWRITE}; + endcase + end + {`Dout2, 1'b0} : {present_state, load_addr} = {`LoadAddr, 1'b0}; + {`LoadAddr, 1'b0} : {present_state, nsel, vsel, write, loadc, load_addr, mem_cmd} = {`Dout3, 7'b0111100, `MREAD}; + {`Dout3, 1'b0} : {present_state, mem_cmd, write} = {`WriteReg, `MNONE, 1'b0}; + + {`StoreAddr, 1'b0} : {present_state, nsel, loada, loadb, asel, bsel, load_addr} = {`Dout, 7'b0101101}; + {`Dout4, 1'b0} : {present_state, write} = {`WriteReg, 1'b0}; + + //CMP branch + {`GetACMP, 1'b0} : {present_state, nsel, loadb, loada} = {`GetBCMP, 4'b0010}; //loads B + {`GetBCMP, 1'b0} : {present_state, asel, bsel, loadc, loads} = {`WriteReg, 4'b0001}; //performs operations and writes into status + + //write to Rd + {`operation, 1'b0} : {present_state, nsel, vsel, write} = {`WriteReg, 5'b01001}; //writing into the register + //waiter/reset + {`WriteReg, 1'b0} : {present_state, loada, loadb, loadc, loads, mem_cmd} = {`RST, 4'b0000, `MNONE}; //extra cycle for values to got through (should I go reset or IF1) + endcase + end + endmodule \ No newline at end of file -- cgit v1.2.3