diff options
| author | kryptoish <krish_thakur7@icloud.com> | 2024-12-03 16:58:07 -0800 |
|---|---|---|
| committer | kryptoish <krish_thakur7@icloud.com> | 2024-12-03 16:58:07 -0800 |
| commit | f665f0ff80397ab10dbbea6cfcb302bb131f9719 (patch) | |
| tree | 131ba7ab978dd127992111d354e8460c61fbc626 | |
added files
| -rw-r--r-- | README.md | 14 | ||||
| -rw-r--r-- | alu.sv | 21 | ||||
| -rw-r--r-- | cpu.sv | 150 | ||||
| -rw-r--r-- | data.txt | 256 | ||||
| -rw-r--r-- | datapath.sv | 48 | ||||
| -rw-r--r-- | lab7bonus_autograder_check.sv | 71 | ||||
| -rw-r--r-- | lab7bonus_fig2.s | 28 | ||||
| -rw-r--r-- | lab7bonus_fig4.s | 29 | ||||
| -rw-r--r-- | lab7bonus_stage2_tb.sv | 35 | ||||
| -rw-r--r-- | lab7bonus_top.sv | 90 | ||||
| -rw-r--r-- | regfile.sv | 45 | ||||
| -rw-r--r-- | shifter.sv | 18 | ||||
| -rw-r--r-- | trigger.py | 31 |
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 @@ +[](https://classroom.github.com/a/H84oO7Rx) +[](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. @@ -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 @@ -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) |