├── .gitignore ├── Reports ├── Report MS2.docx ├── Report MS3.docx └── Final Report.docx ├── Test ├── testCase.txt └── cpu_tb_sim.wcfg ├── RTL ├── Others │ ├── Decoder5_32.v │ ├── Mux2_1.v │ ├── ShiftLeft1.v │ ├── Mux4_1.v │ ├── SignExtend.v │ └── SSDDriver.v ├── ALU │ ├── Full_Adder.v │ ├── AdderSub.v │ ├── RippleAdder.v │ └── ALU.v ├── Registers │ ├── FlipFlop.v │ ├── RegWLoad.v │ ├── RegFile.v │ └── regfileModel.v ├── ClkInverter.v ├── Adder.v ├── Other Units │ ├── ClkDiv.v │ ├── ImmGen.v │ └── ForwardUnit.v ├── TestBench │ ├── clkDiv_tb.v │ ├── cpu_tb.v │ └── mem_tb.v ├── memAddressSelectUnit.v ├── RegSrcUnit.v ├── InterruptAddressGenerator.v ├── Control │ ├── ALUControl.v │ ├── BranchUnit.v │ └── ControlUnit.v ├── PIC.v ├── RISCV_TOP.v ├── TMRGenerator.v ├── Interrupt_Detector.v ├── Memory │ └── Memory.v ├── Global │ └── values.v ├── CSRRegFile.v ├── decompression.v └── RISCV.v └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | .idea/ 3 | -------------------------------------------------------------------------------- /Reports/Report MS2.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djzenma/RV32IC-CPU/HEAD/Reports/Report MS2.docx -------------------------------------------------------------------------------- /Reports/Report MS3.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djzenma/RV32IC-CPU/HEAD/Reports/Report MS3.docx -------------------------------------------------------------------------------- /Reports/Final Report.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djzenma/RV32IC-CPU/HEAD/Reports/Final Report.docx -------------------------------------------------------------------------------- /Test/testCase.txt: -------------------------------------------------------------------------------- 1 | 93 00 80 01 13 01 20 00 93 01 30 00 67 81 00 00 13 02 40 00 93 02 50 00 17 8F 00 00 13 03 60 00 -------------------------------------------------------------------------------- /RTL/Others/Decoder5_32.v: -------------------------------------------------------------------------------- 1 | // file: Decoder5_32.v 2 | // author: @cherifsalama 3 | 4 | `timescale 1ns/1ns 5 | 6 | module Decoder5_32 ( 7 | input en, 8 | input [4:0] dec_in, 9 | output [31:0] dec_out 10 | ); 11 | 12 | assign dec_out = en?(1<Directories 5 | The Repository contains the following Directories: 6 |

RTL

7 | Contains all the verilog implementations 8 | 9 |

Test

10 | Contains the testCase.txt file where you can put your own testcases (assembly instructions), and contains a simulation configuration file that you can use to see a nice looking simulation. 11 | 12 |

Reports

13 | Contains a full detailed documentation about the CPU implementation. 14 | 15 |

Test it yourself!

