aboutsummaryrefslogtreecommitdiff
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
added files
-rw-r--r--README.md14
-rw-r--r--alu.sv21
-rw-r--r--cpu.sv150
-rw-r--r--data.txt256
-rw-r--r--datapath.sv48
-rw-r--r--lab7bonus_autograder_check.sv71
-rw-r--r--lab7bonus_fig2.s28
-rw-r--r--lab7bonus_fig4.s29
-rw-r--r--lab7bonus_stage2_tb.sv35
-rw-r--r--lab7bonus_top.sv90
-rw-r--r--regfile.sv45
-rw-r--r--shifter.sv18
-rw-r--r--trigger.py31
13 files changed, 836 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6b6a671
--- /dev/null
+++ b/README.md
@@ -0,0 +1,14 @@
+[![Review Assignment Due Date](https://classroom.github.com/assets/deadline-readme-button-22041afd0340ce965d47ae6ef1cefeee28c7c493a6346c4f15d667ab976d596c.svg)](https://classroom.github.com/a/H84oO7Rx)
+[![Open in Visual Studio Code](https://classroom.github.com/assets/open-in-vscode-2e0aaae1b6195c2367325f4f02e2d04e9abb55f0b24a779b69b11b9e10269abc.svg)](https://classroom.github.com/online_ide?assignment_repo_id=17389376&assignment_repo_type=AssignmentRepo)
+# starter-lab-7-bonus
+
+Lab 7 bonus ONLY: Do NOT use this repository for Lab 7 or your TA will not get
+your code during your marking session.
+
+See the Lab 7 Bonus handout for detailed instructions for what you need to do
+for the bonus.
+
+IMPORTANT: Ensure your submission includes a Quartus project file and a
+Modelsim Project File and that both specify all (System)Verilog files required
+to synthesize your CPU or the autograder will not be able to compile your
+design and you will get zero marks for the bonus.
diff --git a/alu.sv b/alu.sv
new file mode 100644
index 0000000..4e17d8b
--- /dev/null
+++ b/alu.sv
@@ -0,0 +1,21 @@
+ module ALU(Ain,Bin,ALUop,out,Z);
+ input [15:0] Ain, Bin;
+ input [1:0] ALUop;
+ output reg [15:0] out;
+ output reg [2:0] Z; //Z[0] = zero flag, Z[1] = neg flag, Z[2] = overflow flag
+
+ always_comb begin
+ case(ALUop)
+ 2'b00 : out = Ain + Bin; //add Ain and Bin
+ 2'b01 : out = Ain - Bin; //subtract Ain and Bin
+ 2'b10 : out = Ain & Bin; //AND Ain and Bin
+ 2'b11 : out = ~Bin; //Negate Bin
+ endcase
+
+ //make it better by putting it into the add and subtraction above
+ Z[0] = out[15]; //negative
+ Z[1] = (ALUop == 2'b00) ? ((Ain[15] == Bin[15]) && (out[15] != Ain[15])) :
+ (ALUop == 2'b01) ? ((Ain[15] != Bin[15]) && (out[15] != Ain[15])) : 1'b0; //improvements could be made
+ Z[2] = out == {16{1'b0}}; //zero
+ end
+ endmodule \ No newline at end of file
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
diff --git a/data.txt b/data.txt
new file mode 100644
index 0000000..1f1ecbd
--- /dev/null
+++ b/data.txt
@@ -0,0 +1,256 @@
+@00 1101000000000101
+@01 0110000000100000
+@02 1101001000000110
+@03 1000001000100000
+@04 1110000000000000
+@05 1010101111001101
+@06 0000000000000000
+@07 0000000000000000
+@08 0000000000000000
+@09 0000000000000000
+@0A 0000000000000000
+@0B 0000000000000000
+@0C 0000000000000000
+@0D 0000000000000000
+@0E 0000000000000000
+@0F 0000000000000000
+@10 0000000000000000
+@11 0000000000000000
+@12 0000000000000000
+@13 0000000000000000
+@14 0000000000000000
+@15 0000000000000000
+@16 0000000000000000
+@17 0000000000000000
+@18 0000000000000000
+@19 0000000000000000
+@1A 0000000000000000
+@1B 0000000000000000
+@1C 0000000000000000
+@1D 0000000000000000
+@1E 0000000000000000
+@1F 0000000000000000
+@20 0000000000000000
+@21 0000000000000000
+@22 0000000000000000
+@23 0000000000000000
+@24 0000000000000000
+@25 0000000000000000
+@26 0000000000000000
+@27 0000000000000000
+@28 0000000000000000
+@29 0000000000000000
+@2A 0000000000000000
+@2B 0000000000000000
+@2C 0000000000000000
+@2D 0000000000000000
+@2E 0000000000000000
+@2F 0000000000000000
+@30 0000000000000000
+@31 0000000000000000
+@32 0000000000000000
+@33 0000000000000000
+@34 0000000000000000
+@35 0000000000000000
+@36 0000000000000000
+@37 0000000000000000
+@38 0000000000000000
+@39 0000000000000000
+@3A 0000000000000000
+@3B 0000000000000000
+@3C 0000000000000000
+@3D 0000000000000000
+@3E 0000000000000000
+@3F 0000000000000000
+@40 0000000000000000
+@41 0000000000000000
+@42 0000000000000000
+@43 0000000000000000
+@44 0000000000000000
+@45 0000000000000000
+@46 0000000000000000
+@47 0000000000000000
+@48 0000000000000000
+@49 0000000000000000
+@4A 0000000000000000
+@4B 0000000000000000
+@4C 0000000000000000
+@4D 0000000000000000
+@4E 0000000000000000
+@4F 0000000000000000
+@50 0000000000000000
+@51 0000000000000000
+@52 0000000000000000
+@53 0000000000000000
+@54 0000000000000000
+@55 0000000000000000
+@56 0000000000000000
+@57 0000000000000000
+@58 0000000000000000
+@59 0000000000000000
+@5A 0000000000000000
+@5B 0000000000000000
+@5C 0000000000000000
+@5D 0000000000000000
+@5E 0000000000000000
+@5F 0000000000000000
+@60 0000000000000000
+@61 0000000000000000
+@62 0000000000000000
+@63 0000000000000000
+@64 0000000000000000
+@65 0000000000000000
+@66 0000000000000000
+@67 0000000000000000
+@68 0000000000000000
+@69 0000000000000000
+@6A 0000000000000000
+@6B 0000000000000000
+@6C 0000000000000000
+@6D 0000000000000000
+@6E 0000000000000000
+@6F 0000000000000000
+@70 0000000000000000
+@71 0000000000000000
+@72 0000000000000000
+@73 0000000000000000
+@74 0000000000000000
+@75 0000000000000000
+@76 0000000000000000
+@77 0000000000000000
+@78 0000000000000000
+@79 0000000000000000
+@7A 0000000000000000
+@7B 0000000000000000
+@7C 0000000000000000
+@7D 0000000000000000
+@7E 0000000000000000
+@7F 0000000000000000
+@80 0000000000000000
+@81 0000000000000000
+@82 0000000000000000
+@83 0000000000000000
+@84 0000000000000000
+@85 0000000000000000
+@86 0000000000000000
+@87 0000000000000000
+@88 0000000000000000
+@89 0000000000000000
+@8A 0000000000000000
+@8B 0000000000000000
+@8C 0000000000000000
+@8D 0000000000000000
+@8E 0000000000000000
+@8F 0000000000000000
+@90 0000000000000000
+@91 0000000000000000
+@92 0000000000000000
+@93 0000000000000000
+@94 0000000000000000
+@95 0000000000000000
+@96 0000000000000000
+@97 0000000000000000
+@98 0000000000000000
+@99 0000000000000000
+@9A 0000000000000000
+@9B 0000000000000000
+@9C 0000000000000000
+@9D 0000000000000000
+@9E 0000000000000000
+@9F 0000000000000000
+@A0 0000000000000000
+@A1 0000000000000000
+@A2 0000000000000000
+@A3 0000000000000000
+@A4 0000000000000000
+@A5 0000000000000000
+@A6 0000000000000000
+@A7 0000000000000000
+@A8 0000000000000000
+@A9 0000000000000000
+@AA 0000000000000000
+@AB 0000000000000000
+@AC 0000000000000000
+@AD 0000000000000000
+@AE 0000000000000000
+@AF 0000000000000000
+@B0 0000000000000000
+@B1 0000000000000000
+@B2 0000000000000000
+@B3 0000000000000000
+@B4 0000000000000000
+@B5 0000000000000000
+@B6 0000000000000000
+@B7 0000000000000000
+@B8 0000000000000000
+@B9 0000000000000000
+@BA 0000000000000000
+@BB 0000000000000000
+@BC 0000000000000000
+@BD 0000000000000000
+@BE 0000000000000000
+@BF 0000000000000000
+@C0 0000000000000000
+@C1 0000000000000000
+@C2 0000000000000000
+@C3 0000000000000000
+@C4 0000000000000000
+@C5 0000000000000000
+@C6 0000000000000000
+@C7 0000000000000000
+@C8 0000000000000000
+@C9 0000000000000000
+@CA 0000000000000000
+@CB 0000000000000000
+@CC 0000000000000000
+@CD 0000000000000000
+@CE 0000000000000000
+@CF 0000000000000000
+@D0 0000000000000000
+@D1 0000000000000000
+@D2 0000000000000000
+@D3 0000000000000000
+@D4 0000000000000000
+@D5 0000000000000000
+@D6 0000000000000000
+@D7 0000000000000000
+@D8 0000000000000000
+@D9 0000000000000000
+@DA 0000000000000000
+@DB 0000000000000000
+@DC 0000000000000000
+@DD 0000000000000000
+@DE 0000000000000000
+@DF 0000000000000000
+@E0 0000000000000000
+@E1 0000000000000000
+@E2 0000000000000000
+@E3 0000000000000000
+@E4 0000000000000000
+@E5 0000000000000000
+@E6 0000000000000000
+@E7 0000000000000000
+@E8 0000000000000000
+@E9 0000000000000000
+@EA 0000000000000000
+@EB 0000000000000000
+@EC 0000000000000000
+@ED 0000000000000000
+@EE 0000000000000000
+@EF 0000000000000000
+@F0 0000000000000000
+@F1 0000000000000000
+@F2 0000000000000000
+@F3 0000000000000000
+@F4 0000000000000000
+@F5 0000000000000000
+@F6 0000000000000000
+@F7 0000000000000000
+@F8 0000000000000000
+@F9 0000000000000000
+@FA 0000000000000000
+@FB 0000000000000000
+@FC 0000000000000000
+@FD 0000000000000000
+@FE 0000000000000000
+@FF 0000000000000000 \ No newline at end of file
diff --git a/datapath.sv b/datapath.sv
new file mode 100644
index 0000000..ed74541
--- /dev/null
+++ b/datapath.sv
@@ -0,0 +1,48 @@
+module datapath(clk, readnum, vsel, loada, loadb, shift, asel, bsel, ALUop,
+ loadc, loads, writenum, write, Z_out, datapath_out, sximm5, sximm8, mdata);
+
+ input clk;
+ input write, loada, loadb, asel, bsel, loadc, loads;
+ input [2:0] readnum, writenum;
+ input [1:0] shift, ALUop, vsel;
+ input [15:0] sximm8;
+ input [15:0] sximm5;
+ input [15:0] mdata;
+
+ output reg [15:0] datapath_out;
+ output reg [2:0] Z_out;
+
+ reg [15:0] data_in, in, Aout;
+ reg [7:0] PC = 8'b0; // fix later
+ reg [15:0] Ain, Bin = {16{1'b0}};
+ wire [15:0] data_out, sout, out;
+ wire [2:0] Z;
+ //initialize all ins and outs and internal wires above
+
+ regfile REGFILE(data_in,writenum,write,readnum,clk,data_out);
+ shifter SHIFTER(in,shift,sout);
+ ALU alu(Ain,Bin,ALUop,out,Z);
+
+ //the three components
+
+ always_comb begin
+ case (vsel)
+ 2'b00: data_in = datapath_out; //also known as C
+ 2'b01: data_in = {8'b0, PC};
+ 2'b10: data_in = sximm8; //immediate sign extended
+ 2'b11: data_in = mdata;
+ endcase
+
+ Bin = bsel ? sximm5 : sout; //the Bin multiplexer
+ Ain = asel ? ({16{1'b0}}) : Aout; //the Ain multiplexer
+ end
+
+ always_ff @(posedge clk) begin
+ //push all when clk is pressed
+ if (loadb) in = data_out;
+ if (loada) Aout = data_out;
+ if (loadc) datapath_out = out;
+ if (loads) Z_out = Z;
+ end
+
+endmodule \ No newline at end of file
diff --git a/lab7bonus_autograder_check.sv b/lab7bonus_autograder_check.sv
new file mode 100644
index 0000000..eac9f67
--- /dev/null
+++ b/lab7bonus_autograder_check.sv
@@ -0,0 +1,71 @@
+module lab7bonus_check_tb;
+ reg [3:0] KEY;
+ reg [9:0] SW;
+ wire [9:0] LEDR;
+ wire [6:0] HEX0, HEX1, HEX2, HEX3, HEX4, HEX5;
+ reg err;
+ reg CLOCK_50;
+
+ lab7bonus_top DUT(KEY,SW,LEDR,HEX0,HEX1,HEX2,HEX3,HEX4,HEX5,CLOCK_50);
+
+ initial forever begin
+ CLOCK_50 = 0; #5;
+ CLOCK_50 = 1; #5;
+ end
+
+ initial begin
+ err = 0;
+ KEY[1] = 1'b0; // reset asserted
+ // check if program from Figure 2 in Lab 8 handout can be found loaded in memory
+ if (DUT.MEM.mem[0] !== 16'b1101000000001111) begin err = 1; $display("FAILED: mem[0] wrong; please set data.txt using lab7bonusfig2.s"); $stop; end
+ if (DUT.MEM.mem[1] !== 16'b0110000000000000) begin err = 1; $display("FAILED: mem[1] wrong; please set data.txt using lab7bonusfig2.s"); $stop; end
+ if (DUT.MEM.mem[2] !== 16'b1101000100000000) begin err = 1; $display("FAILED: mem[2] wrong; please set data.txt using lab7bonusfig2.s"); $stop; end
+ if (DUT.MEM.mem[3] !== 16'b1101001000000000) begin err = 1; $display("FAILED: mem[3] wrong; please set data.txt using lab7bonusfig2.s"); $stop; end
+ if (DUT.MEM.mem[4] !== 16'b1101001100010000) begin err = 1; $display("FAILED: mem[4] wrong; please set data.txt using lab7bonusfig2.s"); $stop; end
+ if (DUT.MEM.mem[5] !== 16'b1101010000000001) begin err = 1; $display("FAILED: mem[5] wrong; please set data.txt using lab7bonusfig2.s"); $stop; end
+ if (DUT.MEM.mem[6] !== 16'b1010001110100001) begin err = 1; $display("FAILED: mem[6] wrong; please set data.txt using lab7bonusfig2.s"); $stop; end
+ if (DUT.MEM.mem[7] !== 16'b0110010110100000) begin err = 1; $display("FAILED: mem[7] wrong; please set data.txt using lab7bonusfig2.s"); $stop; end
+ if (DUT.MEM.mem[8] !== 16'b1010001001000101) begin err = 1; $display("FAILED: mem[8] wrong; please set data.txt using lab7bonusfig2.s"); $stop; end
+ if (DUT.MEM.mem[9] !== 16'b1010000100100100) begin err = 1; $display("FAILED: mem[9] wrong; please set data.txt using lab7bonusfig2.s"); $stop; end
+ if (DUT.MEM.mem[10] !== 16'b1010100100000000) begin err = 1; $display("FAILED: mem[10] wrong; please set data.txt using lab7bonusfig2.s"); $stop; end
+ if (DUT.MEM.mem[11] !== 16'b0010001111111010) begin err = 1; $display("FAILED: mem[11] wrong; please set data.txt using lab7bonusfig2.s"); $stop; end
+ if (DUT.MEM.mem[12] !== 16'b1101001100010100) begin err = 1; $display("FAILED: mem[12] wrong; please set data.txt using lab7bonusfig2.s"); $stop; end
+ if (DUT.MEM.mem[13] !== 16'b1000001101000000) begin err = 1; $display("FAILED: mem[13] wrong; please set data.txt using lab7bonusfig2.s"); $stop; end
+ if (DUT.MEM.mem[14] !== 16'b1110000000000000) begin err = 1; $display("FAILED: mem[14] wrong; please set data.txt using lab7bonusfig2.s"); $stop; end
+ if (DUT.MEM.mem[15] !== 16'b0000000000000100) begin err = 1; $display("FAILED: mem[15] wrong; please set data.txt using lab7bonusfig2.s"); $stop; end
+ if (DUT.MEM.mem[16] !== 16'b0000000000110010) begin err = 1; $display("FAILED: mem[16] wrong; please set data.txt using lab7bonusfig2.s"); $stop; end
+ if (DUT.MEM.mem[17] !== 16'b0000000011001000) begin err = 1; $display("FAILED: mem[17] wrong; please set data.txt using lab7bonusfig2.s"); $stop; end
+ if (DUT.MEM.mem[18] !== 16'b0000000001100100) begin err = 1; $display("FAILED: mem[18] wrong; please set data.txt using lab7bonusfig2.s"); $stop; end
+ if (DUT.MEM.mem[19] !== 16'b0000000111110100) begin err = 1; $display("FAILED: mem[19] wrong; please set data.txt using lab7bonusfig2.s"); $stop; end
+ if (DUT.MEM.mem[20] !== 16'b1011101011011101) begin err = 1; $display("FAILED: mem[20] wrong; please set data.txt using lab7bonusfig2.s"); $stop; end
+ if (DUT.MEM.mem[21] !== 16'b0000000000000000) begin err = 1; $display("FAILED: mem[21] wrong; please set data.txt using lab7bonusfig2.s"); $stop; end
+
+ #10; // wait until next falling edge of clock
+ KEY[1] = 1'b1; // reset de-asserted, PC still undefined if as in Figure 4
+
+ #10; // waiting for RST state to cause reset of PC
+ if (DUT.CPU.PC !== 9'h0) begin err = 1; $display("FAILED: PC did not reset to 0."); $stop; end
+
+ // If your simlation never gets past the the line below, check if your CMP instruction is working
+ @(posedge LEDR[8]); // set LEDR[8] to one when executing HALT
+
+ // NOTE: your program counter register output should be called PC and be inside a module with instance name CPU
+ // NOTE: if HALT is working, PC won't change after reaching 0xE
+ if (DUT.CPU.PC !== 9'hF) begin err = 1; $display("FAILED: PC at HALT is incorrect."); $stop; end
+ if (DUT.CPU.DP.REGFILE.R4 !== 16'h1) begin err = 1; $display("FAILED: R4 incorrect at exit; did MOV R4,#1 not work?"); $stop; end
+ if (DUT.CPU.DP.REGFILE.R0 !== 16'h4) begin err = 1; $display("FAILED: R0 incorrect at exit; did LDR R0,[R0] not work?"); $stop; end
+
+ // check memory contents for result
+ if (DUT.MEM.mem[8'h14] === 16'h0) begin
+ err = 1;
+ $display("FAILED: mem[0x14] (result) is wrong;");
+ if (DUT.CPU.DP.REGFILE.R3 === 16'h10)
+ $display(" hint: check if your BLT instruction skipped MOV R3, result");
+ $stop;
+ end
+ if (DUT.MEM.mem[8'h14] !== 16'd850) begin err = 1; $display("FAILED: mem[0x14] (result) is wrong;"); $stop; end
+
+ if (~err) $display("INTERFACE OK");
+ $stop;
+ end
+endmodule
diff --git a/lab7bonus_fig2.s b/lab7bonus_fig2.s
new file mode 100644
index 0000000..35fcc69
--- /dev/null
+++ b/lab7bonus_fig2.s
@@ -0,0 +1,28 @@
+ MOV R0,N // R0 = address of variable N
+ LDR R0,[R0] // R0 = 4
+ MOV R1,#0 // R1 = 0; R1 is "i"
+ MOV R2,#0 // R2 = 0; R2 is "sum"
+ MOV R3,amount // R3 = base address of array "amount"
+ MOV R4,#1 // R4 = 1
+
+LOOP: // for(i=0; i<N; i++) sum = sum + amount[i];
+ ADD R5,R3,R1 // R5 = address of amount[i]
+ LDR R5,[R5] // R5 = amount[i]
+ ADD R2,R2,R5 // sum = sum + amount[i]
+ ADD R1,R1,R4 // i++
+ CMP R1,R0
+ BLT LOOP // if i < N goto LOOP
+
+ MOV R3,result
+ STR R2,[R3] // result = sum
+ HALT
+
+N:
+ .word 4
+amount:
+ .word 50
+ .word 200
+ .word 100
+ .word 500
+result:
+ .word 0xBADD
diff --git a/lab7bonus_fig4.s b/lab7bonus_fig4.s
new file mode 100644
index 0000000..35e20e0
--- /dev/null
+++ b/lab7bonus_fig4.s
@@ -0,0 +1,29 @@
+ MOV R6,stack_begin
+ LDR R6,[R6] // initialize stack pointer
+ MOV R4, result // R4 contains address of result
+ MOV R3,#0
+ STR R3,[R4] // result = 0;
+ MOV R0,#1 // R0 contains first parameter
+ MOV R1,#5 // R1 contains second parameter
+ MOV R2,#9 // R2 contains third parameter
+ MOV R3,#20 // R3 contains fourth parameter
+ BL leaf_example // call leaf_example(1,5,9,20);
+ STR R0,[R4] // result = leaf_example(1,5,9,20);
+ HALT
+leaf_example:
+ STR R4,[R6] // save R4 for use afterwards
+ STR R5,[R6,#-1] // save R5 for use afterwards
+ ADD R4,R0,R1 // R4 = g + h
+ ADD R5,R2,R3 // R5 = i + j
+ MVN R5,R5 // R5 = ~(i + j)
+ ADD R4,R4,R5 // R4 = (g + h) + ~(i + j)
+ MOV R5,#1
+ ADD R4,R4,R5 // R4 = (g + h) - (i + j)
+ MOV R0,R4 // R0 = return value (g + h) - (i + j)
+ LDR R5,[R6,#-1] // restore saved contents of R5
+ LDR R4,[R6] // restore saved contents of R4
+ BX R7 // return control to caller
+stack_begin:
+ .word 0xFF
+result:
+ .word 0xCCCC
diff --git a/lab7bonus_stage2_tb.sv b/lab7bonus_stage2_tb.sv
new file mode 100644
index 0000000..aced299
--- /dev/null
+++ b/lab7bonus_stage2_tb.sv
@@ -0,0 +1,35 @@
+module lab7bonus_stage2_tb;
+ reg [3:0] KEY;
+ reg [9:0] SW;
+ wire [9:0] LEDR;
+ wire [6:0] HEX0, HEX1, HEX2, HEX3, HEX4, HEX5;
+ reg err;
+ reg CLOCK_50;
+
+ lab7bonus_top DUT(KEY,SW,LEDR,HEX0,HEX1,HEX2,HEX3,HEX4,HEX5,CLOCK_50);
+
+ initial forever begin
+ CLOCK_50 = 0; #5;
+ CLOCK_50 = 1; #5;
+ end
+ wire break = (LEDR[8] == 1'b1);
+ initial begin
+ err = 0;
+ KEY[1] = 1'b0; // reset asserted
+ #10; // wait until next falling edge of clock
+ KEY[1] = 1'b1; // reset de-asserted, PC still undefined if as in Figure 4
+ while (~break) begin
+ // Change the following line to wait until your CPU starts to you fetch
+ // the next instruction (e.g., IF1 state from Lab 7 or equivalent in
+ // your design). DUT.CPU.FSM is not required for by the autograder
+ // for Lab 8.
+ @(posedge (DUT.CPU.FSM.present_state == `YOUR_IF1_STATE) or posedge break);
+
+ @(negedge CLOCK_50); // show advance to negative edge of clock
+ $display("PC = %h", DUT.CPU.PC);
+ end
+ if (DUT.MEM.mem[25] !== -16'd23) begin err = 1; $display("FAILED: mem[25] wrong"); $stop; end
+ if (~err) $display("PASSED");
+ $stop;
+ end
+endmodule
diff --git a/lab7bonus_top.sv b/lab7bonus_top.sv
new file mode 100644
index 0000000..d76cf7c
--- /dev/null
+++ b/lab7bonus_top.sv
@@ -0,0 +1,90 @@
+`define MNONE 2'b00
+`define MREAD 2'b01
+`define MWRITE 2'b10
+
+module lab7bonus_top(KEY,SW,LEDR,HEX0,HEX1,HEX2,HEX3,HEX4,HEX5);
+ input [3:0] KEY;
+ input [9:0] SW;
+ output reg [9:0] LEDR;
+ output [6:0] HEX0, HEX1, HEX2, HEX3, HEX4, HEX5;
+
+ reg [8:0] mem_addr;
+ reg [7:0] read_address, write_address, next_LEDR, onto_LEDR;
+ reg write, enable;
+ reg [15:0] dout, din, read_data, write_data, ir;
+ wire [1:0] mem_cmd;
+ reg msel;
+ wire N, V, Z;
+
+
+ RAM MEM(.clk (~KEY[0]),
+ .read_address (read_address),
+ .write_address (write_address),
+ .write (write),
+ .din (din),
+ .dout (dout)
+ );
+
+ cpu CPU(.clk (~KEY[0]),
+ .reset (~KEY[1]),
+ .read_data (read_data),
+ .write_data(write_data),
+ .mem_addr(mem_addr),
+ .mem_cmd(mem_cmd),
+ .N(N),
+ .V(V),
+ .Z(Z)
+ );
+
+
+ always_comb begin
+
+ msel = mem_addr[8]; //checks the last bit to check the indicated address. 0 would mean below 255 and 1 would mean abouve 256
+ write = ({mem_cmd, msel} == {`MWRITE, 1'b0}); //write choosing
+ enable = ({mem_cmd, msel} == {`MREAD, 1'b0}); //the and gates and stuff
+
+ write_address = mem_addr[7:0];
+ read_address = mem_addr[7:0];
+ din = write_data;
+
+ read_data = enable ? dout : {16{1'bz}}; //tri-state driver
+
+ if ({mem_addr, mem_cmd} == {9'h140, `MREAD}) read_data = {8'b0, SW[7:0]}; //desing own logic this reads the switches if mem_cmd and addr are according
+ else read_data = read_data;
+
+ if ({mem_addr, mem_cmd} == {9'h100, `MWRITE}) next_LEDR = write_data[7:0]; //design own logic this writes to the switches if mem_cmd and addr are according
+ else next_LEDR = 8'bx;;
+
+ end
+
+ always_ff @(posedge ~KEY[0]) begin
+ LEDR[7:0] = next_LEDR;
+ end
+
+endmodule
+
+
+// Ram block obtained form slide set 11
+module RAM(clk,read_address,write_address,write,din,dout);
+ parameter data_width = 16;
+ parameter addr_width = 8;
+ parameter filename = "data.txt";
+
+ input clk;
+ input [addr_width-1:0] read_address, write_address;
+ input write;
+ input [data_width-1:0] din;
+ output [data_width-1:0] dout;
+ reg [data_width-1:0] dout;
+
+ reg [data_width-1:0] mem [2**addr_width-1:0];
+
+ initial $readmemb(filename, mem);
+
+ always @ (posedge clk) begin
+ if (write)
+ mem[write_address] <= din;
+ dout <= mem[read_address]; // dout doesn't get din in this clock cycle
+ // (this is due to Verilog non-blocking assignment "<=")
+ end
+endmodule
diff --git a/regfile.sv b/regfile.sv
new file mode 100644
index 0000000..8237b26
--- /dev/null
+++ b/regfile.sv
@@ -0,0 +1,45 @@
+module regfile(data_in,writenum,write,readnum,clk,data_out);
+ input [15:0] data_in;
+ input [2:0] writenum, readnum;
+ input write, clk;
+ output reg [15:0] data_out;
+
+ // This file is made explicit and long for easy readability
+ // e.g
+ // The always_comb can have only one case (readnum to data_out change)
+ // The always_ff in turn will only have one if and one case (write and writenum to R0-R7)
+ // make file more efficient
+
+ reg [15:0] R0, R1, R2, R3, R4, R5, R6, R7;
+
+ always_comb begin
+ //read num for data_out
+ case (readnum)
+ 3'b000: data_out = R0;
+ 3'b001: data_out = R1;
+ 3'b010: data_out = R2;
+ 3'b011: data_out = R3;
+ 3'b100: data_out = R4;
+ 3'b101: data_out = R5;
+ 3'b110: data_out = R6;
+ 3'b111: data_out = R7;
+ endcase
+ end
+
+ always_ff @(posedge clk) begin
+ if (write) begin //only load into register if write is on = 1
+ case (writenum)
+ // Check load select and put data_in into R0-7 depending
+ 3'b000: R0 <= data_in;
+ 3'b001: R1 <= data_in;
+ 3'b010: R2 <= data_in;
+ 3'b011: R3 <= data_in;
+ 3'b100: R4 <= data_in;
+ 3'b101: R5 <= data_in;
+ 3'b110: R6 <= data_in;
+ 3'b111: R7 <= data_in;
+ endcase
+ end
+ end
+
+endmodule \ No newline at end of file
diff --git a/shifter.sv b/shifter.sv
new file mode 100644
index 0000000..da6fd77
--- /dev/null
+++ b/shifter.sv
@@ -0,0 +1,18 @@
+module shifter(in,shift,sout);
+ input [15:0] in;
+ input [1:0] shift;
+ output reg [15:0] sout;
+
+ always_comb begin
+ case (shift)
+ //no shift
+ 2'b00: sout = in;
+ 2'b01: sout = in << 1; //left bit shift
+ 2'b10: sout = in >> 1; //right bit shift
+ 2'b11: begin
+ sout = in >> 1;
+ sout[15] = sout[14]; //in[15] copied to to MSB after right bit shift
+ end
+ endcase
+ end
+endmodule \ No newline at end of file
diff --git a/trigger.py b/trigger.py
new file mode 100644
index 0000000..72ecf10
--- /dev/null
+++ b/trigger.py
@@ -0,0 +1,31 @@
+#!/usr/bin/python3
+# WARNING: Do not modify this file unless directed to do so by your instructor
+
+import requests
+import os
+import re
+
+def notify_autograder(lab,section,student):
+ API_ENDPOINT = "https://cpen211.ece.ubc.ca/autograder_build_request.php"
+ data = {'github_username':student,
+ 'lab':lab,
+ 'section':section}
+ r = requests.post(url=API_ENDPOINT, data=data, timeout=5)
+ if r.text == 'OK':
+ print('Queuing your submission for ranking. You will be emailed when results are available.')
+ else:
+ print('ERROR unable to queue your submission for ranking; notify instructor.')
+ print('Response from server -->')
+ print(r.text);
+ print('<---')
+
+m = re.search(r'lab-7-l1[a-z]-bonus-([^/])+/lab-7-l1(?P<section>[a-z])-bonus-(?P<user>\S+)', os.getcwd())
+if m:
+ github_username = m.group('user')
+ print("Username: " + github_username)
+ section = m.group('section').upper()
+ print("Section: L1" + section)
+else:
+ print("ERROR: Did not match regex. Unable to queue your submission for ranking; notify instructor.")
+ exit(1)
+notify_autograder(8,section,github_username)