├── README.md ├── Topic 1. Multiple-cycle CPU Design ├── adder.v ├── alu_wrapper.v ├── clock.v ├── ctrl.v ├── ctrl_test.v ├── lcd.v ├── lcdtest.v ├── memory.coe ├── new_alu_test.v ├── other.v ├── pbdebounce.v ├── top.bit └── top.v ├── Topic 2. Pipelined CPU with stall ├── alu.v ├── anti_jitter.v ├── clk_gen.v ├── controller.v ├── data_mem.hex ├── data_ram.v ├── datapath.v ├── define.vh ├── dispaly.v ├── displcd.v ├── inst_mem.hex ├── inst_rom.v ├── mips_core.v ├── mips_define.vh ├── mips_top.v ├── mips_top_3e.ucf ├── regfile.v └── sim_mips_top.v ├── Topic 3. Pipelined CPU with forwarding ├── alu.v ├── anti_jitter.v ├── bad_datapath.v ├── clk_gen.v ├── controller.v ├── data_mem.hex ├── data_ram.v ├── datapath.v ├── define.vh ├── dispaly.v ├── displcd.v ├── inst_mem.hex ├── inst_rom.v ├── mips_core.v ├── mips_define.vh ├── mips_top.bit ├── mips_top.v ├── mips_top_3e.ucf ├── regfile.v ├── sim_mips_top.v └── waveconf.wcfg ├── Topic 4. Pipelined CPU resolving control hazard ├── TEST1.wcfg ├── alu.v ├── anti_jitter.v ├── clk_gen.v ├── controller.v ├── data_mem.hex ├── data_ram.v ├── datapath.v ├── define.vh ├── dispaly.v ├── displcd.v ├── inst_mem.hex ├── inst_rom.v ├── mips_core.v ├── mips_define.vh ├── mips_top.bit ├── mips_top.v ├── mips_top_3e.ucf ├── regfile.v ├── sim_mips_top.v └── waveconf.wcfg ├── Topic 5. Pipelined CPU support 31 MIPS Instructions.pdf ├── alu.v ├── anti_jitter.v ├── clk_gen.v ├── controller.v ├── data_mem.hex ├── data_ram.v ├── datapath.v ├── define.vh ├── dispaly.v ├── displcd.v ├── inst_mem.hex ├── inst_rom.v ├── mips_core.v ├── mips_define.vh ├── mips_top.bit ├── mips_top.v ├── mips_top_3e.ucf ├── regfile.v ├── sim_mips_top.v └── test.wcfg ├── Topic 6. Pipelined CPU supporting interrupt ├── alu.v ├── anti_jitter.v ├── clk_gen.v ├── controller.v ├── cp0.v ├── data_mem.hex ├── data_ram.v ├── datapath.v ├── define.vh ├── dispaly.v ├── displcd.v ├── inst_mem.hex ├── inst_rom.v ├── mips_core.v ├── mips_define.vh ├── mips_top.bit ├── mips_top.v ├── mips_top_3e.ucf ├── regfile.v ├── sim_mips_top.v └── test.wcfg ├── Topic 7. Cache Line Design ├── alu.v ├── anti_jitter.v ├── cache_line.v ├── cache_tbw.v ├── clk_gen.v ├── controller.v ├── cp0.v ├── data_mem.hex ├── data_ram.v ├── datapath.v ├── define.vh ├── dispaly.v ├── displcd.v ├── inst_mem.hex ├── inst_rom.v ├── mips_core.v ├── mips_define.vh ├── mips_top.bit ├── mips_top.v ├── mips_top_3e.ucf ├── regfile.v ├── sim_mips_top.v ├── test.wcfg └── test_cache.wcfg └── Topic 8. Pipelined CPU with Cache ├── alu.v ├── anti_jitter.v ├── cache_line.v ├── cache_tbw.v ├── clk_gen.v ├── cmu.v ├── controller.v ├── cp0.v ├── data_mem.hex ├── data_ram.v ├── datapath.v ├── define.vh ├── dispaly.v ├── displcd.v ├── inst_mem.hex ├── inst_rom.v ├── mips_core.v ├── mips_define.vh ├── mips_top.bit ├── mips_top.v ├── mips_top_3e.ucf ├── regfile.v ├── sim_mips_top.v ├── test.wcfg └── test_cache.wcfg /README.md: -------------------------------------------------------------------------------- 1 | # Computer-Architecture 2 | This is the laboratory assignment for the course Computer Architecture. 3 | 4 | The final result of this project is a pipelined MIPS CPU supporting 31 MIPS instructions, interrupt and the cache. 5 | 6 | My collaborator is Yuheng ZHOU. 7 | -------------------------------------------------------------------------------- /Topic 1. Multiple-cycle CPU Design/adder.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 15:41:46 03/23/2015 7 | // Design Name: 8 | // Module Name: adder 9 | // Project Name: 10 | // Target Devices: 11 | // Tool versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module adder(input clk, output reg [3:0] address 22 | ); 23 | initial begin 24 | address = 4'b0; 25 | end 26 | 27 | always@(posedge clk) 28 | begin 29 | if (address < 4'b1111) 30 | begin 31 | address <= address + 1; 32 | end 33 | else 34 | begin 35 | address <= 4'b0; 36 | end 37 | end 38 | 39 | endmodule 40 | 41 | -------------------------------------------------------------------------------- /Topic 1. Multiple-cycle CPU Design/alu_wrapper.v: -------------------------------------------------------------------------------- 1 | //alu 2 | module alu_wrapper(rin_A, rin_B, ir_data, pc, alu_srcA, alu_srcB, alu_ctrl, zero, res); 3 | 4 | input [31:0] rin_A; 5 | input [31:0] rin_B; 6 | input [31:0] ir_data; 7 | input [31:0] pc; 8 | input alu_srcA; 9 | input [1:0] alu_srcB; 10 | input [1:0] alu_ctrl; 11 | output zero; 12 | output[31:0] res; 13 | 14 | wire [31:0] rin_A; 15 | wire [31:0] rin_B; 16 | wire [31:0] ir_data; 17 | wire [31:0] pc; 18 | wire alu_srcA; 19 | wire [1:0] alu_srcB; 20 | wire [1:0] alu_ctrl; 21 | wire [31:0] res; 22 | wire [31:0] in_A; 23 | wire [31:0] in_B; 24 | wire [31:0] signimm; 25 | wire [31:0] shiftimm; 26 | wire zero; 27 | 28 | assign signimm = (ir_data[15] == 1'b0) ? {16'h0000, ir_data[15:0]} : {16'hFFFF, ir_data[15:0]}; 29 | assign shiftimm = signimm; 30 | 31 | assign in_A = (alu_srcA == 1'b1)? rin_A : pc; 32 | //assign in_A = pc; 33 | assign in_B = (alu_srcB == 2'b00)? rin_B : ((alu_srcB == 2'b01)? 32'h00000001 : ((alu_srcB == 2'b10)? signimm: shiftimm)); 34 | assign zero = (res == 32'h00000000)? 1 : 0; 35 | 36 | alu x_alu(in_A, in_B, alu_ctrl, res); 37 | 38 | endmodule 39 | 40 | module alu( 41 | input wire [31:0] A, 42 | input wire [31:0] B, 43 | input wire [2:0] control, 44 | output reg [31:0] result 45 | ); 46 | 47 | always @ * begin 48 | case (control) 49 | 3'b000: result = A + B; 50 | 3'b001: result = A - B; 51 | 3'b010: result = ~(A | B); 52 | 3'b011: result = A & B; 53 | 3'b110: result=A-B; 54 | 3'b111: result=A=clkscale) // clock scaling 12 | begin 13 | clk=~clk; // output clock 14 | clkq=0; // reset clock register 15 | end 16 | end 17 | 18 | endmodule 19 | -------------------------------------------------------------------------------- /Topic 1. Multiple-cycle CPU Design/ctrl_test.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | //////////////////////////////////////////////////////////////////////////////// 4 | // Company: 5 | // Engineer: 6 | // 7 | // Create Date: 20:34:11 03/11/2014 8 | // Design Name: ctrl 9 | // Module Name: C:/Users/Student/Desktop/arch_frame/ctrl_test.v 10 | // Project Name: arch_frame 11 | // Target Device: 12 | // Tool versions: 13 | // Description: 14 | // 15 | // Verilog Test Fixture created by ISE for module: ctrl 16 | // 17 | // Dependencies: 18 | // 19 | // Revision: 20 | // Revision 0.01 - File Created 21 | // Additional Comments: 22 | // 23 | //////////////////////////////////////////////////////////////////////////////// 24 | 25 | module ctrl_test; 26 | 27 | // Inputs 28 | reg clk; 29 | reg rst; 30 | reg [31:0] ir_data; 31 | reg zero; 32 | 33 | // Outputs 34 | wire write_pc; 35 | wire iord; 36 | wire write_mem; 37 | wire write_dr; 38 | wire write_ir; 39 | wire memtoreg; 40 | wire regdst; 41 | wire [1:0] pcsource; 42 | wire write_c; 43 | wire [1:0] alu_ctrl; 44 | wire alu_srcA; 45 | wire [1:0] alu_srcB; 46 | wire write_a; 47 | wire write_b; 48 | wire write_reg; 49 | wire [3:0] state; 50 | wire [3:0] insn_type; 51 | wire [3:0] insn_code; 52 | wire [2:0] insn_stage; 53 | 54 | // Instantiate the Unit Under Test (UUT) 55 | ctrl uut ( 56 | .clk(clk), 57 | .rst(rst), 58 | .ir_data(ir_data), 59 | .zero(zero), 60 | .write_pc(write_pc), 61 | .iord(iord), 62 | .write_mem(write_mem), 63 | .write_dr(write_dr), 64 | .write_ir(write_ir), 65 | .memtoreg(memtoreg), 66 | .regdst(regdst), 67 | .pcsource(pcsource), 68 | .write_c(write_c), 69 | .alu_ctrl(alu_ctrl), 70 | .alu_srcA(alu_srcA), 71 | .alu_srcB(alu_srcB), 72 | .write_a(write_a), 73 | .write_b(write_b), 74 | .write_reg(write_reg), 75 | .state(state), 76 | .insn_type(insn_type), 77 | .insn_code(insn_code), 78 | .insn_stage(insn_stage) 79 | ); 80 | 81 | initial begin 82 | // Initialize Inputs 83 | clk = 0; 84 | rst = 0; 85 | ir_data = 0; 86 | zero = 0; 87 | 88 | // Wait 100 ns for global reset to finish 89 | ir_data = 32'h8C010014; 90 | 91 | #450; 92 | ir_data = 32'h8C020015; 93 | 94 | #450; 95 | ir_data = 32'h00221820; 96 | 97 | #350; 98 | ir_data = 32'h00222022; 99 | 100 | #350; 101 | ir_data = 32'h00642824; 102 | 103 | #350; 104 | ir_data = 32'h00853027; 105 | 106 | #350; 107 | ir_data = 32'hAC060016; 108 | 109 | #350; 110 | ir_data = 32'h08000000; 111 | // Add stimulus here 112 | 113 | end 114 | 115 | always #50 clk = ~clk; 116 | 117 | endmodule 118 | 119 | -------------------------------------------------------------------------------- /Topic 1. Multiple-cycle CPU Design/lcdtest.v: -------------------------------------------------------------------------------- 1 | // Spartan-3E Starter Board 2 | // Liquid Crystal Display Test lcdtest.v 3 | 4 | module lcdtest(input CCLK, BTN2, input [3:0] SW, output LCDRS, LCDRW, LCDE, 5 | output [3:0] LCDDAT, output [7:0] LED); 6 | 7 | wire [3:0] lcdd; 8 | wire rslcd, rwlcd, elcd; 9 | wire debpb0; 10 | 11 | reg [255:0]strdata = "0123456789abcdefHello world!0000"; 12 | reg [3:0] temp=0; 13 | 14 | assign LCDDAT[3]=lcdd[3]; 15 | assign LCDDAT[2]=lcdd[2]; 16 | assign LCDDAT[1]=lcdd[1]; 17 | assign LCDDAT[0]=lcdd[0]; 18 | 19 | assign LCDRS=rslcd; 20 | assign LCDRW=rwlcd; 21 | assign LCDE=elcd; 22 | 23 | assign LED[0] = SW[0]; 24 | assign LED[1] = SW[1]; 25 | assign LED[2] = SW[2]; 26 | assign LED[3] = SW[3]; 27 | assign LED[4] = temp[0]; 28 | assign LED[5] = temp[1]; 29 | assign LED[6] = temp[2]; 30 | assign LED[7] = temp[3]; 31 | 32 | display M0 (CCLK, debpb0, strdata, rslcd, rwlcd, elcd, lcdd); 33 | clock M2 (CCLK, 25000, clk); 34 | pbdebounce M1 (clk, BTN2, debpb0); 35 | 36 | always @(posedge debpb0) 37 | begin 38 | // if(debpb0 == 1'b1) begin 39 | temp = temp +1; 40 | case(temp) 41 | 4'b0000:strdata[7:0] <= "0"; 42 | 4'b0001:strdata[7:0] <= "1"; 43 | 4'b0010:strdata[7:0] <= "2"; 44 | 4'b0011:strdata[7:0] <= "3"; 45 | 4'b0100:strdata[7:0] <= "4"; 46 | 4'b0101:strdata[7:0] <= "5"; 47 | 4'b0110:strdata[7:0] <= "6"; 48 | 4'b0111:strdata[7:0] <= "7"; 49 | 4'b1000:strdata[7:0] <= "8"; 50 | 4'b1001:strdata[7:0] <= "9"; 51 | 4'b1010:strdata[7:0] <= "A"; 52 | 4'b1011:strdata[7:0] <= "B"; 53 | 4'b1100:strdata[7:0] <= "C"; 54 | 4'b1101:strdata[7:0] <= "D"; 55 | 4'b1110:strdata[7:0] <= "E"; 56 | 4'b1111:strdata[7:0] <= "F"; 57 | default:strdata[7:0] <= "0"; 58 | endcase 59 | // end 60 | end 61 | 62 | endmodule 63 | 64 | module display(input CCLK, reset,input [255:0]strdata, output rslcd, rwlcd, elcd, 65 | output [3:0] lcdd); 66 | wire [7:0] lcddatin; 67 | 68 | lcd M0 (CCLK, resetlcd, clearlcd, homelcd, datalcd, addrlcd, 69 | lcdreset, lcdclear, lcdhome, lcddata, lcdaddr, 70 | rslcd, rwlcd, elcd, lcdd, lcddatin, initlcd); 71 | 72 | genlcd M1 (CCLK, reset, strdata, resetlcd, clearlcd, homelcd, datalcd, 73 | addrlcd, initlcd, lcdreset, lcdclear, lcdhome, 74 | lcddata, lcdaddr, lcddatin); 75 | endmodule 76 | 77 | 78 | module genlcd(input CCLK, debpb0, input [255:0]strdata, output reg resetlcd, 79 | output reg clearlcd, output reg homelcd, 80 | output reg datalcd, output reg addrlcd, 81 | output reg initlcd, input lcdreset, lcdclear, 82 | input lcdhome, lcddata, lcdaddr, 83 | output reg [7:0] lcddatin); 84 | 85 | reg [3:0] gstate; // state register 86 | 87 | integer i; 88 | 89 | always@(posedge CCLK) 90 | begin 91 | if (debpb0==1) 92 | begin 93 | resetlcd=0; 94 | clearlcd=0; 95 | homelcd=0; 96 | datalcd=0; 97 | gstate=0; 98 | end 99 | else 100 | 101 | case (gstate) 102 | 0: begin 103 | initlcd=1; 104 | gstate=1; 105 | end 106 | 1: begin 107 | initlcd=0; 108 | gstate=2; 109 | end 110 | 2: begin 111 | resetlcd=1; 112 | if (lcdreset==1) 113 | begin 114 | resetlcd=0; 115 | gstate=3; 116 | end 117 | end 118 | 3: begin 119 | initlcd=1; 120 | gstate=4; 121 | end 122 | 4: begin 123 | initlcd=0; 124 | gstate=5; 125 | end 126 | 5: begin 127 | clearlcd=1; 128 | if (lcdclear==1) 129 | begin 130 | clearlcd=0; 131 | gstate=6; 132 | end 133 | end 134 | 6: begin 135 | initlcd=1; 136 | gstate=7; 137 | end 138 | 7: begin 139 | initlcd=0; 140 | i=255; 141 | gstate=8; 142 | end 143 | 8: begin 144 | if(i>127) 145 | lcddatin[7:0]=8'b0000_0000; 146 | else 147 | lcddatin[7:0]=8'b0100_0000; 148 | 149 | addrlcd=1; 150 | if (lcdaddr==1) 151 | begin 152 | addrlcd=0; 153 | gstate=9; 154 | end 155 | end 156 | 9: begin 157 | initlcd=1; 158 | gstate=10; 159 | end 160 | 10: begin 161 | initlcd=0; 162 | gstate=11; 163 | end 164 | 11: begin 165 | lcddatin[7:0]=strdata[i-:8]; 166 | datalcd=1; 167 | if (lcddata==1) 168 | begin 169 | datalcd=0; 170 | gstate=12; 171 | end 172 | end 173 | 12: begin 174 | initlcd=1; 175 | gstate=13; 176 | end 177 | 13: begin 178 | initlcd=0; 179 | gstate=14; 180 | end 181 | 14: begin 182 | i=i-8; 183 | if (i<0) 184 | gstate=15; 185 | else if (i==127) 186 | gstate=8; 187 | else 188 | gstate=11; 189 | end 190 | 15: gstate=15; 191 | default: gstate=15; 192 | endcase 193 | 194 | end 195 | 196 | endmodule 197 | -------------------------------------------------------------------------------- /Topic 1. Multiple-cycle CPU Design/memory.coe: -------------------------------------------------------------------------------- 1 | memory_initialization_radix=16; 2 | memory_initialization_vector= 3 | 8C010014,8C020015,00221820,00222022,00642824, 4 | 00853027,AC060016,08000000,00000000,00000000, 5 | 00000000,00000000,00000000,00000000,00000000, 6 | 00000000,00000000,00000000,00000000,00000000, 7 | BEEF0000,0000BEEF; -------------------------------------------------------------------------------- /Topic 1. Multiple-cycle CPU Design/new_alu_test.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | //////////////////////////////////////////////////////////////////////////////// 4 | // Company: 5 | // Engineer: 6 | // 7 | // Create Date: 20:25:30 03/11/2014 8 | // Design Name: alu 9 | // Module Name: C:/Users/Student/Desktop/arch_frame/new_alu_test.v 10 | // Project Name: arch_frame 11 | // Target Device: 12 | // Tool versions: 13 | // Description: 14 | // 15 | // Verilog Test Fixture created by ISE for module: alu 16 | // 17 | // Dependencies: 18 | // 19 | // Revision: 20 | // Revision 0.01 - File Created 21 | // Additional Comments: 22 | // 23 | //////////////////////////////////////////////////////////////////////////////// 24 | 25 | module new_alu_test; 26 | 27 | // Inputs 28 | reg [31:0] A; 29 | reg [31:0] B; 30 | reg [2:0] control; 31 | 32 | // Outputs 33 | wire [31:0] result; 34 | 35 | // Instantiate the Unit Under Test (UUT) 36 | alu uut ( 37 | .A(A), 38 | .B(B), 39 | .control(control), 40 | .result(result) 41 | ); 42 | 43 | initial begin 44 | // Initialize Inputs 45 | A = 0; 46 | B = 0; 47 | control = 0; 48 | 49 | // Wait 100 ns for global reset to finish 50 | #100; 51 | A = 32'd123123; 52 | B = 32'd234234; 53 | control = 3'b000; // add 54 | 55 | #100; 56 | A = 32'd123123; 57 | B = 32'd234234; 58 | control = 3'b001; // sub 59 | 60 | #100; 61 | A = 32'h0101; 62 | B = 32'h1010; 63 | control = 3'b010; // nor 64 | 65 | #100; 66 | A = 32'hABCD; 67 | B = 32'hEFAB; 68 | control = 3'b011; // and 69 | 70 | #100; 71 | A = 32'd123123; 72 | B = 32'd322325; 73 | control = 3'b111; // slt 74 | // Add stimulus here 75 | 76 | end 77 | 78 | endmodule 79 | 80 | -------------------------------------------------------------------------------- /Topic 1. Multiple-cycle CPU Design/pbdebounce.v: -------------------------------------------------------------------------------- 1 | // Basys Board and Spartan-3E Starter Boards 2 | // Push Button Debounce pbdebounce.v 3 | 4 | module pbdebounce(input clk, input button, output reg pbreg); 5 | 6 | reg [3:0] pbshift; 7 | 8 | always@(posedge clk) 9 | begin 10 | pbshift=pbshift<<1; 11 | pbshift[0]=button; 12 | if (pbshift==0) 13 | pbreg=0; 14 | if (pbshift==15) 15 | pbreg=1; 16 | end 17 | 18 | endmodule 19 | 20 | -------------------------------------------------------------------------------- /Topic 1. Multiple-cycle CPU Design/top.bit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nblintao/Computer-Architecture/bfc2989655e46618f375dabcfc43c1977ed27409/Topic 1. Multiple-cycle CPU Design/top.bit -------------------------------------------------------------------------------- /Topic 1. Multiple-cycle CPU Design/top.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nblintao/Computer-Architecture/bfc2989655e46618f375dabcfc43c1977ed27409/Topic 1. Multiple-cycle CPU Design/top.v -------------------------------------------------------------------------------- /Topic 2. Pipelined CPU with stall/alu.v: -------------------------------------------------------------------------------- 1 | `include "define.vh" 2 | 3 | /** 4 | * Arithmetic and Logic Unit for MIPS CPU. 5 | * Author: Zhao, Hongyu, Zhejiang University 6 | */ 7 | 8 | module alu ( 9 | input wire [31:0] inst, // instruction 10 | input wire [31:0] a, b, // two operands 11 | input wire [3:0] oper, // operation type 12 | output reg [31:0] result // calculation result 13 | ); 14 | 15 | `include "mips_define.vh" 16 | 17 | /*reg adder_mode; 18 | wire [31:0] adder_result; 19 | 20 | adder ADDER ( 21 | .a(a), 22 | .b(b), 23 | .mode(adder_mode), 24 | .result(adder_result) 25 | );*/ 26 | 27 | always @(*) begin 28 | //adder_mode = 0; 29 | result = 0; 30 | case (oper) 31 | /*EXE_ALU_ADD: begin 32 | adder_mode = 0; 33 | result = adder_result; 34 | end 35 | EXE_ALU_SUB: begin 36 | adder_mode = 1; 37 | result = adder_result; 38 | end*/ 39 | EXE_ALU_ADD: begin 40 | result = a + b; 41 | end 42 | EXE_ALU_SUB: begin 43 | result = a - b; 44 | end 45 | EXE_ALU_AND: begin 46 | result = a & b; 47 | end 48 | EXE_ALU_OR: begin 49 | result = a | b; 50 | end 51 | EXE_ALU_XOR: begin 52 | result = a ^ b; 53 | end 54 | endcase 55 | end 56 | 57 | endmodule 58 | -------------------------------------------------------------------------------- /Topic 2. Pipelined CPU with stall/anti_jitter.v: -------------------------------------------------------------------------------- 1 | `include "define.vh" 2 | 3 | /** 4 | * Anti-jitter for input buttons and switches on board. 5 | * Author: Zhao, Hongyu, Zhejiang University 6 | */ 7 | 8 | module anti_jitter ( 9 | input wire clk, // main clock 10 | input wire rst, // synchronous reset 11 | input wire sig_i, // input signal with jitter noises 12 | output wire sig_o // output signal without jitter noises 13 | ); 14 | 15 | parameter 16 | CLK_FREQ = 100, // main clock frequency in MHz 17 | JITTER_MAX = 10000; // longest time for jitter noises in us 18 | parameter 19 | INIT_VALUE = 0; // initialized output value 20 | localparam 21 | CLK_COUNT = CLK_FREQ * JITTER_MAX; // CLK_FREQ * 1000000 / (1000000 / JITTER_MAX) 22 | 23 | reg [31:0] clk_count = 0; 24 | reg buff = INIT_VALUE; 25 | 26 | always @(posedge clk) begin 27 | if (rst) begin 28 | clk_count <= 0; 29 | buff <= INIT_VALUE; 30 | end 31 | else if (sig_i == sig_o) begin 32 | clk_count <= 0; 33 | end 34 | else if (clk_count == CLK_COUNT-1) begin 35 | clk_count <= 0; 36 | buff <= sig_i; 37 | end 38 | else begin 39 | clk_count <= clk_count + 1'h1; 40 | end 41 | end 42 | 43 | assign sig_o = buff; 44 | 45 | endmodule 46 | -------------------------------------------------------------------------------- /Topic 2. Pipelined CPU with stall/clk_gen.v: -------------------------------------------------------------------------------- 1 | `include "define.vh" 2 | 3 | /** 4 | * Clock generator. 5 | * Author: Zhao, Hongyu, Zhejiang University 6 | */ 7 | 8 | module clk_gen ( 9 | input wire clk_pad, // input clock, 50MHz 10 | output wire clk_100m, 11 | output wire clk_50m, 12 | output wire clk_25m, 13 | output wire clk_10m, 14 | output wire locked 15 | ); 16 | 17 | wire clk_pad_buf; 18 | wire clk_100m_unbuf; 19 | wire clk_50m_unbuf; 20 | wire clk_25m_unbuf; 21 | wire clk_10m_unbuf; 22 | 23 | //IBUFG CLK_PAD_BUF (.I(clk_pad), .O(clk_pad_buf)); 24 | assign clk_pad_buf = clk_pad; 25 | 26 | DCM_SP #( 27 | .CLKDV_DIVIDE(2), 28 | .CLKFX_DIVIDE(10), 29 | .CLKFX_MULTIPLY(2), 30 | .CLKIN_DIVIDE_BY_2("FALSE"), 31 | .CLKIN_PERIOD(10.0), 32 | .CLK_FEEDBACK("2X"), 33 | .CLKOUT_PHASE_SHIFT("NONE"), 34 | .PHASE_SHIFT(0), 35 | .DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), 36 | .STARTUP_WAIT("TRUE") 37 | ) DCM_SYS ( 38 | .CLKIN(clk_pad_buf), 39 | .CLKFB(clk_100m), 40 | .RST(1'b0), 41 | .CLK0(clk_50m_unbuf), 42 | .CLK90(), 43 | .CLK180(), 44 | .CLK270(), 45 | .CLK2X(clk_100m_unbuf), 46 | .CLK2X180(), 47 | .CLKDV(clk_25m_unbuf), 48 | .CLKFX(clk_10m_unbuf), 49 | .CLKFX180(), 50 | .LOCKED(locked), 51 | .STATUS(), 52 | .DSSEN(1'b0), 53 | .PSCLK(1'b0), 54 | .PSEN(1'b0), 55 | .PSINCDEC(1'b0), 56 | .PSDONE() 57 | ); 58 | 59 | BUFG 60 | CLK_BUF_100M (.I(clk_100m_unbuf), .O(clk_100m)), 61 | CLK_BUF_50M (.I(clk_50m_unbuf), .O(clk_50m)), 62 | CLK_BUF_25M (.I(clk_25m_unbuf), .O(clk_25m)), 63 | CLK_BUF_10M (.I(clk_10m_unbuf), .O(clk_10m)); 64 | 65 | endmodule 66 | -------------------------------------------------------------------------------- /Topic 2. Pipelined CPU with stall/controller.v: -------------------------------------------------------------------------------- 1 | `include "define.vh" 2 | 3 | /** 4 | * Controller for MIPS 5-stage pipelined CPU. 5 | * Author: Zhao, Hongyu, Zhejiang University 6 | */ 7 | 8 | module controller (/*AUTOARG*/ 9 | input wire clk, // main clock 10 | input wire rst, // synchronous reset 11 | // debug 12 | `ifdef DEBUG 13 | input wire debug_en, // debug enable 14 | input wire debug_step, // debug step clock 15 | `endif 16 | // instruction decode 17 | input wire [31:0] inst, // instruction 18 | output reg imm_ext, // whether using sign extended to immediate data 19 | output reg exe_b_src, // data source of operand B for ALU 20 | output reg [3:0] exe_alu_oper, // ALU operation type 21 | output reg mem_ren, // memory read enable signal 22 | output reg mem_wen, // memory write enable signal 23 | output reg wb_addr_src, // address source to write data back to registers 24 | output reg wb_data_src, // data source of data being written back to registers 25 | output reg wb_wen, // register write enable signal 26 | output reg is_branch, // whether current instruction is a branch instruction 27 | output reg rs_used, // whether RS is used 28 | output reg rt_used, // whether RT is used 29 | output reg unrecognized, // whether current instruction can not be recognized 30 | // pipeline control 31 | input wire reg_stall, // stall signal when LW instruction followed by an related R instruction 32 | output reg if_rst, // stage reset signal 33 | output reg if_en, // stage enable signal 34 | input wire if_valid, // stage valid flag 35 | output reg id_rst, 36 | output reg id_en, 37 | input wire id_valid, 38 | output reg exe_rst, 39 | output reg exe_en, 40 | input wire exe_valid, 41 | output reg mem_rst, 42 | output reg mem_en, 43 | input wire mem_valid, 44 | output reg wb_rst, 45 | output reg wb_en, 46 | input wire wb_valid 47 | ); 48 | 49 | `include "mips_define.vh" 50 | 51 | // instruction decode 52 | always @(*) begin 53 | imm_ext = 0; 54 | exe_b_src = EXE_B_RT; 55 | exe_alu_oper = EXE_ALU_ADD; 56 | mem_ren = 0; 57 | mem_wen = 0; 58 | wb_addr_src = WB_ADDR_RD; 59 | wb_data_src = WB_DATA_ALU; 60 | wb_wen = 0; 61 | is_branch = 0; 62 | rs_used = 0; 63 | rt_used = 0; 64 | unrecognized = 0; 65 | case (inst[31:26]) 66 | INST_R: begin 67 | case (inst[5:0]) 68 | R_FUNC_ADD: begin 69 | exe_alu_oper = EXE_ALU_ADD; 70 | wb_addr_src = WB_ADDR_RD; 71 | wb_data_src = WB_DATA_ALU; 72 | wb_wen = 1; 73 | rs_used = 1; 74 | rt_used = 1; 75 | end 76 | R_FUNC_SUB: begin 77 | exe_alu_oper = EXE_ALU_SUB; //? 78 | wb_addr_src = WB_ADDR_RD; //? 79 | wb_data_src = WB_DATA_ALU; //? 80 | wb_wen = 1; //? 81 | rs_used = 1; //? 82 | rt_used = 1; //? 83 | end 84 | R_FUNC_AND: begin 85 | exe_alu_oper = EXE_ALU_AND; 86 | wb_addr_src = WB_ADDR_RD; 87 | wb_data_src = WB_DATA_ALU; 88 | wb_wen = 1; 89 | rs_used = 1; 90 | rt_used = 1; 91 | end 92 | R_FUNC_OR: begin 93 | exe_alu_oper = EXE_ALU_OR; //? 94 | wb_addr_src = WB_ADDR_RD; //? 95 | wb_data_src = WB_DATA_ALU; //? 96 | wb_wen = 1; 97 | rs_used = 1; 98 | rt_used = 1; 99 | end 100 | R_FUNC_XOR: begin 101 | exe_alu_oper = EXE_ALU_XOR; 102 | wb_addr_src = WB_ADDR_RD; 103 | wb_data_src = WB_DATA_ALU; 104 | wb_wen = 1; 105 | rs_used = 1; 106 | rt_used = 1; 107 | end 108 | default: begin 109 | unrecognized = 1; 110 | end 111 | endcase 112 | end 113 | INST_BEQ: begin 114 | exe_b_src = EXE_B_IMM; //? 115 | imm_ext = 1; //? 116 | is_branch = 1; //? 117 | rs_used = 1; //? zyh not sure 118 | rt_used = 0; //? zyh not sure 119 | end 120 | INST_LW: begin 121 | imm_ext = 1; 122 | exe_b_src = EXE_B_IMM; 123 | exe_alu_oper = EXE_ALU_ADD; 124 | mem_ren = 1; 125 | wb_addr_src = WB_ADDR_RT; 126 | wb_data_src = WB_DATA_MEM; 127 | wb_wen = 1; 128 | rs_used = 1; 129 | end 130 | INST_SW: begin 131 | imm_ext = 1; //? 132 | exe_b_src = EXE_B_IMM; //? 133 | exe_alu_oper = EXE_ALU_ADD; //? 134 | mem_wen = 1; //? 135 | rs_used = 1; //? 136 | rt_used = 1; //? 137 | end 138 | default: begin 139 | unrecognized = 1; 140 | end 141 | endcase 142 | end 143 | 144 | // pipeline control 145 | `ifdef DEBUG 146 | reg debug_step_prev; 147 | 148 | always @(posedge clk) begin 149 | debug_step_prev <= debug_step; 150 | end 151 | `endif 152 | 153 | always @(*) begin 154 | if_rst = 0; 155 | if_en = 1; 156 | id_rst = 0; 157 | id_en = 1; 158 | exe_rst = 0; 159 | exe_en = 1; 160 | mem_rst = 0; 161 | mem_en = 1; 162 | wb_rst = 0; 163 | wb_en = 1; 164 | if (rst) begin 165 | if_rst = 1; 166 | id_rst = 1; 167 | exe_rst = 1; 168 | mem_rst = 1; 169 | wb_rst = 1; 170 | end 171 | `ifdef DEBUG 172 | // suspend and step execution 173 | else if ((debug_en) && ~(~debug_step_prev && debug_step)) begin 174 | if_en = 0; 175 | id_en = 0; 176 | exe_en = 0; 177 | mem_en = 0; 178 | wb_en = 0; 179 | end 180 | `endif 181 | // this stall indicate that ID is waiting for previous LW instruction, insert one NOP between ID and EXE. 182 | else if (reg_stall) begin 183 | if_en = 0; 184 | id_en = 0; 185 | exe_rst = 1; 186 | end 187 | end 188 | 189 | endmodule 190 | -------------------------------------------------------------------------------- /Topic 2. Pipelined CPU with stall/data_mem.hex: -------------------------------------------------------------------------------- 1 | 00000000 2 | 00000000 3 | 00000000 4 | 00000000 5 | 00000000 6 | 00000000 7 | 00000000 8 | 00000000 9 | 00000000 10 | 00000000 11 | 00000000 12 | 00000000 13 | 00000000 14 | 00000000 15 | 00000000 16 | 00000000 17 | 00000000 18 | 00000000 19 | 00000000 20 | beef0000 21 | 0000beef 22 | 00000000 23 | 00000000 24 | 00000000 25 | 00000000 26 | 00000000 27 | 00000000 28 | 00000000 29 | 00000000 30 | 00000000 31 | 00000000 32 | 00000000 33 | -------------------------------------------------------------------------------- /Topic 2. Pipelined CPU with stall/data_ram.v: -------------------------------------------------------------------------------- 1 | module data_ram ( 2 | input wire clk, 3 | input wire [31:0] addr, 4 | input wire we, 5 | input wire [31:0] din, 6 | output reg [31:0] dout 7 | ); 8 | 9 | parameter 10 | ADDR_WIDTH = 5; 11 | 12 | reg [31:0] data_mem [0:(1<> a; 68 | end 69 | EXE_ALU_SRA: begin 70 | result = $signed(b) >>> a; 71 | end 72 | EXE_ALU_SLLV: begin 73 | result = b << a; 74 | end 75 | EXE_ALU_SRLV: begin 76 | result = b >> a; 77 | end 78 | EXE_ALU_SRAV: begin 79 | result = b >>> a; 80 | end 81 | EXE_ALU_SLTU:begin 82 | result = {b[15:0],16'b0}; 83 | end 84 | endcase 85 | end 86 | 87 | endmodule 88 | -------------------------------------------------------------------------------- /Topic 5. Pipelined CPU support 31 MIPS Instructions.pdf/anti_jitter.v: -------------------------------------------------------------------------------- 1 | `include "define.vh" 2 | 3 | /** 4 | * Anti-jitter for input buttons and switches on board. 5 | * Author: Zhao, Hongyu, Zhejiang University 6 | */ 7 | 8 | module anti_jitter ( 9 | input wire clk, // main clock 10 | input wire rst, // synchronous reset 11 | input wire sig_i, // input signal with jitter noises 12 | output wire sig_o // output signal without jitter noises 13 | ); 14 | 15 | parameter 16 | CLK_FREQ = 100, // main clock frequency in MHz 17 | JITTER_MAX = 10000; // longest time for jitter noises in us 18 | parameter 19 | INIT_VALUE = 0; // initialized output value 20 | localparam 21 | CLK_COUNT = CLK_FREQ * JITTER_MAX; // CLK_FREQ * 1000000 / (1000000 / JITTER_MAX) 22 | 23 | reg [31:0] clk_count = 0; 24 | reg buff = INIT_VALUE; 25 | 26 | always @(posedge clk) begin 27 | if (rst) begin 28 | clk_count <= 0; 29 | buff <= INIT_VALUE; 30 | end 31 | else if (sig_i == sig_o) begin 32 | clk_count <= 0; 33 | end 34 | else if (clk_count == CLK_COUNT-1) begin 35 | clk_count <= 0; 36 | buff <= sig_i; 37 | end 38 | else begin 39 | clk_count <= clk_count + 1'h1; 40 | end 41 | end 42 | 43 | assign sig_o = buff; 44 | 45 | endmodule 46 | -------------------------------------------------------------------------------- /Topic 5. Pipelined CPU support 31 MIPS Instructions.pdf/clk_gen.v: -------------------------------------------------------------------------------- 1 | `include "define.vh" 2 | 3 | /** 4 | * Clock generator. 5 | * Author: Zhao, Hongyu, Zhejiang University 6 | */ 7 | 8 | module clk_gen ( 9 | input wire clk_pad, // input clock, 50MHz 10 | output wire clk_100m, 11 | output wire clk_50m, 12 | output wire clk_25m, 13 | output wire clk_10m, 14 | output wire locked 15 | ); 16 | 17 | wire clk_pad_buf; 18 | wire clk_100m_unbuf; 19 | wire clk_50m_unbuf; 20 | wire clk_25m_unbuf; 21 | wire clk_10m_unbuf; 22 | 23 | //IBUFG CLK_PAD_BUF (.I(clk_pad), .O(clk_pad_buf)); 24 | assign clk_pad_buf = clk_pad; 25 | 26 | DCM_SP #( 27 | .CLKDV_DIVIDE(2), 28 | .CLKFX_DIVIDE(10), 29 | .CLKFX_MULTIPLY(2), 30 | .CLKIN_DIVIDE_BY_2("FALSE"), 31 | .CLKIN_PERIOD(10.0), 32 | .CLK_FEEDBACK("2X"), 33 | .CLKOUT_PHASE_SHIFT("NONE"), 34 | .PHASE_SHIFT(0), 35 | .DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), 36 | .STARTUP_WAIT("TRUE") 37 | ) DCM_SYS ( 38 | .CLKIN(clk_pad_buf), 39 | .CLKFB(clk_100m), 40 | .RST(1'b0), 41 | .CLK0(clk_50m_unbuf), 42 | .CLK90(), 43 | .CLK180(), 44 | .CLK270(), 45 | .CLK2X(clk_100m_unbuf), 46 | .CLK2X180(), 47 | .CLKDV(clk_25m_unbuf), 48 | .CLKFX(clk_10m_unbuf), 49 | .CLKFX180(), 50 | .LOCKED(locked), 51 | .STATUS(), 52 | .DSSEN(1'b0), 53 | .PSCLK(1'b0), 54 | .PSEN(1'b0), 55 | .PSINCDEC(1'b0), 56 | .PSDONE() 57 | ); 58 | 59 | BUFG 60 | CLK_BUF_100M (.I(clk_100m_unbuf), .O(clk_100m)), 61 | CLK_BUF_50M (.I(clk_50m_unbuf), .O(clk_50m)), 62 | CLK_BUF_25M (.I(clk_25m_unbuf), .O(clk_25m)), 63 | CLK_BUF_10M (.I(clk_10m_unbuf), .O(clk_10m)); 64 | 65 | endmodule 66 | -------------------------------------------------------------------------------- /Topic 5. Pipelined CPU support 31 MIPS Instructions.pdf/data_mem.hex: -------------------------------------------------------------------------------- 1 | BF800000 2 | 00000000 3 | 00000000 4 | 00000000 5 | 00000000 6 | 00000000 7 | 00000000 8 | 00000000 9 | 00000000 10 | 00000000 11 | 00000000 12 | 00000000 13 | 00000000 14 | 00000000 15 | 00000000 16 | 00000000 17 | 00000000 18 | 00000000 19 | 00000000 20 | 00000000 21 | 000000A3 22 | 00000027 23 | 00000079 24 | 00000115 25 | 00000000 26 | 00000000 27 | 00000000 28 | 00000000 29 | 00000000 30 | 00000000 31 | 00000000 32 | 00000000 -------------------------------------------------------------------------------- /Topic 5. Pipelined CPU support 31 MIPS Instructions.pdf/data_ram.v: -------------------------------------------------------------------------------- 1 | module data_ram ( 2 | input wire clk, 3 | input wire [31:0] addr, 4 | input wire we, 5 | input wire [31:0] din, 6 | output reg [31:0] dout 7 | ); 8 | 9 | parameter 10 | ADDR_WIDTH = 5; 11 | 12 | reg [31:0] data_mem [0:(1<> a; 77 | end 78 | EXE_ALU_SRA: begin 79 | result = $signed(b) >>> a; 80 | end 81 | /*EXE_ALU_SLLV: begin 82 | result = b << a; 83 | end 84 | EXE_ALU_SRLV: begin 85 | result = b >> a; 86 | end 87 | EXE_ALU_SRAV: begin 88 | result = $signed(b) >>> a; 89 | end*/ 90 | EXE_ALU_B:begin 91 | result = b; 92 | end 93 | 94 | endcase 95 | end 96 | 97 | endmodule 98 | -------------------------------------------------------------------------------- /Topic 6. Pipelined CPU supporting interrupt/anti_jitter.v: -------------------------------------------------------------------------------- 1 | `include "define.vh" 2 | 3 | /** 4 | * Anti-jitter for input buttons and switches on board. 5 | * Author: Zhao, Hongyu, Zhejiang University 6 | */ 7 | 8 | module anti_jitter ( 9 | input wire clk, // main clock 10 | input wire rst, // synchronous reset 11 | input wire sig_i, // input signal with jitter noises 12 | output wire sig_o // output signal without jitter noises 13 | ); 14 | 15 | parameter 16 | CLK_FREQ = 100, // main clock frequency in MHz 17 | JITTER_MAX = 10000; // longest time for jitter noises in us 18 | parameter 19 | INIT_VALUE = 0; // initialized output value 20 | localparam 21 | CLK_COUNT = CLK_FREQ * JITTER_MAX; // CLK_FREQ * 1000000 / (1000000 / JITTER_MAX) 22 | 23 | reg [31:0] clk_count = 0; 24 | reg buff = INIT_VALUE; 25 | 26 | always @(posedge clk) begin 27 | if (rst) begin 28 | clk_count <= 0; 29 | buff <= INIT_VALUE; 30 | end 31 | else if (sig_i == sig_o) begin 32 | clk_count <= 0; 33 | end 34 | else if (clk_count == CLK_COUNT-1) begin 35 | clk_count <= 0; 36 | buff <= sig_i; 37 | end 38 | else begin 39 | clk_count <= clk_count + 1'h1; 40 | end 41 | end 42 | 43 | assign sig_o = buff; 44 | 45 | endmodule 46 | -------------------------------------------------------------------------------- /Topic 6. Pipelined CPU supporting interrupt/clk_gen.v: -------------------------------------------------------------------------------- 1 | `include "define.vh" 2 | 3 | /** 4 | * Clock generator. 5 | * Author: Zhao, Hongyu, Zhejiang University 6 | */ 7 | 8 | module clk_gen ( 9 | input wire clk_pad, // input clock, 50MHz 10 | output wire clk_100m, 11 | output wire clk_50m, 12 | output wire clk_25m, 13 | output wire clk_10m, 14 | output wire locked 15 | ); 16 | 17 | wire clk_pad_buf; 18 | wire clk_100m_unbuf; 19 | wire clk_50m_unbuf; 20 | wire clk_25m_unbuf; 21 | wire clk_10m_unbuf; 22 | 23 | //IBUFG CLK_PAD_BUF (.I(clk_pad), .O(clk_pad_buf)); 24 | assign clk_pad_buf = clk_pad; 25 | 26 | DCM_SP #( 27 | .CLKDV_DIVIDE(2), 28 | .CLKFX_DIVIDE(10), 29 | .CLKFX_MULTIPLY(2), 30 | .CLKIN_DIVIDE_BY_2("FALSE"), 31 | .CLKIN_PERIOD(10.0), 32 | .CLK_FEEDBACK("2X"), 33 | .CLKOUT_PHASE_SHIFT("NONE"), 34 | .PHASE_SHIFT(0), 35 | .DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), 36 | .STARTUP_WAIT("TRUE") 37 | ) DCM_SYS ( 38 | .CLKIN(clk_pad_buf), 39 | .CLKFB(clk_100m), 40 | .RST(1'b0), 41 | .CLK0(clk_50m_unbuf), 42 | .CLK90(), 43 | .CLK180(), 44 | .CLK270(), 45 | .CLK2X(clk_100m_unbuf), 46 | .CLK2X180(), 47 | .CLKDV(clk_25m_unbuf), 48 | .CLKFX(clk_10m_unbuf), 49 | .CLKFX180(), 50 | .LOCKED(locked), 51 | .STATUS(), 52 | .DSSEN(1'b0), 53 | .PSCLK(1'b0), 54 | .PSEN(1'b0), 55 | .PSINCDEC(1'b0), 56 | .PSDONE() 57 | ); 58 | 59 | BUFG 60 | CLK_BUF_100M (.I(clk_100m_unbuf), .O(clk_100m)), 61 | CLK_BUF_50M (.I(clk_50m_unbuf), .O(clk_50m)), 62 | CLK_BUF_25M (.I(clk_25m_unbuf), .O(clk_25m)), 63 | CLK_BUF_10M (.I(clk_10m_unbuf), .O(clk_10m)); 64 | 65 | endmodule 66 | -------------------------------------------------------------------------------- /Topic 6. Pipelined CPU supporting interrupt/cp0.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 17:04:34 05/26/2015 7 | // Design Name: 8 | // Module Name: cp0 9 | // Project Name: 10 | // Target Devices: 11 | // Tool versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | `include "define.vh" 22 | module cp0( 23 | input wire clk, // main clock 24 | // debug 25 | `ifdef DEBUG 26 | input wire [4:0] debug_addr, // debug address 27 | output reg [31:0] debug_data, // debug data 28 | `endif 29 | // operations (read in ID stage and write in EXE stage) 30 | input wire [1:0] oper, // CP0 operation type 31 | input wire [4:0] addr_r, // read address 32 | output reg [31:0] data_r, // read data 33 | input wire [4:0] addr_w, // write address 34 | input wire [31:0] data_w, // write data 35 | // control signal 36 | input wire rst, // synchronous reset 37 | input wire ir_en, // interrupt enable 38 | input wire ir_in, // external interrupt input 39 | input wire [31:0] ret_addr, // target instruction address to store when interrupt occurred 40 | output wire jump_en, // force jump enable signal when interrupt authorised or ERET occurred 41 | output reg [31:0] jump_addr // target instruction address to jump to 42 | ); 43 | `include "mips_define.vh" 44 | // interrupt determination 45 | wire ir; 46 | reg ir_wait = 0, ir_valid = 1; 47 | reg eret = 0; 48 | reg [31:0] EHBR; 49 | reg [31:0] EPCR; 50 | initial begin 51 | EHBR = 0; 52 | EPCR = 0; 53 | end 54 | always @(posedge clk) begin 55 | if (rst) 56 | ir_wait <= 0; 57 | else if (ir_in) 58 | ir_wait <= 1; 59 | else if (eret) 60 | ir_wait <= 0; 61 | end 62 | always @(posedge clk) begin 63 | if (rst) 64 | ir_valid <= 1; 65 | else if (eret) 66 | ir_valid <= 1; 67 | else if (ir) 68 | ir_valid <= 0; // prevent exception reenter 69 | end 70 | assign ir = ir_en & ir_wait & ir_valid; 71 | 72 | assign jump_en = ir||eret; 73 | /*always @(posedge clk) begin 74 | jump_en <= 0; 75 | if (ir||eret) 76 | jump_en <= 1; 77 | end*/ 78 | 79 | 80 | always @(*) begin 81 | eret <= 0; 82 | jump_addr <= 0; 83 | if(ir)begin 84 | jump_addr <= EHBR; 85 | end 86 | else begin 87 | case(oper) 88 | EXE_CP_NONE: begin //MFC0 89 | case(addr_r) 90 | CP0_EPCR: data_r <= EPCR; 91 | CP0_EHBR: data_r <= EHBR; 92 | default: data_r <= 0; 93 | endcase 94 | end 95 | /*EXE_CP_STORE: begin //MTC0 96 | case(addr_w) 97 | CP0_EPCR: EPCR <= data_w; 98 | CP0_EHBR: EHBR <= data_w; 99 | default: ; 100 | endcase 101 | end*/ 102 | EXE_CP0_ERET: begin //ERET 103 | eret <= 1; 104 | jump_addr <= EPCR; 105 | end 106 | default:; 107 | endcase 108 | end 109 | end 110 | 111 | always @(posedge clk) begin 112 | 113 | if(ir)begin 114 | EPCR <= ret_addr; 115 | end 116 | else begin 117 | case(oper) 118 | EXE_CP_STORE: begin //MTC0 119 | case(addr_w) 120 | CP0_EPCR: EPCR <= data_w; 121 | CP0_EHBR: EHBR <= data_w; 122 | default: ; 123 | endcase 124 | end 125 | endcase 126 | end 127 | end 128 | 129 | 130 | endmodule 131 | -------------------------------------------------------------------------------- /Topic 6. Pipelined CPU supporting interrupt/data_mem.hex: -------------------------------------------------------------------------------- 1 | BF800000 2 | 00000000 3 | 00000000 4 | 00000000 5 | 00000000 6 | 00000000 7 | 00000000 8 | 00000000 9 | 00000000 10 | 00000000 11 | 00000000 12 | 00000000 13 | 00000000 14 | 00000000 15 | 00000000 16 | 00000000 17 | 00000000 18 | 00000000 19 | 00000000 20 | 00000000 21 | 000000A3 22 | 00000027 23 | 00000079 24 | 00000115 25 | 00000000 26 | 00000000 27 | 00000000 28 | 00000000 29 | 00000000 30 | 00000000 31 | 00000000 32 | 00000000 33 | -------------------------------------------------------------------------------- /Topic 6. Pipelined CPU supporting interrupt/data_ram.v: -------------------------------------------------------------------------------- 1 | module data_ram ( 2 | input wire clk, 3 | input wire [31:0] addr, 4 | input wire we, 5 | input wire [31:0] din, 6 | output reg [31:0] dout 7 | ); 8 | 9 | parameter 10 | ADDR_WIDTH = 5; 11 | 12 | reg [31:0] data_mem [0:(1<> a; 77 | end 78 | EXE_ALU_SRA: begin 79 | result = $signed(b) >>> a; 80 | end 81 | /*EXE_ALU_SLLV: begin 82 | result = b << a; 83 | end 84 | EXE_ALU_SRLV: begin 85 | result = b >> a; 86 | end 87 | EXE_ALU_SRAV: begin 88 | result = $signed(b) >>> a; 89 | end*/ 90 | EXE_ALU_B:begin 91 | result = b; 92 | end 93 | 94 | endcase 95 | end 96 | 97 | endmodule 98 | -------------------------------------------------------------------------------- /Topic 7. Cache Line Design/anti_jitter.v: -------------------------------------------------------------------------------- 1 | `include "define.vh" 2 | 3 | /** 4 | * Anti-jitter for input buttons and switches on board. 5 | * Author: Zhao, Hongyu, Zhejiang University 6 | */ 7 | 8 | module anti_jitter ( 9 | input wire clk, // main clock 10 | input wire rst, // synchronous reset 11 | input wire sig_i, // input signal with jitter noises 12 | output wire sig_o // output signal without jitter noises 13 | ); 14 | 15 | parameter 16 | CLK_FREQ = 100, // main clock frequency in MHz 17 | JITTER_MAX = 10000; // longest time for jitter noises in us 18 | parameter 19 | INIT_VALUE = 0; // initialized output value 20 | localparam 21 | CLK_COUNT = CLK_FREQ * JITTER_MAX; // CLK_FREQ * 1000000 / (1000000 / JITTER_MAX) 22 | 23 | reg [31:0] clk_count = 0; 24 | reg buff = INIT_VALUE; 25 | 26 | always @(posedge clk) begin 27 | if (rst) begin 28 | clk_count <= 0; 29 | buff <= INIT_VALUE; 30 | end 31 | else if (sig_i == sig_o) begin 32 | clk_count <= 0; 33 | end 34 | else if (clk_count == CLK_COUNT-1) begin 35 | clk_count <= 0; 36 | buff <= sig_i; 37 | end 38 | else begin 39 | clk_count <= clk_count + 1'h1; 40 | end 41 | end 42 | 43 | assign sig_o = buff; 44 | 45 | endmodule 46 | -------------------------------------------------------------------------------- /Topic 7. Cache Line Design/cache_line.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | `include "mips_define.vh" 3 | ////////////////////////////////////////////////////////////////////////////////// 4 | // Company: 5 | // Engineer: 6 | // 7 | // Create Date: 14:22:47 06/15/2015 8 | // Design Name: 9 | // Module Name: cache_line 10 | // Project Name: 11 | // Target Devices: 12 | // Tool versions: 13 | // Description: 14 | // 15 | // Dependencies: 16 | // 17 | // Revision: 18 | // Revision 0.01 - File Created 19 | // Additional Comments: 20 | // 21 | ////////////////////////////////////////////////////////////////////////////////// 22 | module cache_line( 23 | input wire clk, 24 | input wire rst, 25 | input wire [31:0] addr, 26 | input wire load, 27 | input wire edit, 28 | input wire invalid, 29 | input wire [31:0] din, 30 | output reg hit, 31 | output reg [31:0] dout, 32 | output reg valid, 33 | output reg dirty, 34 | output reg [21:0] tag 35 | ); 36 | reg [LINE_NUM-1:0] inner_valid = 0; 37 | reg [LINE_NUM-1:0] inner_dirty = 0; 38 | reg [LINE_NUM-1:0] inner_tag [0:LINE_NUM-1]; 39 | reg [WORD_BITS-1:0] inner_data [0:LINE_NUM*LINE_WORDS-1]; 40 | 41 | always @(posedge clk) begin 42 | dout <= inner_data[addr[ADDR_BITS-TAG_BITS-1:WORD_BYTES_WIDTH]]; 43 | if (edit&hit || load) 44 | inner_data[addr[ADDR_BITS-TAG_BITS-1:WORD_BYTES_WIDTH]] = din; 45 | 46 | if (invalid) begin 47 | inner_valid[addr[ADDR_BITS-TAG_BITS-1:LINE_WORDS_WIDTH+WORD_BYTES_WIDTH]] = 0; 48 | inner_dirty[addr[ADDR_BITS-TAG_BITS-1:LINE_WORDS_WIDTH+WORD_BYTES_WIDTH]] = 0; 49 | end 50 | 51 | if (load) begin 52 | inner_valid[addr[ADDR_BITS-TAG_BITS-1:LINE_WORDS_WIDTH+WORD_BYTES_WIDTH]] = 1; 53 | inner_dirty[addr[ADDR_BITS-TAG_BITS-1:LINE_WORDS_WIDTH+WORD_BYTES_WIDTH]] = 0; 54 | inner_tag[addr[ADDR_BITS-TAG_BITS-1:LINE_WORDS_WIDTH+WORD_BYTES_WIDTH]] = addr[ADDR_BITS-1:ADDR_BITS-TAG_BITS]; 55 | end 56 | 57 | if (edit) begin 58 | inner_dirty[addr[ADDR_BITS-TAG_BITS-1:LINE_WORDS_WIDTH+WORD_BYTES_WIDTH]] = 1; 59 | inner_tag[addr[ADDR_BITS-TAG_BITS-1:LINE_WORDS_WIDTH+WORD_BYTES_WIDTH]] = addr[ADDR_BITS-1:ADDR_BITS-TAG_BITS]; 60 | end 61 | 62 | valid = inner_valid[addr[ADDR_BITS-TAG_BITS-1:LINE_WORDS_WIDTH+WORD_BYTES_WIDTH]]; 63 | dirty = inner_dirty[addr[ADDR_BITS-TAG_BITS-1:LINE_WORDS_WIDTH+WORD_BYTES_WIDTH]]; 64 | tag = inner_tag[addr[ADDR_BITS-TAG_BITS-1:LINE_WORDS_WIDTH+WORD_BYTES_WIDTH]]; 65 | hit = valid & tag==addr[ADDR_BITS-1:ADDR_BITS-TAG_BITS]; 66 | end 67 | 68 | endmodule 69 | -------------------------------------------------------------------------------- /Topic 7. Cache Line Design/cache_tbw.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | //////////////////////////////////////////////////////////////////////////////// 4 | // Company: 5 | // Engineer: 6 | // 7 | // Create Date: 21:36:31 06/15/2015 8 | // Design Name: cache_line 9 | // Module Name: E:/___My_Work___/3rd/CA/Lab7/mips_cpu/code/cache_tbw.v 10 | // Project Name: mips_cpu 11 | // Target Device: 12 | // Tool versions: 13 | // Description: 14 | // 15 | // Verilog Test Fixture created by ISE for module: cache_line 16 | // 17 | // Dependencies: 18 | // 19 | // Revision: 20 | // Revision 0.01 - File Created 21 | // Additional Comments: 22 | // 23 | //////////////////////////////////////////////////////////////////////////////// 24 | 25 | module cache_tbw; 26 | 27 | // Inputs 28 | reg clk; 29 | reg rst; 30 | reg [31:0] addr; 31 | reg load; 32 | reg edit; 33 | reg invalid; 34 | reg [31:0] din; 35 | 36 | // Outputs 37 | wire hit; 38 | wire [31:0] dout; 39 | wire valid; 40 | wire dirty; 41 | wire [21:0] tag; 42 | 43 | // Instantiate the Unit Under Test (UUT) 44 | cache_line uut ( 45 | .clk(clk), 46 | .rst(rst), 47 | .addr(addr), 48 | .load(load), 49 | .edit(edit), 50 | .invalid(invalid), 51 | .din(din), 52 | .hit(hit), 53 | .dout(dout), 54 | .valid(valid), 55 | .dirty(dirty), 56 | .tag(tag) 57 | ); 58 | 59 | initial begin 60 | // Initialize Inputs 61 | clk = 0; 62 | rst = 0; 63 | addr = 0; 64 | load = 0; 65 | edit = 0; 66 | invalid = 0; 67 | din = 0; 68 | 69 | // Wait 100 ns for global reset to finish 70 | #100; 71 | 72 | // Add stimulus here 73 | #210 load = 1; din = 32'h11111111; addr = 32'h00000000; 74 | #20 addr = 32'h00000004; 75 | #20 addr = 32'h000000A8; 76 | #20 addr = 32'h0000001C; 77 | #20 load = 0; addr = 32'h000000B4; din = 0; 78 | #100 edit = 1; din = 32'h22222222; addr = 32'h00000008; 79 | #100 edit = 0; din = 0; addr = 0; 80 | end 81 | 82 | initial forever #10 clk = ~clk; 83 | 84 | endmodule 85 | 86 | -------------------------------------------------------------------------------- /Topic 7. Cache Line Design/clk_gen.v: -------------------------------------------------------------------------------- 1 | `include "define.vh" 2 | 3 | /** 4 | * Clock generator. 5 | * Author: Zhao, Hongyu, Zhejiang University 6 | */ 7 | 8 | module clk_gen ( 9 | input wire clk_pad, // input clock, 50MHz 10 | output wire clk_100m, 11 | output wire clk_50m, 12 | output wire clk_25m, 13 | output wire clk_10m, 14 | output wire locked 15 | ); 16 | 17 | wire clk_pad_buf; 18 | wire clk_100m_unbuf; 19 | wire clk_50m_unbuf; 20 | wire clk_25m_unbuf; 21 | wire clk_10m_unbuf; 22 | 23 | //IBUFG CLK_PAD_BUF (.I(clk_pad), .O(clk_pad_buf)); 24 | assign clk_pad_buf = clk_pad; 25 | 26 | DCM_SP #( 27 | .CLKDV_DIVIDE(2), 28 | .CLKFX_DIVIDE(10), 29 | .CLKFX_MULTIPLY(2), 30 | .CLKIN_DIVIDE_BY_2("FALSE"), 31 | .CLKIN_PERIOD(10.0), 32 | .CLK_FEEDBACK("2X"), 33 | .CLKOUT_PHASE_SHIFT("NONE"), 34 | .PHASE_SHIFT(0), 35 | .DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), 36 | .STARTUP_WAIT("TRUE") 37 | ) DCM_SYS ( 38 | .CLKIN(clk_pad_buf), 39 | .CLKFB(clk_100m), 40 | .RST(1'b0), 41 | .CLK0(clk_50m_unbuf), 42 | .CLK90(), 43 | .CLK180(), 44 | .CLK270(), 45 | .CLK2X(clk_100m_unbuf), 46 | .CLK2X180(), 47 | .CLKDV(clk_25m_unbuf), 48 | .CLKFX(clk_10m_unbuf), 49 | .CLKFX180(), 50 | .LOCKED(locked), 51 | .STATUS(), 52 | .DSSEN(1'b0), 53 | .PSCLK(1'b0), 54 | .PSEN(1'b0), 55 | .PSINCDEC(1'b0), 56 | .PSDONE() 57 | ); 58 | 59 | BUFG 60 | CLK_BUF_100M (.I(clk_100m_unbuf), .O(clk_100m)), 61 | CLK_BUF_50M (.I(clk_50m_unbuf), .O(clk_50m)), 62 | CLK_BUF_25M (.I(clk_25m_unbuf), .O(clk_25m)), 63 | CLK_BUF_10M (.I(clk_10m_unbuf), .O(clk_10m)); 64 | 65 | endmodule 66 | -------------------------------------------------------------------------------- /Topic 7. Cache Line Design/cp0.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 17:04:34 05/26/2015 7 | // Design Name: 8 | // Module Name: cp0 9 | // Project Name: 10 | // Target Devices: 11 | // Tool versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | `include "define.vh" 22 | module cp0( 23 | input wire clk, // main clock 24 | // debug 25 | `ifdef DEBUG 26 | input wire [4:0] debug_addr, // debug address 27 | output reg [31:0] debug_data, // debug data 28 | `endif 29 | // operations (read in ID stage and write in EXE stage) 30 | input wire [1:0] oper, // CP0 operation type 31 | input wire [4:0] addr_r, // read address 32 | output reg [31:0] data_r, // read data 33 | input wire [4:0] addr_w, // write address 34 | input wire [31:0] data_w, // write data 35 | // control signal 36 | input wire rst, // synchronous reset 37 | input wire ir_en, // interrupt enable 38 | input wire ir_in, // external interrupt input 39 | input wire [31:0] ret_addr, // target instruction address to store when interrupt occurred 40 | output wire jump_en, // force jump enable signal when interrupt authorised or ERET occurred 41 | output reg [31:0] jump_addr // target instruction address to jump to 42 | ); 43 | `include "mips_define.vh" 44 | // interrupt determination 45 | wire ir; 46 | reg ir_wait = 0, ir_valid = 1; 47 | reg eret = 0; 48 | reg [31:0] EHBR; 49 | reg [31:0] EPCR; 50 | reg [31:0] TCR; 51 | reg eret_prv; 52 | initial begin 53 | EHBR = 0; 54 | EPCR = 0; 55 | TCR = 0; 56 | end 57 | always @(posedge clk) begin 58 | if (rst) 59 | ir_wait <= 0; 60 | else if (ir_in) 61 | ir_wait <= 1; 62 | else if (eret && ~eret_prv) 63 | ir_wait <= 0; 64 | end 65 | always @(posedge clk) begin 66 | if (rst) 67 | ir_valid <= 1; 68 | else if (eret && ~eret_prv) 69 | ir_valid <= 1; 70 | else if (ir) 71 | ir_valid <= 0; // prevent exception reenter 72 | end 73 | assign ir = ir_en & ir_wait & ir_valid; 74 | 75 | assign jump_en = ir||(eret && ~eret_prv); 76 | always @(posedge clk) begin 77 | eret_prv <= eret; 78 | end 79 | 80 | 81 | always @(*) begin 82 | eret <= 0; 83 | jump_addr <= 0; 84 | if(ir)begin 85 | jump_addr <= EHBR; 86 | end 87 | else begin 88 | case(oper) 89 | EXE_CP_NONE: begin //MFC0 90 | case(addr_r) 91 | CP0_EPCR: data_r <= EPCR; 92 | CP0_EHBR: data_r <= EHBR; 93 | CP0_TCR: data_r <= TCR; 94 | default: data_r <= 0; 95 | endcase 96 | end 97 | /*EXE_CP_STORE: begin //MTC0 98 | case(addr_w) 99 | CP0_EPCR: EPCR <= data_w; 100 | CP0_EHBR: EHBR <= data_w; 101 | default: ; 102 | endcase 103 | end*/ 104 | EXE_CP0_ERET: begin //ERET 105 | eret <= 1; 106 | jump_addr <= EPCR; 107 | end 108 | default:; 109 | endcase 110 | end 111 | end 112 | 113 | always @(posedge clk) begin 114 | TCR <= TCR + 1; 115 | if(ir)begin 116 | EPCR <= ret_addr; 117 | end 118 | else begin 119 | case(oper) 120 | EXE_CP_STORE: begin //MTC0 121 | case(addr_w) 122 | CP0_EPCR: EPCR <= data_w; 123 | CP0_EHBR: EHBR <= data_w; 124 | CP0_TCR: TCR <= data_w; 125 | default: ; 126 | endcase 127 | end 128 | endcase 129 | end 130 | end 131 | 132 | 133 | endmodule 134 | -------------------------------------------------------------------------------- /Topic 7. Cache Line Design/data_mem.hex: -------------------------------------------------------------------------------- 1 | 00000000 2 | 00000000 3 | 00000000 4 | 00000000 5 | 00000000 6 | 00000000 7 | 00000000 8 | 00000000 9 | 00000000 10 | 00000000 11 | 00000000 12 | 00000000 13 | 00000000 14 | 00000000 15 | 00000000 16 | 00000000 17 | 00000000 18 | 00000000 19 | 00000000 20 | 00000000 21 | 00000000 22 | 00000000 23 | 00000000 24 | 00000000 25 | 00000000 26 | 00000000 27 | 00000000 28 | 00000000 29 | 00000000 30 | 00000000 31 | 00000000 32 | 00000000 33 | -------------------------------------------------------------------------------- /Topic 7. Cache Line Design/data_ram.v: -------------------------------------------------------------------------------- 1 | module data_ram ( 2 | input wire clk, 3 | input wire [31:0] addr, 4 | input wire we, 5 | input wire [31:0] din, 6 | output reg [31:0] dout 7 | ); 8 | 9 | parameter 10 | ADDR_WIDTH = 5; 11 | 12 | reg [31:0] data_mem [0:(1< 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | hit 16 | hit 17 | 18 | 19 | dout[31:0] 20 | dout[31:0] 21 | HEXRADIX 22 | 23 | 24 | valid 25 | valid 26 | 27 | 28 | dirty 29 | dirty 30 | 31 | 32 | tag[21:0] 33 | tag[21:0] 34 | HEXRADIX 35 | 36 | 37 | clk 38 | clk 39 | 40 | 41 | rst 42 | rst 43 | 44 | 45 | addr[31:0] 46 | addr[31:0] 47 | HEXRADIX 48 | 49 | 50 | load 51 | load 52 | 53 | 54 | edit 55 | edit 56 | 57 | 58 | invalid 59 | invalid 60 | 61 | 62 | din[31:0] 63 | din[31:0] 64 | HEXRADIX 65 | 66 | 67 | -------------------------------------------------------------------------------- /Topic 8. Pipelined CPU with Cache/alu.v: -------------------------------------------------------------------------------- 1 | `include "define.vh" 2 | 3 | /** 4 | * Arithmetic and Logic Unit for MIPS CPU. 5 | * Author: Zhao, Hongyu, Zhejiang University 6 | */ 7 | 8 | module alu ( 9 | input wire [31:0] inst, // instruction 10 | input wire [31:0] a, b, // two operands 11 | input wire [3:0] oper, // operation type 12 | output reg [31:0] result // calculation result 13 | ); 14 | 15 | `include "mips_define.vh" 16 | 17 | /*reg adder_mode; 18 | wire [31:0] adder_result; 19 | 20 | adder ADDER ( 21 | .a(a), 22 | .b(b), 23 | .mode(adder_mode), 24 | .result(adder_result) 25 | );*/ 26 | 27 | always @(*) begin 28 | //adder_mode = 0; 29 | result = 0; 30 | case (oper) 31 | /*EXE_ALU_ADD: begin 32 | adder_mode = 0; 33 | result = adder_result; 34 | end 35 | EXE_ALU_SUB: begin 36 | adder_mode = 1; 37 | result = adder_result; 38 | end*/ 39 | EXE_ALU_ADD: begin 40 | result = $signed(a) + $signed(b); 41 | end 42 | EXE_ALU_SUB: begin 43 | result = $signed(a) - $signed(b); 44 | end 45 | EXE_ALU_ADDU: begin 46 | result = a + b; 47 | end 48 | EXE_ALU_SUBU: begin 49 | result = a - b; 50 | end 51 | EXE_ALU_AND: begin 52 | result = a & b; 53 | end 54 | EXE_ALU_OR: begin 55 | result = a | b; 56 | end 57 | EXE_ALU_XOR: begin 58 | result = a ^ b; 59 | end 60 | EXE_ALU_NOR: begin 61 | result = ~ (a | b); 62 | end 63 | EXE_ALU_SLT: begin 64 | result = ($signed(a) < $signed(b)) ? 1 : 0; 65 | end 66 | EXE_ALU_SLTU: begin 67 | result = (a < b) ? 1 : 0; 68 | end 69 | EXE_ALU_LUI: begin 70 | result = b << 16; 71 | end 72 | EXE_ALU_SLL: begin 73 | result = b << a; 74 | end 75 | EXE_ALU_SRL: begin 76 | result = b >> a; 77 | end 78 | EXE_ALU_SRA: begin 79 | result = $signed(b) >>> a; 80 | end 81 | /*EXE_ALU_SLLV: begin 82 | result = b << a; 83 | end 84 | EXE_ALU_SRLV: begin 85 | result = b >> a; 86 | end 87 | EXE_ALU_SRAV: begin 88 | result = $signed(b) >>> a; 89 | end*/ 90 | EXE_ALU_B:begin 91 | result = b; 92 | end 93 | 94 | endcase 95 | end 96 | 97 | endmodule 98 | -------------------------------------------------------------------------------- /Topic 8. Pipelined CPU with Cache/anti_jitter.v: -------------------------------------------------------------------------------- 1 | `include "define.vh" 2 | 3 | /** 4 | * Anti-jitter for input buttons and switches on board. 5 | * Author: Zhao, Hongyu, Zhejiang University 6 | */ 7 | 8 | module anti_jitter ( 9 | input wire clk, // main clock 10 | input wire rst, // synchronous reset 11 | input wire sig_i, // input signal with jitter noises 12 | output wire sig_o // output signal without jitter noises 13 | ); 14 | 15 | parameter 16 | CLK_FREQ = 100, // main clock frequency in MHz 17 | JITTER_MAX = 10000; // longest time for jitter noises in us 18 | parameter 19 | INIT_VALUE = 0; // initialized output value 20 | localparam 21 | CLK_COUNT = CLK_FREQ * JITTER_MAX; // CLK_FREQ * 1000000 / (1000000 / JITTER_MAX) 22 | 23 | reg [31:0] clk_count = 0; 24 | reg buff = INIT_VALUE; 25 | 26 | always @(posedge clk) begin 27 | if (rst) begin 28 | clk_count <= 0; 29 | buff <= INIT_VALUE; 30 | end 31 | else if (sig_i == sig_o) begin 32 | clk_count <= 0; 33 | end 34 | else if (clk_count == CLK_COUNT-1) begin 35 | clk_count <= 0; 36 | buff <= sig_i; 37 | end 38 | else begin 39 | clk_count <= clk_count + 1'h1; 40 | end 41 | end 42 | 43 | assign sig_o = buff; 44 | 45 | endmodule 46 | -------------------------------------------------------------------------------- /Topic 8. Pipelined CPU with Cache/cache_line.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | ////////////////////////////////////////////////////////////////////////////////// 4 | // Company: 5 | // Engineer: 6 | // 7 | // Create Date: 14:22:47 06/15/2015 8 | // Design Name: 9 | // Module Name: cache_line 10 | // Project Name: 11 | // Target Devices: 12 | // Tool versions: 13 | // Description: 14 | // 15 | // Dependencies: 16 | // 17 | // Revision: 18 | // Revision 0.01 - File Created 19 | // Additional Comments: 20 | // 21 | ////////////////////////////////////////////////////////////////////////////////// 22 | module cache_line( 23 | input wire clk, 24 | input wire rst, 25 | input wire [31:0] addr, 26 | input wire load, 27 | input wire edit, 28 | input wire invalid, 29 | input wire [31:0] din, 30 | output reg hit, 31 | output reg [31:0] dout, 32 | output reg valid, 33 | output reg dirty, 34 | output reg [21:0] tag 35 | ); 36 | `include "mips_define.vh" 37 | reg [LINE_NUM-1:0] inner_valid = 0; 38 | reg [LINE_NUM-1:0] inner_dirty = 0; 39 | reg [LINE_NUM-1:0] inner_tag [0:LINE_NUM-1]; 40 | reg [WORD_BITS-1:0] inner_data [0:LINE_NUM*LINE_WORDS-1]; 41 | always @(negedge clk) begin 42 | dout = inner_data[addr[ADDR_BITS-TAG_BITS-1:WORD_BYTES_WIDTH]]; 43 | valid = inner_valid[addr[ADDR_BITS-TAG_BITS-1:LINE_WORDS_WIDTH+WORD_BYTES_WIDTH]]; 44 | dirty = inner_dirty[addr[ADDR_BITS-TAG_BITS-1:LINE_WORDS_WIDTH+WORD_BYTES_WIDTH]]; 45 | tag = inner_tag[addr[ADDR_BITS-TAG_BITS-1:LINE_WORDS_WIDTH+WORD_BYTES_WIDTH]]; 46 | hit = valid & tag==addr[ADDR_BITS-1:ADDR_BITS-TAG_BITS]; 47 | end 48 | always @(posedge clk) begin 49 | 50 | if (invalid) begin 51 | inner_valid[addr[ADDR_BITS-TAG_BITS-1:LINE_WORDS_WIDTH+WORD_BYTES_WIDTH]] = 0; 52 | inner_dirty[addr[ADDR_BITS-TAG_BITS-1:LINE_WORDS_WIDTH+WORD_BYTES_WIDTH]] = 0; 53 | end 54 | 55 | if (load) begin 56 | inner_valid[addr[ADDR_BITS-TAG_BITS-1:LINE_WORDS_WIDTH+WORD_BYTES_WIDTH]] = 1; 57 | inner_dirty[addr[ADDR_BITS-TAG_BITS-1:LINE_WORDS_WIDTH+WORD_BYTES_WIDTH]] = 0; 58 | inner_tag[addr[ADDR_BITS-TAG_BITS-1:LINE_WORDS_WIDTH+WORD_BYTES_WIDTH]] = addr[ADDR_BITS-1:ADDR_BITS-TAG_BITS]; 59 | end 60 | 61 | if (edit) begin 62 | inner_dirty[addr[ADDR_BITS-TAG_BITS-1:LINE_WORDS_WIDTH+WORD_BYTES_WIDTH]] = 1; 63 | inner_tag[addr[ADDR_BITS-TAG_BITS-1:LINE_WORDS_WIDTH+WORD_BYTES_WIDTH]] = addr[ADDR_BITS-1:ADDR_BITS-TAG_BITS]; 64 | end 65 | 66 | if (edit&hit || load) 67 | inner_data[addr[ADDR_BITS-TAG_BITS-1:WORD_BYTES_WIDTH]] = din; 68 | 69 | end 70 | 71 | 72 | endmodule 73 | -------------------------------------------------------------------------------- /Topic 8. Pipelined CPU with Cache/cache_tbw.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module cache_tbw; 4 | 5 | // Inputs 6 | reg clk; 7 | reg rst; 8 | reg [31:0] addr; 9 | reg load; 10 | reg edit; 11 | reg invalid; 12 | reg [31:0] din; 13 | 14 | // Outputs 15 | wire hit; 16 | wire [31:0] dout; 17 | wire valid; 18 | wire dirty; 19 | wire [21:0] tag; 20 | 21 | // Instantiate the Unit Under Test (UUT) 22 | cache_line uut ( 23 | .clk(clk), 24 | .rst(rst), 25 | .addr(addr), 26 | .load(load), 27 | .edit(edit), 28 | .invalid(invalid), 29 | .din(din), 30 | .hit(hit), 31 | .dout(dout), 32 | .valid(valid), 33 | .dirty(dirty), 34 | .tag(tag) 35 | ); 36 | 37 | initial begin 38 | // Initialize Inputs 39 | clk = 0; 40 | rst = 0; 41 | addr = 0; 42 | load = 0; 43 | edit = 0; 44 | invalid = 0; 45 | din = 0; 46 | 47 | // Wait 100 ns for global reset to finish 48 | #100; 49 | 50 | // Add stimulus here 51 | #210 load = 1; din = 32'h11111111; addr = 32'h00000000; 52 | #20 addr = 32'h00000004; 53 | #20 addr = 32'h000000A8; 54 | #20 addr = 32'h0000001C; 55 | #20 load = 0; addr = 32'h000000B4; din = 0; 56 | #100 edit = 1; din = 32'h22222222; addr = 32'h00000008; 57 | #100 edit = 0; din = 0; addr = 0; 58 | end 59 | 60 | initial forever #10 clk = ~clk; 61 | 62 | endmodule 63 | 64 | -------------------------------------------------------------------------------- /Topic 8. Pipelined CPU with Cache/clk_gen.v: -------------------------------------------------------------------------------- 1 | `include "define.vh" 2 | 3 | /** 4 | * Clock generator. 5 | * Author: Zhao, Hongyu, Zhejiang University 6 | */ 7 | 8 | module clk_gen ( 9 | input wire clk_pad, // input clock, 50MHz 10 | output wire clk_100m, 11 | output wire clk_50m, 12 | output wire clk_25m, 13 | output wire clk_10m, 14 | output wire locked 15 | ); 16 | 17 | wire clk_pad_buf; 18 | wire clk_100m_unbuf; 19 | wire clk_50m_unbuf; 20 | wire clk_25m_unbuf; 21 | wire clk_10m_unbuf; 22 | 23 | //IBUFG CLK_PAD_BUF (.I(clk_pad), .O(clk_pad_buf)); 24 | assign clk_pad_buf = clk_pad; 25 | 26 | DCM_SP #( 27 | .CLKDV_DIVIDE(2), 28 | .CLKFX_DIVIDE(10), 29 | .CLKFX_MULTIPLY(2), 30 | .CLKIN_DIVIDE_BY_2("FALSE"), 31 | .CLKIN_PERIOD(10.0), 32 | .CLK_FEEDBACK("2X"), 33 | .CLKOUT_PHASE_SHIFT("NONE"), 34 | .PHASE_SHIFT(0), 35 | .DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), 36 | .STARTUP_WAIT("TRUE") 37 | ) DCM_SYS ( 38 | .CLKIN(clk_pad_buf), 39 | .CLKFB(clk_100m), 40 | .RST(1'b0), 41 | .CLK0(clk_50m_unbuf), 42 | .CLK90(), 43 | .CLK180(), 44 | .CLK270(), 45 | .CLK2X(clk_100m_unbuf), 46 | .CLK2X180(), 47 | .CLKDV(clk_25m_unbuf), 48 | .CLKFX(clk_10m_unbuf), 49 | .CLKFX180(), 50 | .LOCKED(locked), 51 | .STATUS(), 52 | .DSSEN(1'b0), 53 | .PSCLK(1'b0), 54 | .PSEN(1'b0), 55 | .PSINCDEC(1'b0), 56 | .PSDONE() 57 | ); 58 | 59 | BUFG 60 | CLK_BUF_100M (.I(clk_100m_unbuf), .O(clk_100m)), 61 | CLK_BUF_50M (.I(clk_50m_unbuf), .O(clk_50m)), 62 | CLK_BUF_25M (.I(clk_25m_unbuf), .O(clk_25m)), 63 | CLK_BUF_10M (.I(clk_10m_unbuf), .O(clk_10m)); 64 | 65 | endmodule 66 | -------------------------------------------------------------------------------- /Topic 8. Pipelined CPU with Cache/cmu.v: -------------------------------------------------------------------------------- 1 | module cmu( 2 | input wire clk, 3 | input wire rst, 4 | input wire [31:0] addr_rw, 5 | input wire en_r, 6 | output wire [31:0] data_r, 7 | input wire en_w, 8 | input wire [31:0] data_w, 9 | output reg stall, 10 | output reg mem_cs_o, 11 | output reg mem_we_o, 12 | output reg [31:0] mem_addr_o, 13 | input wire [31:0] mem_data_i, 14 | output reg [31:0] mem_data_o, 15 | input wire mem_ack_i 16 | // input wire [31:0] mem_data_syn, 17 | // input wire [] 18 | // output reg [31:0] data_r, 19 | // output reg busy, 20 | // output reg [31:0] mem_addr_o 21 | ); 22 | `include "mips_define.vh" 23 | 24 | wire [31:0] mem_data_syn; 25 | // wire busy; 26 | assign mem_data_syn = mem_data_i; 27 | assign mem_ack_syn = mem_ack_i; 28 | // assign stall = busy; 29 | 30 | // assign stall = (state != S_IDLE)?1:0; 31 | 32 | 33 | reg [31:0] cache_addr; 34 | reg cache_edit; 35 | reg [31:0] cache_din; 36 | reg cache_store; 37 | wire [31:0] cache_dout; 38 | 39 | initial begin 40 | cache_edit = 0; 41 | end 42 | 43 | cache_line CACHELINE( 44 | .clk(clk), 45 | .rst(rst), 46 | .addr(cache_addr), // [31:0] 47 | .load(cache_store), 48 | .edit(cache_edit), 49 | .invalid(1'b0), 50 | .din(cache_din), // [31:0] 51 | 52 | .hit(cache_hit), 53 | .dout(cache_dout), // [31:0] 54 | .valid(cache_valid), 55 | .dirty(cache_dirty), 56 | .tag(cache_tag) // [21:0] 57 | ); 58 | 59 | reg [2:0] state; 60 | reg [2:0] next_state; 61 | reg [LINE_WORDS_WIDTH-1:0] word_count; 62 | reg [LINE_WORDS_WIDTH-1:0] next_word_count; 63 | reg [LINE_WORDS_WIDTH-1:0] word_count_buf; 64 | reg mem_ack_i_pre; 65 | wire mem_ack_i_real; 66 | assign data_r = {32{((state==S_IDLE)&cache_hit)}}&cache_dout; 67 | initial state = S_IDLE; 68 | always @(*)begin 69 | // if(state!=S_IDLE) 70 | if(!cache_hit || (state !=S_IDLE)) 71 | stall = 1; 72 | else 73 | stall = 0; 74 | end 75 | always@(posedge clk)begin 76 | word_count_buf <= word_count; 77 | mem_ack_i_pre <= mem_ack_i; 78 | end 79 | assign mem_ack_i_real = (~mem_ack_i_pre) & mem_ack_i; 80 | always @(posedge clk) begin 81 | case(state) 82 | S_IDLE: begin 83 | if (en_r || en_w) begin 84 | if (cache_hit) 85 | next_state = S_IDLE; 86 | else if (cache_valid && cache_dirty) next_state = S_BACK; 87 | else next_state = S_FILL; 88 | end 89 | end 90 | 91 | S_BACK: begin 92 | if (mem_ack_i_real) 93 | next_word_count = word_count + 1'h1; 94 | else 95 | next_word_count = word_count; 96 | 97 | if (mem_ack_i_real && word_count == {LINE_WORDS_WIDTH{1'b1}}) 98 | next_state = S_BACK_WAIT; 99 | else 100 | next_state = S_BACK; 101 | end 102 | 103 | S_BACK_WAIT: begin 104 | next_word_count = 0; 105 | next_state = S_FILL; 106 | end 107 | 108 | S_FILL: begin 109 | if (mem_ack_i_real) 110 | next_word_count = word_count + 1'h1; 111 | else 112 | next_word_count = word_count; 113 | if (mem_ack_i_real && word_count == {LINE_WORDS_WIDTH{1'b1}}) 114 | next_state = S_FILL_WAIT; 115 | else 116 | next_state = S_FILL; 117 | end 118 | 119 | S_FILL_WAIT: begin 120 | next_word_count = 0; 121 | next_state = S_IDLE; 122 | end 123 | endcase 124 | if (rst) begin 125 | state <= 0; 126 | word_count <= 0; 127 | next_word_count = 0;// 128 | end 129 | else begin 130 | state <= next_state; 131 | word_count <= next_word_count; 132 | end 133 | end 134 | 135 | 136 | 137 | always @(*) begin 138 | case (next_state) 139 | S_IDLE: begin 140 | cache_addr = addr_rw; 141 | cache_edit = en_w; 142 | cache_din = data_w; 143 | end 144 | S_BACK, S_BACK_WAIT: begin 145 | cache_addr = {addr_rw[31:LINE_WORDS_WIDTH+2], next_word_count, 2'b00}; 146 | end 147 | S_FILL, S_FILL_WAIT: begin 148 | // cache_addr = {addr_rw[31:LINE_WORDS_WIDTH+2], next_word_count, 2'b00}; 149 | cache_addr = {addr_rw[31:LINE_WORDS_WIDTH+2], word_count_buf, 2'b00}; 150 | cache_din = mem_data_syn; 151 | cache_store = mem_ack_syn; 152 | end 153 | endcase 154 | 155 | case (next_state) 156 | S_IDLE, S_BACK_WAIT, S_FILL_WAIT: begin 157 | mem_cs_o <= 0; 158 | mem_we_o <= 0; 159 | mem_addr_o <= 0; 160 | end 161 | S_BACK: begin 162 | mem_cs_o <= 1; 163 | mem_we_o <= 1; 164 | mem_addr_o <= {cache_tag, addr_rw[31-TAG_BITS:LINE_WORDS_WIDTH+2], next_word_count, 2'b00}; 165 | end 166 | S_FILL: begin 167 | mem_cs_o <= 1; 168 | mem_we_o <= 0; 169 | mem_addr_o <= {addr_rw[31:LINE_WORDS_WIDTH+2], word_count_buf, 2'b00}; 170 | end 171 | endcase 172 | end 173 | 174 | endmodule 175 | -------------------------------------------------------------------------------- /Topic 8. Pipelined CPU with Cache/cp0.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 17:04:34 05/26/2015 7 | // Design Name: 8 | // Module Name: cp0 9 | // Project Name: 10 | // Target Devices: 11 | // Tool versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | `include "define.vh" 22 | module cp0( 23 | input wire clk, // main clock 24 | // debug 25 | `ifdef DEBUG 26 | input wire [4:0] debug_addr, // debug address 27 | output reg [31:0] debug_data, // debug data 28 | `endif 29 | // operations (read in ID stage and write in EXE stage) 30 | input wire [1:0] oper, // CP0 operation type 31 | input wire [4:0] addr_r, // read address 32 | output reg [31:0] data_r, // read data 33 | input wire [4:0] addr_w, // write address 34 | input wire [31:0] data_w, // write data 35 | // control signal 36 | input wire rst, // synchronous reset 37 | input wire ir_en, // interrupt enable 38 | input wire ir_in, // external interrupt input 39 | input wire [31:0] ret_addr, // target instruction address to store when interrupt occurred 40 | output wire jump_en, // force jump enable signal when interrupt authorised or ERET occurred 41 | output reg [31:0] jump_addr // target instruction address to jump to 42 | ); 43 | `include "mips_define.vh" 44 | // interrupt determination 45 | wire ir; 46 | reg ir_wait = 0, ir_valid = 1; 47 | reg eret = 0; 48 | reg [31:0] EHBR; 49 | reg [31:0] EPCR; 50 | reg [31:0] TCR; 51 | reg eret_prv; 52 | initial begin 53 | EHBR = 0; 54 | EPCR = 0; 55 | TCR = 0; 56 | end 57 | always @(posedge clk) begin 58 | if (rst) 59 | ir_wait <= 0; 60 | else if (ir_in) 61 | ir_wait <= 1; 62 | else if (eret && ~eret_prv) 63 | ir_wait <= 0; 64 | end 65 | always @(posedge clk) begin 66 | if (rst) 67 | ir_valid <= 1; 68 | else if (eret && ~eret_prv) 69 | ir_valid <= 1; 70 | else if (ir) 71 | ir_valid <= 0; // prevent exception reenter 72 | end 73 | assign ir = ir_en & ir_wait & ir_valid; 74 | 75 | assign jump_en = ir||(eret && ~eret_prv); 76 | always @(posedge clk) begin 77 | eret_prv <= eret; 78 | end 79 | 80 | 81 | always @(*) begin 82 | eret <= 0; 83 | jump_addr <= 0; 84 | if(ir)begin 85 | jump_addr <= EHBR; 86 | end 87 | else begin 88 | case(oper) 89 | EXE_CP_NONE: begin //MFC0 90 | case(addr_r) 91 | CP0_EPCR: data_r <= EPCR; 92 | CP0_EHBR: data_r <= EHBR; 93 | CP0_TCR: data_r <= TCR; 94 | default: data_r <= 0; 95 | endcase 96 | end 97 | /*EXE_CP_STORE: begin //MTC0 98 | case(addr_w) 99 | CP0_EPCR: EPCR <= data_w; 100 | CP0_EHBR: EHBR <= data_w; 101 | default: ; 102 | endcase 103 | end*/ 104 | EXE_CP0_ERET: begin //ERET 105 | eret <= 1; 106 | jump_addr <= EPCR; 107 | end 108 | default:; 109 | endcase 110 | end 111 | end 112 | 113 | always @(posedge clk) begin 114 | TCR <= TCR + 1; 115 | if(ir)begin 116 | EPCR <= ret_addr; 117 | end 118 | else begin 119 | case(oper) 120 | EXE_CP_STORE: begin //MTC0 121 | case(addr_w) 122 | CP0_EPCR: EPCR <= data_w; 123 | CP0_EHBR: EHBR <= data_w; 124 | CP0_TCR: TCR <= data_w; 125 | default: ; 126 | endcase 127 | end 128 | endcase 129 | end 130 | end 131 | 132 | 133 | endmodule 134 | -------------------------------------------------------------------------------- /Topic 8. Pipelined CPU with Cache/data_mem.hex: -------------------------------------------------------------------------------- 1 | 00000000 2 | 00000000 3 | 00000000 4 | 00000000 5 | 00000000 6 | 00000000 7 | 00000000 8 | 00000000 9 | 00000000 10 | 00000000 11 | 00000000 12 | 00000000 13 | 00000000 14 | 00000000 15 | 00000000 16 | 00000000 17 | 00000000 18 | 00000000 19 | 00000000 20 | 00000000 21 | 00000000 22 | 00000000 23 | 00000000 24 | 00000000 25 | 00000000 26 | 00000000 27 | 00000000 28 | 00000000 29 | 00000000 30 | 00000000 31 | 00000000 32 | 00000000 33 | -------------------------------------------------------------------------------- /Topic 8. Pipelined CPU with Cache/data_ram.v: -------------------------------------------------------------------------------- 1 | module data_ram ( 2 | input wire clk, 3 | input wire rst, 4 | input wire [31:0] addr, 5 | input wire ren, 6 | input wire wen, 7 | input wire [31:0] din, 8 | output reg [31:0] dout, 9 | output reg stall, 10 | output reg ack 11 | ); 12 | 13 | parameter 14 | ADDR_WIDTH = 5, 15 | CLK_DELAY = 8; 16 | 17 | reg [31:0] data_mem [0:(1< 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | hit 16 | hit 17 | 18 | 19 | dout[31:0] 20 | dout[31:0] 21 | HEXRADIX 22 | 23 | 24 | valid 25 | valid 26 | 27 | 28 | dirty 29 | dirty 30 | 31 | 32 | tag[21:0] 33 | tag[21:0] 34 | HEXRADIX 35 | 36 | 37 | clk 38 | clk 39 | 40 | 41 | rst 42 | rst 43 | 44 | 45 | addr[31:0] 46 | addr[31:0] 47 | HEXRADIX 48 | 49 | 50 | load 51 | load 52 | 53 | 54 | edit 55 | edit 56 | 57 | 58 | invalid 59 | invalid 60 | 61 | 62 | din[31:0] 63 | din[31:0] 64 | HEXRADIX 65 | 66 | 67 | --------------------------------------------------------------------------------