16 | If you want to test your own code on my RISCV32IC CPU, please do the following:
17 | 1. convert your code to hex,
18 | 2. then go to the file “RTL/TestBench/testCase.txt” in the project directory and paste your code into it.
19 | 3. Please make sure to change the path of the "testCase.txt" file in the $readmemh() function in the Memory module according to your own path. 20 | 21 | 22 | -------------------------------------------------------------------------------- /RTL/RegSrcUnit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 11/03/2018 10:23:44 PM 7 | // Design Name: 8 | // Module Name: RegSrcUnit 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 | 22 | 23 | module RegSrcUnit( 24 | input clk, 25 | input regWrite, 26 | output reg regMuxSelect 27 | ); 28 | 29 | always @(negedge clk) begin 30 | if(!regWrite && !clk) 31 | if(regWrite) 32 | regMuxSelect = 1'b1; 33 | else 34 | regMuxSelect = 1'b0; 35 | end 36 | 37 | always @(posedge clk) begin 38 | regMuxSelect = 1'b0; 39 | end 40 | 41 | 42 | 43 | endmodule 44 | -------------------------------------------------------------------------------- /RTL/InterruptAddressGenerator.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 11/13/2018 08:05:36 PM 7 | // Design Name: 8 | // Module Name: InterruptAddressGenerator 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 | 22 | 23 | module InterruptAddressGenerator( 24 | input interruptF, 25 | input [2:0] interSel, 26 | input [2:0] intNum, 27 | output reg [31:0] addr 28 | ); 29 | 30 | always @(*) begin 31 | if(interruptF) begin 32 | case(interSel) 33 | `NMI: addr = 32'h10; 34 | `ECALL: addr = 32'h20; 35 | `EBREAK:addr = 32'h30; 36 | `TMR: addr = 32'h40; 37 | `INT: addr = 32'h100 + (intNum * 32'h10); 38 | endcase 39 | end 40 | end 41 | 42 | endmodule 43 | -------------------------------------------------------------------------------- /RTL/TestBench/mem_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 10/26/2018 10:34:55 PM 7 | // Design Name: 8 | // Module Name: mem_tb 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 | 22 | 23 | module mem_tb(); 24 | 25 | reg clk, rst, MemRead, MemWrite; 26 | reg [1:0] mode; 27 | reg [5:0] addr; 28 | reg [31:0] data_in; 29 | wire [31:0] data_out; 30 | 31 | Memory MEM (clk, rst,MemRead,MemWrite,mode,addr,data_in,data_out); 32 | 33 | always begin 34 | clk=~clk; 35 | #10; 36 | 37 | end 38 | 39 | initial begin 40 | clk=0; 41 | rst=1; 42 | MemWrite = 0; 43 | mode=0; 44 | addr=0; 45 | data_in=15; 46 | 47 | #20; 48 | MemRead=1; 49 | 50 | end 51 | 52 | endmodule 53 | -------------------------------------------------------------------------------- /RTL/Control/ALUControl.v: -------------------------------------------------------------------------------- 1 | // file: ALUControl.v 2 | // author: @cherifsalama 3 | 4 | `timescale 1ns/1ns 5 | 6 | module ALUControl( 7 | input [1:0] ALUOp, 8 | input [2:0] func3, 9 | input [6:0] func7, 10 | output reg [3:0] sel 11 | ); 12 | 13 | always @(*) begin // TODO :: Remove negedge clk 14 | case (ALUOp) 15 | `ALUOP_ADD: sel = `ALU_ADD; //add 16 | `ALUOP_SUB: sel = `ALU_SUB; //sub 17 | `ALUOP_OTHER: begin 18 | sel = (func3 == `F3_SLL) ? `ALU_SLL: // TODO :: convert to case 19 | (func3 == `F3_SLT) ? `ALU_SLT: 20 | (func3 == `F3_SLTU) ? `ALU_SLTU: 21 | (func3 == `F3_XOR) ? `ALU_XOR: 22 | (func3 == `F3_SRL) ? `ALU_SRL: 23 | (func3 == `F3_OR) ? `ALU_OR: 24 | (func3 == `F3_AND) ? `ALU_AND: 25 | (func3 == `F3_SRL && func7 == `F7_SRA) ? `ALU_SRA: 26 | `ALU_ADD; 27 | end 28 | default : sel = `ALU_PASS; 29 | endcase 30 | end 31 | 32 | endmodule 33 | 34 | -------------------------------------------------------------------------------- /RTL/PIC.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 11/13/2018 06:16:18 PM 7 | // Design Name: 8 | // Module Name: PIC 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 | 22 | 23 | module PIC(input [7:0] intReq, output Int, output[2:0] Int_Num); 24 | assign Int = (intReq[0] || intReq[1] || intReq[2] || intReq[3] || intReq[4] || intReq[5] || intReq[6] || intReq[7]); 25 | assign Int_Num = (intReq[0]) ? 3'b000 : 26 | (intReq[1]) ? 3'b001 : 27 | (intReq[2]) ? 3'b010 : 28 | (intReq[3]) ? 3'b011 : 29 | (intReq[4]) ? 3'b100 : 30 | (intReq[5]) ? 3'b101 : 31 | (intReq[6]) ? 3'b110 : 32 | 3'b111; 33 | endmodule 34 | -------------------------------------------------------------------------------- /RTL/Other Units/ForwardUnit.v: -------------------------------------------------------------------------------- 1 | // file: ForwardUnit.v 2 | // author: @mobs_11 3 | 4 | `timescale 1ns/1ns 5 | 6 | 7 | module ForwardUnit( 8 | input [4:0] ID_EX_Rs1, 9 | input [4:0] ID_EX_Rs2, 10 | input EX_MEM_RegWrite, 11 | input [4:0] EX_MEM_Rd, 12 | input MEM_WB_RegWrite, 13 | input [4:0] MEM_WB_Rd, 14 | output reg[1:0] ForwardA, 15 | output reg[1:0] ForwardB 16 | 17 | ); 18 | 19 | always @ (*) begin 20 | if (EX_MEM_RegWrite && (EX_MEM_Rd != 0) && (EX_MEM_Rd == ID_EX_Rs1)) 21 | ForwardA = 2'b10; 22 | else if (MEM_WB_RegWrite && (MEM_WB_Rd != 0) && (MEM_WB_Rd == ID_EX_Rs1) && !(EX_MEM_RegWrite && (EX_MEM_Rd != 0) && (EX_MEM_Rd == ID_EX_Rs1) ) ) 23 | ForwardA = 2'b01; 24 | else 25 | ForwardA = 2'b00; 26 | end 27 | 28 | always @ (*) begin 29 | if (EX_MEM_RegWrite && (EX_MEM_Rd != 0) && (EX_MEM_Rd == ID_EX_Rs2)) 30 | ForwardB = 2'b10; 31 | else if (MEM_WB_RegWrite && (MEM_WB_Rd != 0) && (MEM_WB_Rd == ID_EX_Rs2) && !(EX_MEM_RegWrite && (EX_MEM_Rd != 0) && (EX_MEM_Rd == ID_EX_Rs2) ) ) 32 | ForwardB = 2'b01; 33 | else 34 | ForwardB = 2'b00; 35 | end 36 | 37 | endmodule 38 | 39 | -------------------------------------------------------------------------------- /RTL/RISCV_TOP.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 11/13/2018 06:13:20 PM 7 | // Design Name: 8 | // Module Name: RISCV_TOP 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 | 22 | 23 | module RISCV_TOP( 24 | input clk, 25 | input rst, 26 | input en_inter, 27 | input [7:0] intReq, 28 | input nmi, 29 | output [31:0] out 30 | ); 31 | 32 | wire int; 33 | wire [2:0] int_num; 34 | 35 | PIC pic (.intReq(intReq), .Int(int), .Int_Num(int_num)); 36 | 37 | RISCV CPU ( 38 | .clk_i(clk), 39 | .rst(rst), 40 | .en_inter(1'b1), 41 | .int(int), 42 | .int_num(int_num), 43 | .nmi(nmi), 44 | .en_nmi(1'b0), 45 | .en_ecall(1'b1), 46 | .en_ebreak(1'b0), 47 | .en_int(1'b0), 48 | .en_tmr(1'b1), 49 | .limit(0), 50 | .out(out) 51 | ); 52 | 53 | endmodule 54 | -------------------------------------------------------------------------------- /RTL/TMRGenerator.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 11/13/2018 07:06:58 PM 7 | // Design Name: 8 | // Module Name: NmiGenerator 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 | 22 | 23 | module TMRGenerator( 24 | input clk, 25 | input rst, 26 | input [31:0] limit, 27 | output reg tmrF 28 | ); 29 | 30 | reg [31:0] count; 31 | 32 | always @ (posedge clk) begin 33 | if(rst) begin 34 | count <= 32'b0; 35 | tmrF <= 1'b0; 36 | end 37 | else begin 38 | if(count == limit) begin 39 | count <= 32'b0; 40 | tmrF <= 1'b1; 41 | end 42 | if(count == limit + 1) begin 43 | count <= 32'b0; 44 | tmrF <= 1'b0; 45 | end 46 | else begin 47 | count <= count + 1; 48 | tmrF <= 1'b0; 49 | end 50 | end 51 | end 52 | 53 | endmodule 54 | -------------------------------------------------------------------------------- /RTL/Control/BranchUnit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 10/29/2018 06:53:37 PM 7 | // Design Name: 8 | // Module Name: BranchUnit 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 | 22 | module BranchUnit( input branch, 23 | input s, 24 | input z, 25 | input c, 26 | input v, 27 | input [2:0] func3, 28 | output reg branchTaken); 29 | 30 | always @ * begin 31 | case(func3) 32 | `BR_BEQ: branchTaken = z & branch; 33 | `BR_BNE: branchTaken = ~z & branch; 34 | `BR_BLT: branchTaken = (s != v) & branch; 35 | `BR_BGE: branchTaken = (s == v) & branch; 36 | `BR_BLTU: branchTaken = (~c) & branch; 37 | `BR_BGEU: branchTaken = (c) & branch; 38 | default: branchTaken = 1'b0; 39 | endcase 40 | end 41 | 42 | endmodule 43 | 44 | 45 | -------------------------------------------------------------------------------- /RTL/Registers/RegFile.v: -------------------------------------------------------------------------------- 1 | // file: RegFile.v 2 | // author: @cherifsalama 3 | 4 | `timescale 1ns/1ns 5 | 6 | module RegFile( 7 | input clk, 8 | input clk_slow, 9 | input rst, 10 | input WriteEn, 11 | input [4:0] rs1_rd, 12 | input [4:0] rs2, 13 | input [31:0] write_data, 14 | output reg [31:0] read_data1, 15 | output reg [31:0] read_data2 16 | ); 17 | 18 | wire [31:0] xs[31:0]; 19 | wire [31:0] load; 20 | wire write; 21 | 22 | Decoder5_32 dec ( .en(WriteEn), 23 | .dec_in(rs1_rd), 24 | .dec_out(load) 25 | ); 26 | 27 | RegWLoad r0 (clk, rst, 1'b0, write_data, xs[0]); //Reg x0 cannot be written (load = 0) 28 | genvar i; 29 | generate 30 | for (i = 1;i < 32; i = i + 1) 31 | RegWLoad ri ( 32 | .clk(clk), 33 | .rst(rst), 34 | .load(load[i] & write), 35 | .data_in(write_data), 36 | .data_out(xs[i]) 37 | ); 38 | endgenerate 39 | 40 | assign write = (clk ^ clk_slow); 41 | 42 | always @(negedge clk) begin 43 | // if(~WriteEn) begin 44 | read_data1 = xs[rs1_rd]; 45 | read_data2 = xs[rs2]; 46 | // end 47 | end 48 | 49 | endmodule 50 | 51 | -------------------------------------------------------------------------------- /RTL/Registers/regfileModel.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 10/26/2018 11:02:30 PM 7 | // Design Name: 8 | // Module Name: regfileModel 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 | 22 | 23 | module regfileModel( input clk, input rst, input en, input[4:0] rs1, input[4:0] rs2, input[4:0] rd, input[31:0] RegW, output[31:0] RegR1, output[31:0] RegR2); 24 | wire[4:0] regsrc; 25 | RegFile rf (.clk (~clk), 26 | .rst (rst), 27 | .WriteEn (en), 28 | .rs1_rd (regsrc), 29 | .rs2 (rs2), 30 | .write_data (RegW), 31 | .read_data1 (RegR1), 32 | .read_data2 (RegR2) 33 | ); 34 | Mux2_1#(5) MuxregFile (.sel (en), 35 | .in1 (rs1), 36 | .in2 (rd), 37 | .out (regsrc) 38 | ); 39 | 40 | endmodule 41 | -------------------------------------------------------------------------------- /RTL/Interrupt_Detector.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 11/13/2018 06:34:31 PM 7 | // Design Name: 8 | // Module Name: Interrupt_Detector 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 | 22 | module Interrupt_Detector( 23 | input nmi, 24 | input ecall, 25 | input ebreak, 26 | input int, 27 | input tmr, 28 | 29 | input en_inter, 30 | 31 | input en_ecall, 32 | input en_int, 33 | input en_tmr, 34 | 35 | output interFlag, 36 | output [2:0] interSel 37 | ); 38 | 39 | assign interFlag = ( (nmi) || (ebreak) || (en_int && int && en_inter) || (en_tmr && tmr && en_inter) || (en_ecall && ecall && en_inter) ); 40 | 41 | assign interSel = (nmi) ? `NMI: 42 | (ebreak) ? `EBREAK : 43 | (tmr) ? `TMR: 44 | (int) ? `INT: 45 | `ECALL; 46 | endmodule 47 | -------------------------------------------------------------------------------- /RTL/ALU/ALU.v: -------------------------------------------------------------------------------- 1 | // file: ALU.v 2 | // author: Engineer Mazen Amr & Engineer Mohamed Hossam 3 | 4 | `timescale 1ns/1ns 5 | 6 | module ALU( 7 | input [3:0] sel, 8 | input [31:0] a, 9 | input [31:0] b, 10 | output reg [31:0] result, 11 | output z, 12 | output s, 13 | output c, 14 | output v 15 | ); 16 | 17 | wire [31:0] sum, difference; 18 | reg [31:0] tempA, tempB; 19 | wire cout, ci; 20 | 21 | always @ (*) begin 22 | case (sel) 23 | 24 | `ALU_ADD: begin 25 | result = a + b; 26 | // $display("Add result: %d + %d = %d", a, b, result); 27 | end 28 | `ALU_SUB: begin 29 | result = a - b; 30 | $display("Add result: %d + %d = %d", a, b, result); 31 | end 32 | `ALU_PASS:result = result; 33 | `ALU_OR: result = a | b; 34 | `ALU_AND: result = a & b; 35 | `ALU_XOR: result = a ^ b; 36 | `ALU_SRL: result = a >> b; 37 | `ALU_SRA: result = a >>> b; 38 | `ALU_SLL: result = a << b; 39 | `ALU_SLT: result = (a 1 To Enable TMR, [1] 0 => 1 To Enable EX_INTERRUPT, [2] 0 => 1 TO Enable ECALL, [3] TO GLOBALLY DISABLE/ENABLE 63 | 6. 0x344 mip 0 => 1 iff TMR IS HIGH, 0 => 1 iff NMI || EX_INTERRUPT IS HIGH, 0 => 1 iff EBREAK OR ECALL IS HIGH WITH EACH CLOCK CYCLE 64 | */ 65 | 66 | /** 67 | CSR Registers Classifications 68 | 69 | Standard Read-Write 70 | MEPC //STORES ADDRESS OF PC AS IS WITHOUT INCREMENT 71 | MIE 72 | MIP 73 | Read-Write Shadows 74 | MCYCLE 75 | MTIME 76 | MINSTRET 77 | MTIMECMP 78 | */ 79 | 80 | reg [31:0] CSR [6:0]; 81 | reg [2:0] Selected_Addr; 82 | reg [31:0] count; 83 | 84 | reg tmr; 85 | wire [2:0] interSel, int_num; 86 | wire load; 87 | 88 | 89 | //Convert Incoming RISC V standard addr to selected address 90 | always @(*) begin 91 | Selected_Addr = (addr == 12'h341) ? `MEPC : 92 | (addr == 12'hb00) ? `MCYCLE : 93 | (addr == 12'hb01) ? `MTIME : 94 | (addr == 12'hb02) ? `MINSTRET : 95 | (addr == 12'hb03) ? `MTIMECMP : 96 | (addr == 12'h304) ? `MIE : 97 | `MIP ; 98 | end 99 | 100 | 101 | //rst or write with posedge of clk 102 | always @(posedge clk) begin 103 | if(rst) begin 104 | CSR[`MTIME] = 32'd22000; 105 | CSR[`MTIMECMP] = 32'd22010; 106 | CSR[`MEPC] = 32'b0; 107 | CSR[`MINSTRET] = 32'b0; 108 | CSR[`MCYCLE] = 32'b0; 109 | CSR[`MIP] = 32'b0; 110 | CSR[`MIE] = 32'b01111; 111 | count = 0; 112 | end 113 | end 114 | 115 | //Read with negedge of clk 116 | always @(negedge clk) begin 117 | CSR_Read_Data = CSR[Selected_Addr] ; 118 | end 119 | 120 | always @(posedge clk_slow) begin 121 | // MCYCLES Reg Handling 122 | CSR[`MCYCLE] = CSR[`MCYCLE] + 1; 123 | 124 | // MTIME && MTIMECMP Regs Handling 125 | if(count == 10) begin 126 | CSR[`MTIME] = CSR[`MTIME] + 1; 127 | count = count + 1; 128 | end 129 | else if(count == 10 + 1) begin 130 | count = 0; 131 | end 132 | else 133 | count = count + 1; 134 | 135 | if(CSR[`MTIME] == CSR[`MTIMECMP]) begin 136 | CSR[`MTIMECMP] = CSR[`MTIMECMP] + 10; 137 | tmr = 1'b1; 138 | end 139 | else begin 140 | CSR[`MTIMECMP] = CSR[`MTIMECMP]; 141 | tmr = 1'b0; 142 | end 143 | 144 | // MinStret Reg Handling 145 | if(!JumpOrBranch) 146 | CSR[`MINSTRET] = CSR[`MINSTRET] + 1; 147 | end 148 | 149 | assign load = clk ^ clk_slow; 150 | 151 | always @(load) begin 152 | // Writing 153 | if(CSR_Write) begin 154 | if(Set) // CSRS 155 | CSR[Selected_Addr] = CSR[Selected_Addr] | CSR_Write_Data; 156 | else if(Clear) // CSRC 157 | CSR[Selected_Addr] = CSR[Selected_Addr] & ~CSR_Write_Data; 158 | else // CSRW 159 | CSR[Selected_Addr] = CSR_Write_Data; 160 | end 161 | else 162 | CSR[Selected_Addr] = CSR[Selected_Addr]; 163 | end 164 | 165 | always @ (posedge clk) begin 166 | CSR[`MIE] = {28'b0, en_inter, en_ecall, en_int, en_tmr}; 167 | CSR[`MIP] = {29'b0, (ecall || ebreak), int, tmr}; 168 | 169 | 170 | if(interF && pc >= `CODE_SEGMENT) 171 | CSR[`MEPC] = pc; 172 | end 173 | 174 | 175 | Interrupt_Detector interUnit ( 176 | .nmi(nmi), 177 | .ecall(ecall), 178 | .ebreak(ebreak), 179 | .int(int), 180 | .tmr(tmr), 181 | 182 | .en_inter(en_inter), 183 | 184 | .en_ecall(en_ecall), 185 | .en_int(en_int), 186 | .en_tmr(en_tmr), 187 | 188 | .interFlag(interF), 189 | .interSel(interSel) 190 | ); 191 | 192 | InterruptAddressGenerator intrAdrrGen( 193 | .interruptF(interF), 194 | .interSel(interSel), 195 | .intNum(int_num), 196 | .addr(interAddr) 197 | ); 198 | 199 | 200 | endmodule -------------------------------------------------------------------------------- /RTL/decompression.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 11/07/2018 05:58:14 PM 7 | // Design Name: 8 | // Module Name: DecompressionUnit 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 | 22 | 23 | module Decompression( 24 | input [15:0] IF_Instr_16, 25 | output reg [31:0] IF_Dec_32 26 | ); 27 | 28 | always @ (*) begin 29 | 30 | case ({IF_Instr_16[15:13], IF_Instr_16[1:0]}) 31 | /* c.addi4spn ---------------------------------------------------------------------*/ 32 | 5'b00000: IF_Dec_32 = {2'b00, IF_Instr_16[10:7], IF_Instr_16[12:11], IF_Instr_16[5], IF_Instr_16[6], 2'b00, 5'd2, 3'b000, 2'b01, IF_Instr_16[4:2], 7'b0010011}; 33 | /* c.lw ---------------------------------------------------------------------------*/ 34 | 5'b01000: IF_Dec_32 = {5'b00000, IF_Instr_16[5], IF_Instr_16[12:10], IF_Instr_16[6], 2'b00, 2'b01, IF_Instr_16[9:7], 3'b010, 2'b01, IF_Instr_16[4:2], 7'b0000011}; 35 | /* c.sw ---------------------------------------------------------------------------*/ 36 | 5'b11000: IF_Dec_32 = {5'b00000, IF_Instr_16[5], IF_Instr_16[12], 2'b01, IF_Instr_16[4:2], 2'b01, IF_Instr_16[9:7], 3'b010, IF_Instr_16[11:10], IF_Instr_16[6], 2'b00, 7'b0100011}; 37 | 5'b00001: begin 38 | /* c.nop ----------------------------------------------------------------------*/ 39 | if (IF_Instr_16[12:2] == 11'b0) 40 | IF_Dec_32 = {25'b0, 7'b0010011}; 41 | /* c.addi --------------------------------------------------------------------*/ 42 | else IF_Dec_32 = {{7{IF_Instr_16[12]}}, IF_Instr_16[6:2], IF_Instr_16[11:7], 3'b000, IF_Instr_16[11:7], 7'b0010011}; 43 | end 44 | /* c.jal --------------------------------------------------------------------------*/ 45 | 5'b00101: IF_Dec_32 = {IF_Instr_16[12], IF_Instr_16[8], IF_Instr_16[10:9], IF_Instr_16[6], IF_Instr_16[7], IF_Instr_16[2], IF_Instr_16[11], IF_Instr_16[5:3], IF_Instr_16[12], {8{IF_Instr_16[12]}}, 5'd1, 7'b1101111}; 46 | /* c.li ---------------------------------------------------------------------------*/ 47 | 5'b01001: IF_Dec_32 = {{7{IF_Instr_16[12]}}, IF_Instr_16[6:2], 5'd0, 3'b000, IF_Instr_16[11:7], 7'b0010011}; 48 | 5'b01101: begin 49 | /* c.addi16sp ------------------------------------------------------------------*/ 50 | if (IF_Instr_16[11:7] == 5'd2) 51 | IF_Dec_32 = {{3{IF_Instr_16[12]}}, IF_Instr_16[4], IF_Instr_16[3], IF_Instr_16[5], IF_Instr_16[2], IF_Instr_16[6], 4'b0000, 5'd2, 3'b000, 5'd2, 7'b0010011}; 52 | /* c.lui -----------------------------------------------------------------------*/ 53 | else IF_Dec_32 = {{15{IF_Instr_16[12]}}, IF_Instr_16[6:2], IF_Instr_16[11:7], 7'b0110111}; 54 | end 55 | 5'b10001: begin 56 | /* c.sub --------------------------------------------------------------------*/ 57 | if (IF_Instr_16[12:10] == 3'b011 && IF_Instr_16[6:5] == 2'b00) 58 | IF_Dec_32 = {7'b0100000, 2'b01, IF_Instr_16[4:2], 2'b01, IF_Instr_16[9:7], 3'b000, 2'b01, IF_Instr_16[9:7], 7'b0110011}; 59 | /* c.xor --------------------------------------------------------------------*/ 60 | else if (IF_Instr_16[12:10] == 3'b011 && IF_Instr_16[6:5] == 2'b01) 61 | IF_Dec_32 = {7'b0000000, 2'b01, IF_Instr_16[4:2], 2'b01, IF_Instr_16[9:7], 3'b100, 2'b01, IF_Instr_16[9:7], 7'b0110011}; 62 | /* c.or --------------------------------------------------------------------*/ 63 | else if (IF_Instr_16[12:10] == 3'b011 && IF_Instr_16[6:5] == 2'b10) 64 | IF_Dec_32 = {7'b0000000, 2'b01, IF_Instr_16[4:2], 2'b01, IF_Instr_16[9:7], 3'b110, 2'b01, IF_Instr_16[9:7], 7'b0110011}; 65 | /* c.and --------------------------------------------------------------------*/ 66 | else if (IF_Instr_16[12:10] == 3'b011 && IF_Instr_16[6:5] == 2'b11) 67 | IF_Dec_32 = {7'b0000000, 2'b01, IF_Instr_16[4:2], 2'b01, IF_Instr_16[9:7], 3'b111, 2'b01, IF_Instr_16[9:7], 7'b0110011}; 68 | /* c.andi --------------------------------------------------------------------*/ 69 | else if (IF_Instr_16[11:10] == 2'b10) 70 | IF_Dec_32 = {{7{IF_Instr_16[12]}}, IF_Instr_16[6:2], 2'b01, IF_Instr_16[9:7], 3'b111, 2'b01, IF_Instr_16[9:7], 7'b0010011}; 71 | /* Skip instruction ---------------------------------------------------------*/ 72 | else if (IF_Instr_16[12] == 1'b0 && IF_Instr_16[6:2] == 5'b0) 73 | IF_Dec_32 = 32'b0; 74 | /* c.srli --------------------------------------------------------------------*/ 75 | else if (IF_Instr_16[11:10] == 2'b00) 76 | IF_Dec_32 = {7'b0000000, IF_Instr_16[6:2], 2'b01, IF_Instr_16[9:7], 3'b101, 2'b01, IF_Instr_16[9:7], 7'b0010011}; 77 | /* c.srai --------------------------------------------------------------------*/ 78 | else 79 | IF_Dec_32 = {7'b0100000, IF_Instr_16[6:2], 2'b01, IF_Instr_16[9:7], 3'b101, 2'b01, IF_Instr_16[9:7], 7'b0010011}; 80 | end 81 | /* c.j -----------------------------------------------------------------------*/ 82 | 5'b10101: IF_Dec_32 = {IF_Instr_16[12], IF_Instr_16[8], IF_Instr_16[10:9], IF_Instr_16[6], IF_Instr_16[7], IF_Instr_16[2], IF_Instr_16[11], IF_Instr_16[5:3], IF_Instr_16[12], {8{IF_Instr_16[12]}}, 5'd0, 7'b1101111}; 83 | /* c.beqz --------------------------------------------------------------------*/ 84 | 5'b11001: IF_Dec_32 = {{4{IF_Instr_16[12]}}, IF_Instr_16[6], IF_Instr_16[5], IF_Instr_16[2], 5'd0, 2'b01, IF_Instr_16[9:7], 3'b000, IF_Instr_16[11], IF_Instr_16[10], IF_Instr_16[4], IF_Instr_16[3], IF_Instr_16[12], 7'b1100011}; 85 | /* c.bnez --------------------------------------------------------------------*/ 86 | 5'b11101: IF_Dec_32 = {{4{IF_Instr_16[12]}}, IF_Instr_16[6], IF_Instr_16[5], IF_Instr_16[2], 5'd0, 2'b01, IF_Instr_16[9:7], 3'b001, IF_Instr_16[11], IF_Instr_16[10], IF_Instr_16[4], IF_Instr_16[3], IF_Instr_16[12], 7'b1100011}; 87 | /* c.slli --------------------------------------------------------------------*/ 88 | 5'b00010: IF_Dec_32 = {7'b0000000, IF_Instr_16[6:2], IF_Instr_16[11:7], 3'b001, IF_Instr_16[11:7], 7'b0010011}; 89 | /* c.lwsp --------------------------------------------------------------------*/ 90 | 5'b01010: IF_Dec_32 = {4'b0000, IF_Instr_16[3:2], IF_Instr_16[12], IF_Instr_16[6:4], 2'b0, 5'd2, 3'b010, IF_Instr_16[11:7], 7'b0000011}; 91 | /* c.swsp --------------------------------------------------------------------*/ 92 | 5'b11010: IF_Dec_32 = {4'b0000, IF_Instr_16[8:7], IF_Instr_16[12], IF_Instr_16[6:2], 5'd2, 3'b010, IF_Instr_16[11:9], 2'b00, 7'b0100011}; 93 | 5'b10010: begin 94 | if (IF_Instr_16[6:2] == 5'd0) begin 95 | /* c.jalr --------------------------------------------------------------------*/ 96 | if (IF_Instr_16[12] && IF_Instr_16[11:7] != 5'b0) 97 | IF_Dec_32 = {12'b0, IF_Instr_16[11:7], 3'b000, 5'd1, 7'b1100111}; 98 | /* c.jr --------------------------------------------------------------------*/ 99 | else IF_Dec_32 = {12'b0, IF_Instr_16[11:7], 3'b000, 5'd0, 7'b1100111}; 100 | end 101 | else if (IF_Instr_16[11:7] != 5'b0) begin 102 | /* c.mv --------------------------------------------------------------------*/ 103 | if (IF_Instr_16[12] == 1'b0) 104 | IF_Dec_32 = {7'b0000000, IF_Instr_16[6:2], 5'd0, 3'b000, IF_Instr_16[11:7], 7'b0110011}; 105 | /* c.add --------------------------------------------------------------------*/ 106 | else IF_Dec_32 = {7'b0000000, IF_Instr_16[6:2], IF_Instr_16[11:7], 3'b000, IF_Instr_16[11:7], 7'b0110011}; 107 | end 108 | end 109 | default : IF_Dec_32 = 32'b0; 110 | endcase 111 | end 112 | 113 | endmodule 114 | -------------------------------------------------------------------------------- /RTL/RISCV.v: -------------------------------------------------------------------------------- 1 | // file: RISCV.v 2 | // author: @mazenAmr 3 | 4 | `timescale 1ns/1ns 5 | 6 | 7 | 8 | module RISCV( 9 | input clk_i, 10 | input rst, 11 | input en_inter, 12 | input int, 13 | input int_num, 14 | input nmi, 15 | input en_nmi, 16 | input en_ecall, 17 | input en_ebreak, 18 | input en_int, 19 | input en_tmr, 20 | input [31:0] limit, 21 | output [31:0] out 22 | ); 23 | /* 24 | * Variables Declaration 25 | */ 26 | wire [31:0] PC_out, PCAdder_out, BranchAdder_out, PC_Or_Branch, 27 | RegR1, RegR2, RegW, ImmGen_out, ALUSrcMux_out, 28 | ALU_out, Mem_out, Inst, PC_Or_Jal, decompressedInstr; 29 | wire Branch, MemRead, MemToReg, MemWrite, ALUSrc, RegWrite, Zero; 30 | wire [1:0] ALUOp, Jump; 31 | wire [3:0] ALUSel; 32 | wire branchTaken, clk_RF, clk_inv, clk, memSelect; 33 | reg [31:0] PC_in; 34 | 35 | 36 | // IF_ID pipeline reg wires 37 | wire [31:0] IF_ID_PC, IF_ID_Inst, jump_address, jal_branch_address, jalR_address, PC4_Or_Branch, IF_ID_InstOut, PC_PLUS_FOUR, PC_PLUS_TWO; 38 | wire [2:0] IF_ID_Mode; 39 | wire [4:0] rs2; 40 | wire [1:0] fwdA, fwdB; 41 | wire IF_ID_luiControl, CompressedFlag, ECall, EBreak, MRET, CSRWrite, CSRSet, CSRClear, CSRI, Auipc; 42 | 43 | wire [12:0] ctrls_part1; 44 | wire [3:0] ctrls_part2; 45 | wire [4:0] ctrls_part3; 46 | 47 | 48 | // ID_EX pipeline reg wires 49 | reg [31:0] ALU_OprandA, ALU_OprandB, ALU_OprandA_fwdRes; 50 | wire [31:0] ID_EX_PC, ID_EX_RegR1, ID_EX_RegR2, ID_EX_Imm, ID_EX_interAddr, PC_in_wo_inter, ID_EX_Inst, csr_read; 51 | wire [12:0] ID_EX_Ctrl; 52 | wire [9:0] ID_EX_Func; 53 | wire [4:0] ID_EX_Rs1, ID_EX_Rs2, ID_EX_Rd, regsrc; 54 | wire [2:0] ID_EX_Mode; 55 | wire [31:0] memMuxOut; 56 | wire [2:0] interSel; 57 | wire ID_EX_luiControl, interF, tmr, ID_EX_ECall, ID_EX_EBreak, ID_EX_MRET, ID_EX_CSRWrite, ID_EX_CSRSet, ID_EX_CSRClear, ID_EX_CSRI, ID_EX_Auipc; 58 | wire [11:0] csrAddr, csrAddrR; 59 | 60 | // EX_MEM pipeline reg wires 61 | wire [31:0] EX_MEM_BranchAddOut, EX_MEM_ALU_out, EX_MEM_RegR2, EX_MEM_PC, EX_MEM_Imm, EX_MEM_csr_read, EX_MEM_RegR1, EX_MEM_Inst; 62 | wire [9:0] EX_MEM_Ctrl; 63 | wire [4:0] EX_MEM_Rd, EX_MEM_Rs1; 64 | wire EX_MEM_Zero, sFlag, vFlag, cFlag, EX_MEM_luiControl, EX_MEM_CSRWrite, EX_MEM_CSRSet, EX_MEM_CSRClear, EX_MEM_CSRI, EX_MEM_branchTaken; 65 | 66 | // MEM_WB pipeline reg wires 67 | wire [31:0] MEM_WB_Mem_out, MEM_WB_ALU_out, MEM_WB_PC, RegData, MEM_WB_Imm, MEM_WB_csr_read, RegW_No_Inter, MEM_WB_RegR1, MEM_WB_Inst, MEM_WB_CSRData; 68 | wire [3:0] MEM_WB_Ctrl; 69 | wire [4:0] MEM_WB_Rd, MEM_WB_Rs1; 70 | wire regMuxSelection, jalSel, MEM_WB_luiControl, MEM_WB_CSRWrite, MEM_WB_CSRSet, MEM_WB_CSRClear, MEM_WB_CSRI, MEM_WB_branchTaken, JumpOrBranch; 71 | 72 | 73 | ClkDiv clkDiv (.clk(clk_i), .rst(rst), .clk_o(clk)); 74 | //ClkDivRF clkDivRF (.clk(clk_i), .rst(rst), .clk_o(clk_RF)); 75 | 76 | ClkInverter clkInv ( 77 | .clk_i(clk), 78 | .clk_o(clk_inv) 79 | ); 80 | 81 | /* 82 | * Pipeline Registers 83 | */ 84 | 85 | RegWLoad#(64) IF_ID (.clk (clk_inv), 86 | .rst (rst), 87 | .load (1'b1), 88 | .data_in ({PC_out, Mem_out}), 89 | .data_out ({IF_ID_PC, IF_ID_InstOut}) 90 | ); 91 | 92 | 93 | 94 | RegWLoad#(207) ID_EX (.clk (clk), 95 | .rst (rst), 96 | .load (1'b1), 97 | .data_in ({ ctrls_part1,// all the control signals 98 | IF_ID_PC, RegR1, RegR2, ImmGen_out, 99 | IF_ID_Inst[31:25], IF_ID_Inst[14:12], 100 | IF_ID_Inst[19:15], IF_ID_Inst[24:20], IF_ID_Inst[11:7], ctrls_part2, IF_ID_InstOut, ctrls_part3}), // the 3 regs 101 | .data_out ({ID_EX_Ctrl, ID_EX_PC, ID_EX_RegR1, ID_EX_RegR2, ID_EX_Imm, // ID_EX_Ctrl has all the 11 bits (7) controls 102 | ID_EX_Func, ID_EX_Rs1, ID_EX_Rs2, ID_EX_Rd, ID_EX_luiControl, ID_EX_ECall, ID_EX_EBreak, ID_EX_MRET, ID_EX_Inst, ID_EX_CSRWrite, ID_EX_CSRSet, ID_EX_CSRClear, ID_EX_CSRI, ID_EX_Auipc}) 103 | ); 104 | 105 | RegWLoad#(283) EX_MEM (.clk (clk_inv), 106 | .rst (rst), 107 | .load (1'b1), 108 | .data_in ({ID_EX_Ctrl[12:3], // Jump, IF_ID_Mode, RegWrite,MemToReg, and Branch,MemRead,MemWrite 109 | BranchAdder_out, Zero, ALU_out, 110 | ID_EX_RegR2, ID_EX_Rd, ID_EX_PC, ID_EX_Imm, ID_EX_luiControl, csr_read, ID_EX_CSRWrite, ID_EX_RegR1, ID_EX_Inst, ID_EX_CSRSet, ID_EX_CSRClear, ID_EX_Rs1, ID_EX_CSRI, branchTaken}), 111 | .data_out ({EX_MEM_Ctrl, // EX_MEM_Ctrl = Jump, IF_ID_Mode, RegWrite,MemToReg, and Branch,MemRead,MemWrite 112 | EX_MEM_BranchAddOut, EX_MEM_Zero, 113 | EX_MEM_ALU_out, 114 | EX_MEM_RegR2, EX_MEM_Rd, EX_MEM_PC, EX_MEM_Imm, EX_MEM_luiControl, EX_MEM_csr_read, EX_MEM_CSRWrite, EX_MEM_RegR1, EX_MEM_Inst, EX_MEM_CSRSet, EX_MEM_CSRClear, EX_MEM_Rs1, EX_MEM_CSRI, EX_MEM_branchTaken}) 115 | ); 116 | 117 | 118 | RegWLoad#(244) MEM_WB (.clk (clk), 119 | .rst (rst), 120 | .load (1'b1), 121 | .data_in ({ {EX_MEM_Ctrl[9:8], EX_MEM_Ctrl[4:3]}, // RegWrite,MemToReg 122 | Mem_out, EX_MEM_ALU_out, EX_MEM_Rd, EX_MEM_PC, EX_MEM_Imm, EX_MEM_luiControl, EX_MEM_csr_read, EX_MEM_CSRWrite, EX_MEM_RegR1, EX_MEM_Inst, EX_MEM_CSRSet, EX_MEM_CSRClear, EX_MEM_Rs1, EX_MEM_CSRI, EX_MEM_branchTaken}), 123 | .data_out ({MEM_WB_Ctrl, MEM_WB_Mem_out, MEM_WB_ALU_out, MEM_WB_Rd, MEM_WB_PC, MEM_WB_Imm, MEM_WB_luiControl, MEM_WB_csr_read, MEM_WB_CSRWrite, MEM_WB_RegR1, MEM_WB_Inst, MEM_WB_CSRSet, MEM_WB_CSRClear, MEM_WB_Rs1, MEM_WB_CSRI, MEM_WB_branchTaken}) 124 | ); 125 | 126 | /* 127 | * Fetch 128 | */ 129 | 130 | RegWLoad PC (.clk (clk), 131 | .rst (rst), 132 | .load (1'b1), 133 | .data_in (PC_in), 134 | .data_out (PC_out) 135 | ); 136 | 137 | 138 | /* 139 | * Decode 140 | */ 141 | 142 | Decompression decUnit ( 143 | .IF_Instr_16(IF_ID_InstOut[15:0]), 144 | .IF_Dec_32(decompressedInstr) 145 | ); 146 | assign CompressedFlag = (IF_ID_InstOut[1:0] != 2'b11) ? 1 : 0; 147 | assign IF_ID_Inst = (CompressedFlag == 1'b1) ? decompressedInstr : IF_ID_InstOut; 148 | 149 | assign rs2 = IF_ID_Inst[24:20]; 150 | 151 | 152 | 153 | RegFile rf (.clk (clk_i), 154 | .clk_slow (clk), 155 | .rst (rst), 156 | .WriteEn (MEM_WB_Ctrl[1]), // RegWrite 157 | .rs1_rd (regsrc), 158 | .rs2 (rs2), 159 | .write_data (RegW), 160 | .read_data1 (RegR1), 161 | .read_data2 (RegR2) 162 | ); 163 | 164 | RegSrcUnit regSrcUnit ( 165 | .clk(clk), 166 | .regWrite(MEM_WB_Ctrl[1]), // RegWrite 167 | .regMuxSelect(regMuxSelection) 168 | ); 169 | 170 | Mux2_1#(5) MuxregFile (.sel (clk), // RegWrite 171 | .in1 (IF_ID_Inst[19:15]), // rs1 172 | .in2 (MEM_WB_Rd), 173 | .out (regsrc) 174 | ); 175 | 176 | ImmGen ig (.IR (IF_ID_Inst), 177 | .Imm (ImmGen_out) 178 | ); 179 | 180 | 181 | 182 | ControlUnit cu (.instr (IF_ID_Inst), 183 | .opcode (IF_ID_Inst[6:2]), 184 | .Branch (Branch), 185 | .Jump (Jump), 186 | .MemRead (MemRead), 187 | .MemToReg (MemToReg), 188 | .ALUOp (ALUOp), 189 | .MemWrite (MemWrite), 190 | .ALUSrc (ALUSrc), 191 | .RegWrite (RegWrite), 192 | .Mode (IF_ID_Mode), 193 | .Lui (IF_ID_luiControl), 194 | .Auipc (Auipc), 195 | .ECall (ECall), 196 | .EBreak (EBreak), 197 | .MRET (MRET), 198 | .CSRWrite (CSRWrite), 199 | .CSRSet (CSRSet), 200 | .CSRClear (CSRClear), 201 | .CSRI (CSRI) 202 | ); 203 | 204 | // if branch taken, or jump, or MRET => flush 205 | 206 | assign ctrls_part1 = (ID_EX_Ctrl[12:11] || branchTaken || ID_EX_MRET) ? {13'b0} : {Jump, IF_ID_Mode, RegWrite, MemToReg, Branch, MemRead, MemWrite, ALUOp, ALUSrc}; 207 | assign ctrls_part2 = (ID_EX_Ctrl[12:11] || branchTaken || ID_EX_MRET) ? {4'b0} : {IF_ID_luiControl, ECall, EBreak, MRET}; 208 | assign ctrls_part3 = (ID_EX_Ctrl[12:11] || branchTaken || ID_EX_MRET) ? {5'b0} : {CSRWrite, CSRSet, CSRClear, CSRI, Auipc}; 209 | 210 | /* 211 | * Execute 212 | */ 213 | 214 | 215 | ForwardUnit FwdUnit ( 216 | .ID_EX_Rs1(ID_EX_Rs1), 217 | .ID_EX_Rs2(ID_EX_Rs2), 218 | .EX_MEM_RegWrite(EX_MEM_Ctrl[4]), 219 | .EX_MEM_Rd(EX_MEM_Rd), 220 | .MEM_WB_RegWrite(MEM_WB_Ctrl[1]), 221 | .MEM_WB_Rd(MEM_WB_Rd), 222 | .ForwardA(fwdA), 223 | .ForwardB(fwdB) 224 | ); 225 | 226 | // Forwarding MUX A & MUX B 227 | always @ (*) begin 228 | if(ID_EX_Auipc) 229 | ALU_OprandA = ID_EX_PC; 230 | else begin 231 | case(fwdA) 232 | 2'b00: 233 | ALU_OprandA = ID_EX_RegR1; 234 | 2'b10: 235 | ALU_OprandA = EX_MEM_ALU_out; 236 | 2'b01: 237 | ALU_OprandA = RegW; 238 | default: 239 | ALU_OprandA = ID_EX_RegR1; 240 | endcase 241 | end 242 | 243 | case(fwdB) 244 | 2'b00: 245 | ALU_OprandB = ALUSrcMux_out; 246 | 2'b10: 247 | ALU_OprandB = EX_MEM_ALU_out; 248 | 2'b01: 249 | ALU_OprandB = RegW; 250 | default: 251 | ALU_OprandB = ALUSrcMux_out; 252 | endcase 253 | 254 | end 255 | 256 | Mux2_1#(32) aluSrcBMux (.sel (ID_EX_Ctrl[0]), // ALUSrc 257 | .in1 (ID_EX_RegR2), 258 | .in2 (ID_EX_Imm), 259 | .out (ALUSrcMux_out) 260 | ); 261 | 262 | 263 | ALU a1 ( 264 | .sel (ALUSel), 265 | .a (ALU_OprandA), 266 | .b (ALU_OprandB), 267 | .result (ALU_out), 268 | .z (Zero), 269 | .s (sFlag), 270 | .c (cFlag), 271 | .v (vFlag) 272 | ); 273 | 274 | 275 | BranchUnit branchUnit ( 276 | .branch(ID_EX_Ctrl[5]), // BRANCH 277 | .s(sFlag), 278 | .z(Zero), 279 | .c(cFlag), 280 | .v(vFlag), 281 | .func3(ID_EX_Func[2:0]), 282 | .branchTaken (branchTaken) 283 | ); 284 | 285 | 286 | Adder OffsetPC ( 287 | .a(ID_EX_PC), 288 | .b(ID_EX_Imm), 289 | .res(BranchAdder_out) 290 | ); 291 | 292 | Adder PC_plus_four ( 293 | .a(IF_ID_PC), 294 | .b(4), 295 | .res(PC_PLUS_FOUR) 296 | ); 297 | 298 | Adder PC_plus_two ( 299 | .a(IF_ID_PC), 300 | .b(2), 301 | .res(PC_PLUS_TWO) 302 | ); 303 | 304 | // beq: PC + imm 305 | Mux2_1#(32) BranchOrPCMux (.sel (branchTaken), 306 | .in1 (PC_PLUS_FOUR), 307 | .in2 (BranchAdder_out), 308 | .out (PC4_Or_Branch) 309 | ); 310 | 311 | Mux2_1#(32) BranchOrPCPlus4OrPcPlus2Mux ( .sel (CompressedFlag), 312 | .in1 (PC4_Or_Branch), 313 | .in2 (PC_PLUS_TWO), 314 | .out (PC_Or_Branch) 315 | ); 316 | 317 | Mux4_1 #(32) srcOfPC( 318 | .sel(ID_EX_Ctrl[12:11]), // Jump 319 | .in1(PC_Or_Branch), 320 | .in2(jal_branch_address), 321 | .in3(jalR_address), 322 | .in4(), 323 | .out(PC_in_wo_inter) 324 | ); 325 | 326 | 327 | // jalr: reg + imm 328 | Adder jalRAdder ( 329 | .a(ID_EX_RegR1), 330 | .b(ID_EX_Imm), 331 | .res(jalR_address) 332 | ); 333 | 334 | ALUControl acu ( 335 | .ALUOp (ID_EX_Ctrl[2:1]), // ALUOp 336 | .func3 (ID_EX_Func[2:0]), 337 | .func7 (ID_EX_Func[9:3]), 338 | .sel (ALUSel) 339 | ); 340 | 341 | // jal: address + PC 342 | 343 | Adder JalAddressAdder ( 344 | .a(ID_EX_Imm), 345 | .b(ID_EX_PC), 346 | .res(jal_branch_address) 347 | ); 348 | 349 | 350 | /*********************************************************************/ 351 | 352 | assign csrAddrR = (ID_EX_MRET) ? `MEPC_ADDR : ID_EX_Inst[31:20]; 353 | assign csrAddr = (clk) ? MEM_WB_Inst[31:20]: csrAddrR; 354 | 355 | assign MEM_WB_CSRData = (MEM_WB_CSRI)? {27'b0, MEM_WB_Rs1} : MEM_WB_RegR1; 356 | 357 | assign JumpOrBranch = (jalSel || MEM_WB_branchTaken)? 1'b1 : 1'b0 ; 358 | 359 | CSRRegFile csrFile( 360 | .clk(clk_i), 361 | .clk_slow(clk), 362 | .rst(rst), 363 | .pc(ID_EX_PC), 364 | .nmi(nmi), 365 | .ecall(ID_EX_ECall), 366 | .ebreak(ID_EX_EBreak), 367 | .int(int), 368 | .en_inter(en_inter), 369 | .en_ecall(en_ecall), 370 | .en_int(en_int), 371 | .en_tmr(en_tmr), 372 | .addr(csrAddr), 373 | .CSR_Write(MEM_WB_CSRWrite), 374 | .CSR_Write_Data(MEM_WB_CSRData), 375 | .Set(MEM_WB_CSRSet), 376 | .Clear(MEM_WB_CSRClear), 377 | .JumpOrBranch(JumpOrBranch), 378 | .CSR_Read_Data(csr_read), 379 | .interF(interF), 380 | .interAddr(ID_EX_interAddr) 381 | ); 382 | 383 | /**********************************************************************/ 384 | always @(*) begin 385 | if(ID_EX_MRET) 386 | PC_in = csr_read + 4 ; 387 | else if(interF) 388 | PC_in = ID_EX_interAddr; 389 | else 390 | PC_in = PC_in_wo_inter; 391 | end 392 | 393 | /* 394 | * Mem 395 | */ 396 | 397 | Memory Mem ( 398 | .clk(clk), 399 | .clk_i(clk_i), 400 | .rst(rst), 401 | .MemRead(EX_MEM_Ctrl[1]), 402 | .MemWrite(EX_MEM_Ctrl[0]), 403 | .mode(EX_MEM_Ctrl[7:5]), 404 | .addr(memMuxOut), 405 | .data_in(EX_MEM_RegR2), 406 | .data_out(Mem_out) 407 | ); 408 | 409 | memAddressSelectUnit MemSrcAddress ( 410 | .clk_fast(clk_i), 411 | .clk_slow(clk), 412 | .select(memSelect) 413 | ); 414 | 415 | Mux2_1 #(32) MemMux (.sel (memSelect), // ~clk_i 416 | .in1 (PC_out), 417 | .in2 (EX_MEM_ALU_out), 418 | .out (memMuxOut) 419 | ); 420 | 421 | 422 | /* 423 | * Write Back 424 | */ 425 | Mux2_1#(32) regWSrcMux1 (.sel (MEM_WB_Ctrl[0]), // MemToReg 426 | .in1 (MEM_WB_ALU_out), 427 | .in2 (MEM_WB_Mem_out), 428 | .out (RegData) 429 | ); 430 | 431 | assign jalSel = (MEM_WB_Ctrl[2] || MEM_WB_Ctrl[3]); 432 | Mux2_1#(32) regWSrcMux2 ( .sel (jalSel), // Jump 433 | .in1 (RegData), 434 | .in2 (MEM_WB_PC + 4), 435 | .out (PC_Or_Jal) 436 | ); 437 | 438 | Mux2_1#(32) regWSrcMux3 ( .sel (MEM_WB_luiControl), 439 | .in1 (PC_Or_Jal), 440 | .in2 (MEM_WB_Imm), 441 | .out (RegW_No_Inter) 442 | ); 443 | assign RegW = (MEM_WB_CSRWrite) ? MEM_WB_csr_read : RegW_No_Inter; 444 | 445 | // only to see delay 446 | assign out = RegW; 447 | 448 | endmodule 449 | 450 | -------------------------------------------------------------------------------- /Test/cpu_tb_sim.wcfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | label 25 | clk 26 | clk 27 | clk_fast 28 | 29 | 30 | clk 31 | clk 32 | 33 | 34 | rst 35 | rst 36 | 37 | 38 | PC 39 | label 40 | #FFFFFF 41 | 42 | 43 | PC_in[31:0] 44 | PC_in[31:0] 45 | UNSIGNEDDECRADIX 46 | 47 | 48 | PC_out[31:0] 49 | PC_out[31:0] 50 | UNSIGNEDDECRADIX 51 | 52 | 53 | IF_ID_PC[31:0] 54 | IF_ID_PC[31:0] 55 | UNSIGNEDDECRADIX 56 | 57 | 58 | ID_EX_PC[31:0] 59 | ID_EX_PC[31:0] 60 | UNSIGNEDDECRADIX 61 | 62 | 63 | EX_MEM_PC[31:0] 64 | EX_MEM_PC[31:0] 65 | UNSIGNEDDECRADIX 66 | 67 | 68 | MEM_WB_PC[31:0] 69 | MEM_WB_PC[31:0] 70 | UNSIGNEDDECRADIX 71 | 72 | 73 | ctrls_part1[12:0] 74 | ctrls_part1[12:0] 75 | 76 | 77 | ctrls_part2[3:0] 78 | ctrls_part2[3:0] 79 | 80 | 81 | ctrls_part3[4:0] 82 | ctrls_part3[4:0] 83 | 84 | 85 | 86 | CSR 87 | label 88 | #E0FFFF 89 | 90 | 91 | ecall 92 | ecall 93 | 94 | 95 | ebreak 96 | ebreak 97 | 98 | 99 | interFlag 100 | interFlag 101 | 102 | 103 | interF 104 | interF 105 | 106 | 107 | ID_EX_EBreak 108 | ID_EX_EBreak 109 | 110 | 111 | ID_EX_ECall 112 | ID_EX_ECall 113 | 114 | 115 | ID_EX_MRET 116 | ID_EX_MRET 117 | 118 | 119 | ID_EX_interAddr[31:0] 120 | ID_EX_interAddr[31:0] 121 | UNSIGNEDDECRADIX 122 | 123 | 124 | csr_read[31:0] 125 | csr_read[31:0] 126 | 127 | 128 | csrAddr[11:0] 129 | csrAddr[11:0] 130 | HEXRADIX 131 | 132 | 133 | MEM_WB_CSRWrite 134 | MEM_WB_CSRWrite 135 | 136 | 137 | MEM_WB_RegR1[31:0] 138 | MEM_WB_RegR1[31:0] 139 | BINARYRADIX 140 | 141 | 142 | MEM_WB_CSRData[31:0] 143 | MEM_WB_CSRData[31:0] 144 | BINARYRADIX 145 | 146 | 147 | MEM_WB_CSRI 148 | MEM_WB_CSRI 149 | 150 | 151 | CSR[6:0][31:0] 152 | CSR[6:0][31:0] 153 | 154 | 155 | 156 | Branch Or PC Mux 157 | label 158 | #E0FFFF 159 | 160 | 161 | CompressedFlag 162 | CompressedFlag 163 | 164 | 165 | PC4_Or_Branch[31:0] 166 | PC4_Or_Branch[31:0] 167 | UNSIGNEDDECRADIX 168 | 169 | 170 | ID_EX_PC[31:0] 171 | ID_EX_PC[31:0] 172 | 173 | 174 | PC_Or_Branch[31:0] 175 | PC_Or_Branch[31:0] 176 | 177 | 178 | PC Src Mux 179 | label 180 | #E0FFFF 181 | 182 | 183 | sel[1:0] 184 | sel[1:0] 185 | 186 | 187 | in1[31:0] 188 | in1[31:0] 189 | 190 | 191 | in2[31:0] 192 | in2[31:0] 193 | 194 | 195 | in3[31:0] 196 | in3[31:0] 197 | 198 | 199 | out[31:0] 200 | out[31:0] 201 | HEXRADIX 202 | 203 | 204 | MEM Address MUX 205 | label 206 | #E0FFFF 207 | 208 | 209 | MEMORY 210 | label 211 | #E0FFFF 212 | 213 | 214 | memMuxOut[31:0] 215 | memMuxOut[31:0] 216 | UNSIGNEDDECRADIX 217 | 218 | 219 | Mem_out[31:0] 220 | Mem_out[31:0] 221 | 222 | 223 | mem[4095:0][7:0] 224 | mem[4095:0][7:0] 225 | 226 | 227 | IF_ID Reg 228 | label 229 | #E0FFFF 230 | 231 | 232 | IF_ID_InstOut[31:0] 233 | IF_ID_InstOut[31:0] 234 | 235 | 236 | Stages Regs 237 | label 238 | #E0FFFF 239 | 240 | 241 | ID_EX_PC[31:0] 242 | ID_EX_PC[31:0] 243 | 244 | 245 | Register 246 | label 247 | #E0FFFF 248 | 249 | 250 | clk 251 | clk 252 | 253 | 254 | MEM_WB_CSRWrite 255 | MEM_WB_CSRWrite 256 | 257 | 258 | MEM_WB_csr_read[31:0] 259 | MEM_WB_csr_read[31:0] 260 | 261 | 262 | RegW[31:0] 263 | RegW[31:0] 264 | UNSIGNEDDECRADIX 265 | 266 | 267 | WriteEn 268 | WriteEn 269 | 270 | 271 | regsrc[4:0] 272 | regsrc[4:0] 273 | UNSIGNEDDECRADIX 274 | 275 | 276 | rs2[4:0] 277 | rs2[4:0] 278 | 279 | 280 | RegR1[31:0] 281 | RegR1[31:0] 282 | 283 | 284 | RegR2[31:0] 285 | RegR2[31:0] 286 | 287 | 288 | xs[31:0][31:0] 289 | xs[31:0][31:0] 290 | 291 | 292 | [31][31:0] 293 | [31][31:0] 294 | 295 | 296 | [30][31:0] 297 | [30][31:0] 298 | 299 | 300 | [29][31:0] 301 | [29][31:0] 302 | 303 | 304 | [28][31:0] 305 | [28][31:0] 306 | 307 | 308 | [27][31:0] 309 | [27][31:0] 310 | 311 | 312 | [26][31:0] 313 | [26][31:0] 314 | 315 | 316 | [25][31:0] 317 | [25][31:0] 318 | 319 | 320 | [24][31:0] 321 | [24][31:0] 322 | 323 | 324 | [23][31:0] 325 | [23][31:0] 326 | 327 | 328 | [22][31:0] 329 | [22][31:0] 330 | 331 | 332 | [21][31:0] 333 | [21][31:0] 334 | 335 | 336 | [20][31:0] 337 | [20][31:0] 338 | 339 | 340 | [19][31:0] 341 | [19][31:0] 342 | 343 | 344 | [18][31:0] 345 | [18][31:0] 346 | 347 | 348 | [17][31:0] 349 | [17][31:0] 350 | 351 | 352 | [16][31:0] 353 | [16][31:0] 354 | 355 | 356 | [15][31:0] 357 | [15][31:0] 358 | 359 | 360 | [14][31:0] 361 | [14][31:0] 362 | 363 | 364 | [13][31:0] 365 | [13][31:0] 366 | 367 | 368 | [12][31:0] 369 | [12][31:0] 370 | 371 | 372 | [11][31:0] 373 | [11][31:0] 374 | 375 | 376 | [10][31:0] 377 | [10][31:0] 378 | 379 | 380 | [9][31:0] 381 | [9][31:0] 382 | 383 | 384 | [8][31:0] 385 | [8][31:0] 386 | 387 | 388 | [7][31:0] 389 | [7][31:0] 390 | 391 | 392 | [6][31:0] 393 | [6][31:0] 394 | 395 | 396 | [5][31:0] 397 | [5][31:0] 398 | 399 | 400 | [4][31:0] 401 | [4][31:0] 402 | 403 | 404 | [3][31:0] 405 | [3][31:0] 406 | 407 | 408 | [2][31:0] 409 | [2][31:0] 410 | UNSIGNEDDECRADIX 411 | 412 | 413 | [1][31:0] 414 | [1][31:0] 415 | 416 | 417 | [0][31:0] 418 | [0][31:0] 419 | 420 | 421 | [31][31:0] 422 | [31][31:0] 423 | 424 | 425 | [30][31:0] 426 | [30][31:0] 427 | 428 | 429 | [29][31:0] 430 | [29][31:0] 431 | 432 | 433 | [28][31:0] 434 | [28][31:0] 435 | 436 | 437 | [27][31:0] 438 | [27][31:0] 439 | 440 | 441 | [26][31:0] 442 | [26][31:0] 443 | 444 | 445 | [25][31:0] 446 | [25][31:0] 447 | 448 | 449 | [24][31:0] 450 | [24][31:0] 451 | 452 | 453 | [23][31:0] 454 | [23][31:0] 455 | 456 | 457 | [22][31:0] 458 | [22][31:0] 459 | 460 | 461 | [21][31:0] 462 | [21][31:0] 463 | 464 | 465 | [20][31:0] 466 | [20][31:0] 467 | 468 | 469 | [19][31:0] 470 | [19][31:0] 471 | 472 | 473 | [18][31:0] 474 | [18][31:0] 475 | 476 | 477 | [17][31:0] 478 | [17][31:0] 479 | 480 | 481 | [16][31:0] 482 | [16][31:0] 483 | 484 | 485 | [15][31:0] 486 | [15][31:0] 487 | 488 | 489 | [14][31:0] 490 | [14][31:0] 491 | 492 | 493 | [13][31:0] 494 | [13][31:0] 495 | 496 | 497 | [12][31:0] 498 | [12][31:0] 499 | 500 | 501 | [11][31:0] 502 | [11][31:0] 503 | 504 | 505 | [10][31:0] 506 | [10][31:0] 507 | 508 | 509 | [9][31:0] 510 | [9][31:0] 511 | 512 | 513 | [8][31:0] 514 | [8][31:0] 515 | 516 | 517 | [7][31:0] 518 | [7][31:0] 519 | 520 | 521 | [6][31:0] 522 | [6][31:0] 523 | 524 | 525 | [5][31:0] 526 | [5][31:0] 527 | 528 | 529 | [4][31:0] 530 | [4][31:0] 531 | 532 | 533 | [3][31:0] 534 | [3][31:0] 535 | 536 | 537 | [2][31:0] 538 | [2][31:0] 539 | 540 | 541 | [1][31:0] 542 | [1][31:0] 543 | 544 | 545 | [0][31:0] 546 | [0][31:0] 547 | 548 | 549 | 550 | RegFile MUX 551 | label 552 | #E0FFFF 553 | 554 | 555 | Write Back MUX 556 | label 557 | #E0FFFF 558 | 559 | 560 | ALU 561 | label 562 | #E0FFFF 563 | 564 | 565 | fwdA[1:0] 566 | fwdA[1:0] 567 | 568 | 569 | fwdB[1:0] 570 | fwdB[1:0] 571 | 572 | 573 | ID_EX_RegR1[31:0] 574 | ID_EX_RegR1[31:0] 575 | UNSIGNEDDECRADIX 576 | 577 | 578 | ALUSrcMux_out[31:0] 579 | ALUSrcMux_out[31:0] 580 | UNSIGNEDDECRADIX 581 | 582 | 583 | ALU_OprandA[31:0] 584 | ALU_OprandA[31:0] 585 | UNSIGNEDDECRADIX 586 | 587 | 588 | ALU_OprandB[31:0] 589 | ALU_OprandB[31:0] 590 | UNSIGNEDDECRADIX 591 | 592 | 593 | ALU_out[31:0] 594 | ALU_out[31:0] 595 | HEXRADIX 596 | 597 | 598 | ALU Control 599 | label 600 | #E0FFFF 601 | 602 | 603 | Branch 604 | label 605 | #E0FFFF 606 | 607 | 608 | branchTaken 609 | branchTaken 610 | 611 | 612 | Control Unit 613 | label 614 | #E0FFFF 615 | 616 | 617 | instr[31:0] 618 | instr[31:0] 619 | 620 | 621 | opcode[4:0] 622 | opcode[4:0] 623 | 624 | 625 | Branch 626 | Branch 627 | 628 | 629 | Jump[1:0] 630 | Jump[1:0] 631 | 632 | 633 | MemRead 634 | MemRead 635 | 636 | 637 | MemToReg 638 | MemToReg 639 | 640 | 641 | ALUOp[1:0] 642 | ALUOp[1:0] 643 | 644 | 645 | MemWrite 646 | MemWrite 647 | 648 | 649 | ALUSrc 650 | ALUSrc 651 | 652 | 653 | RegWrite 654 | RegWrite 655 | 656 | 657 | Mode[2:0] 658 | Mode[2:0] 659 | 660 | 661 | Lui 662 | Lui 663 | 664 | 665 | ECall 666 | ECall 667 | 668 | 669 | EBreak 670 | EBreak 671 | 672 | 673 | MRET 674 | MRET 675 | 676 | 677 | CSRWrite 678 | CSRWrite 679 | 680 | 681 | [1] 682 | [1] 683 | 684 | 685 | [4] 686 | [4] 687 | 688 | 689 | [7] 690 | [7] 691 | 692 | 693 | --------------------------------------------------------------------------------