aboutsummaryrefslogtreecommitdiff
path: root/cpu.sv
diff options
context:
space:
mode:
authorkryptoish <krish_thakur7@icloud.com>2024-12-03 16:58:07 -0800
committerkryptoish <krish_thakur7@icloud.com>2024-12-03 16:58:07 -0800
commitf665f0ff80397ab10dbbea6cfcb302bb131f9719 (patch)
tree131ba7ab978dd127992111d354e8460c61fbc626 /cpu.sv
added files
Diffstat (limited to '')
-rw-r--r--cpu.sv150
1 files changed, 150 insertions, 0 deletions
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