├── .gitattributes ├── .gitignore ├── Testbench ├── Bin2Mem │ ├── Bin2Mem-BE.exe │ ├── Bin2Mem-LE.exe │ ├── Bin2Mem-BE.c │ └── Bin2Mem-LE.c ├── TLB_Test │ ├── ram.ld │ ├── Makefile │ ├── test_ram.data │ └── test.S └── Cache_Test │ ├── ram.ld │ ├── Makefile │ ├── test.S │ └── test_ram.data ├── Src ├── Cache │ ├── ICache_Ram.v │ ├── DCache_Ram.v │ ├── ICache_Controller.v │ └── DCache_Controller.v ├── Core │ ├── HiLo_LLbit.v │ ├── PC.v │ ├── Reg_IF_ID.v │ ├── WriteBack.v │ ├── Exception.v │ ├── Reg_MEM_WB.v │ ├── Reg_ID_EX.v │ ├── RegFile.v │ ├── ALU_MEM.v │ ├── Divider.v │ ├── Control.v │ ├── MMU.v │ ├── Reg_EX_MEM.v │ ├── ALU_EX.v │ ├── CP0.v │ └── TLBU.v ├── Config.v ├── NSCSCC_Top │ ├── nscscc_sram_top.v │ └── nscscc_axi_top.v ├── Xilinx_IP │ ├── DCache_Ram_IP │ │ └── DCache_Ram_IP.xci │ └── ICache_Ram_IP │ │ └── ICache_Ram_IP.xci └── MangoMIPS_Top.v ├── ChangeLog.md └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.elf 3 | *.bin 4 | *.s 5 | *.txt -------------------------------------------------------------------------------- /Testbench/Bin2Mem/Bin2Mem-BE.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RickyTino/MangoMIPS32/HEAD/Testbench/Bin2Mem/Bin2Mem-BE.exe -------------------------------------------------------------------------------- /Testbench/Bin2Mem/Bin2Mem-LE.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RickyTino/MangoMIPS32/HEAD/Testbench/Bin2Mem/Bin2Mem-LE.exe -------------------------------------------------------------------------------- /Testbench/TLB_Test/ram.ld: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | ram : ORIGIN = 0xBFC00000, LENGTH = 0x00001000 4 | } 5 | 6 | SECTIONS 7 | { 8 | .text : 9 | { 10 | *(.text) 11 | } > ram 12 | 13 | .data : 14 | { 15 | *(.data) 16 | } > ram 17 | 18 | .bss : 19 | { 20 | *(.bss) 21 | } > ram 22 | 23 | .reginfo : 24 | { 25 | *(.reginfo) 26 | } > ram 27 | } 28 | 29 | ENTRY (_start) 30 | 31 | -------------------------------------------------------------------------------- /Testbench/Cache_Test/ram.ld: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | ram : ORIGIN = 0xBFC00000, LENGTH = 0x00001000 4 | } 5 | 6 | SECTIONS 7 | { 8 | .text : 9 | { 10 | *(.text) 11 | } > ram 12 | 13 | .data : 14 | { 15 | *(.data) 16 | } > ram 17 | 18 | .bss : 19 | { 20 | *(.bss) 21 | } > ram 22 | 23 | .reginfo : 24 | { 25 | *(.reginfo) 26 | } > ram 27 | } 28 | 29 | ENTRY (_start) 30 | 31 | -------------------------------------------------------------------------------- /Testbench/Cache_Test/Makefile: -------------------------------------------------------------------------------- 1 | ifndef CROSS_COMPILE 2 | CROSS_COMPILE = mipsel-linux- 3 | endif 4 | 5 | SOURCE = test.S 6 | TARGET = test_ram 7 | 8 | CC = $(CROSS_COMPILE)as 9 | LD = $(CROSS_COMPILE)ld 10 | OBJCOPY = $(CROSS_COMPILE)objcopy 11 | OBJDUMP = $(CROSS_COMPILE)objdump 12 | 13 | OBJECTS = $(TARGET).o 14 | 15 | export CROSS_COMPILE 16 | 17 | all: $(TARGET).data 18 | 19 | $(TARGET).o: $(SOURCE) 20 | $(CC) -mips32 $< -o $@ 21 | 22 | $(TARGET).elf: ram.ld $(TARGET).o 23 | $(LD) -T ram.ld $(TARGET).o -o $@ 24 | $(OBJDUMP) -alD $@ > $(TARGET).s 25 | 26 | $(TARGET).bin: $(TARGET).elf 27 | $(OBJCOPY) -O binary $< $@ 28 | 29 | $(TARGET).data: $(TARGET).bin 30 | ../Bin2Mem/Bin2Mem-LE.exe -f $< -o $@ 31 | 32 | clean: 33 | -rm -f *.o *.elf *.bin *.data *.s 34 | -------------------------------------------------------------------------------- /Testbench/TLB_Test/Makefile: -------------------------------------------------------------------------------- 1 | ifndef CROSS_COMPILE 2 | CROSS_COMPILE = mipsel-linux- 3 | endif 4 | 5 | SOURCE = test.S 6 | TARGET = test_ram 7 | 8 | CC = $(CROSS_COMPILE)as 9 | LD = $(CROSS_COMPILE)ld 10 | OBJCOPY = $(CROSS_COMPILE)objcopy 11 | OBJDUMP = $(CROSS_COMPILE)objdump 12 | 13 | OBJECTS = $(TARGET).o 14 | 15 | export CROSS_COMPILE 16 | 17 | all: $(TARGET).data 18 | 19 | $(TARGET).o: $(SOURCE) 20 | $(CC) -mips32 $< -o $@ 21 | 22 | $(TARGET).elf: ram.ld $(TARGET).o 23 | $(LD) -T ram.ld $(TARGET).o -o $@ 24 | $(OBJDUMP) -alD $@ > $(TARGET).s 25 | 26 | $(TARGET).bin: $(TARGET).elf 27 | $(OBJCOPY) -O binary $< $@ 28 | 29 | $(TARGET).data: $(TARGET).bin 30 | ../Bin2Mem/Bin2Mem-LE.exe -f $< -o $@ 31 | 32 | clean: 33 | -rm -f *.o *.elf *.bin *.data *.s 34 | -------------------------------------------------------------------------------- /Src/Cache/ICache_Ram.v: -------------------------------------------------------------------------------- 1 | /********************MangoMIPS32******************* 2 | Filename: ICache_Ram.v 3 | Author: RickyTino 4 | Version: v1.1.3 5 | **************************************************/ 6 | `include "../Config.v" 7 | `include "../Defines.v" 8 | 9 | module ICache_Ram 10 | ( 11 | input wire clk, 12 | input wire wen, 13 | input wire [`I_ramad] adw, 14 | input wire [`I_ramad] adr, 15 | input wire [`DataBus] din, 16 | output wire [`DataBus] dout 17 | ); 18 | 19 | ICache_Ram_IP icache_ram ( 20 | .clk (clk ), 21 | .we (wen ), 22 | .a (adw ), 23 | .d (din ), 24 | .dpra (adr ), 25 | .dpo (dout ) 26 | ); 27 | 28 | endmodule -------------------------------------------------------------------------------- /ChangeLog.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | -------------------------------------------------- 3 | ## v1.1.3 4 | - 微调译码逻辑以支持ehb/jr.hb/jalr.hb三条指令 5 | - 修复了wait指令后有气泡时不响应中断的bug 6 | 7 | -------------------------------------------------- 8 | ## v1.1.2 9 | - 微调了一些宏定义的表述和代码格式 10 | - 修复致命错误:AdEL和AdES异常产生的Cause.ExcCode相反 11 | 12 | -------------------------------------------------- 13 | ## v1.1.1 14 | - 修复中断发生在访存等待中导致的bug 15 | - 该日志反序 16 | 17 | -------------------------------------------------- 18 | ## v1.1.0 19 | - 增加了可配置大小的直接映射指令/数据缓存,并实现了Cache指令 20 | - 增加可配置项:禁用用户模式 21 | - 实现了32项全相连TLB,并实现了相关CP0寄存器和指令 22 | - 外部实现为AXI总线接口 23 | - 目录结构调整,分类更加清晰 24 | - 增加了一些汇编测试程序,位于Testbench目录下 25 | - 修复若干Bug 26 | - 经测试可成功启动Linux 2.6.32 27 | 28 | -------------------------------------------------- 29 | ## v1.0.1 30 | - 增加了固定地址映射MMU在Status.ERL=1时的映射方式; 31 | - 将MMU_Inst和MMU_Data统一为同一个模块MMU,使用时分别例化。 32 | 33 | -------------------------------------------------- 34 | ## v1.0.0 35 | - 初始发布版本,详见 README.md 36 | 37 | 38 | -------------------------------------------------------------------------------- /Src/Core/HiLo_LLbit.v: -------------------------------------------------------------------------------- 1 | /********************MangoMIPS32******************* 2 | Filename: HiLo_LLbit.v 3 | Author: RickyTino 4 | Version: v1.1.3 5 | **************************************************/ 6 | `include "../Config.v" 7 | `include "../Defines.v" 8 | 9 | module HiLo_LLbit 10 | ( 11 | input wire clk, 12 | input wire rst, 13 | input wire hilo_wen, 14 | input wire [`DWord] hilo_wdata, 15 | output wire [`DWord] hilo_rdata, 16 | 17 | input wire [`ExcType] exc_type, 18 | input wire llb_wen, 19 | input wire llb_wdata, 20 | input wire mem_llb_wen, 21 | input wire mem_llbit, 22 | output wire llb_rdata 23 | ); 24 | reg [`DWord] hilo; 25 | reg llbit; 26 | 27 | always @(posedge clk, posedge rst) begin 28 | if(rst) begin 29 | hilo <= `ZeroDWord; 30 | llbit <= `Zero; 31 | end 32 | else begin 33 | if(hilo_wen) hilo <= hilo_wdata; 34 | 35 | if(exc_type == `ExcT_ERET) llbit <= `Zero; 36 | else if(llb_wen) llbit <= llb_wdata; 37 | end 38 | end 39 | 40 | assign hilo_rdata = hilo_wen ? hilo_wdata : hilo; 41 | assign llb_rdata = mem_llb_wen ? mem_llbit : 42 | llb_wen ? llb_wdata : llbit; 43 | 44 | endmodule 45 | -------------------------------------------------------------------------------- /Src/Core/PC.v: -------------------------------------------------------------------------------- 1 | /********************MangoMIPS32******************* 2 | Filename: PC.v 3 | Author: RickyTino 4 | Version: v1.1.3 5 | **************************************************/ 6 | `include "../Config.v" 7 | `include "../Defines.v" 8 | 9 | module PC 10 | ( 11 | input wire clk, 12 | input wire rst, 13 | input wire stall, 14 | input wire flush, 15 | input wire [`AddrBus] flush_pc, 16 | input wire br_flag, 17 | input wire [`AddrBus] br_addr, 18 | input wire usermode, 19 | input wire i_tlbr, 20 | input wire i_tlbi, 21 | 22 | output reg [`AddrBus] pc, 23 | output wire [`AddrBus] pcp4, 24 | output reg [`ExcBus ] excp, 25 | output reg i_en 26 | ); 27 | 28 | assign pcp4 = pc + 32'd4; 29 | 30 | always @(posedge clk, posedge rst) begin 31 | if(rst) begin 32 | pc <= `ZeroWord; 33 | i_en <= `false; 34 | end 35 | else begin 36 | i_en <= `true; 37 | casez ({stall, br_flag, flush}) 38 | 3'b000: pc <= i_en ? pcp4 : `Reset_Entrance; 39 | 3'b010: pc <= br_addr; 40 | 3'b??1: pc <= flush_pc; 41 | endcase 42 | end 43 | end 44 | 45 | always @(*) begin 46 | excp <= 0; 47 | excp[`Exc_I_AdE ] <= (pc[1:0] != 2'b0) || (usermode && pc[31]); 48 | excp[`Exc_I_TLBR] <= i_tlbr; 49 | excp[`Exc_I_TLBI] <= i_tlbi; 50 | end 51 | 52 | endmodule -------------------------------------------------------------------------------- /Src/Cache/DCache_Ram.v: -------------------------------------------------------------------------------- 1 | /********************MangoMIPS32******************* 2 | Filename: DCache_Ram.v 3 | Author: RickyTino 4 | Version: v1.1.3 5 | **************************************************/ 6 | `include "../Config.v" 7 | `include "../Defines.v" 8 | 9 | module DCache_Ram 10 | ( 11 | input wire clk, 12 | input wire enb, 13 | input wire [`ByteWEn] wea, web, 14 | input wire [`D_ramad] ada, adb, 15 | input wire [`DataBus] dina, dinb, 16 | output wire [`DataBus] dout 17 | ); 18 | 19 | wire [`D_ramad] addr = enb ? adb : ada; 20 | wire [`ByteWEn] wen = enb ? web : wea; 21 | wire [`DataBus] din = enb ? dinb : dina; 22 | 23 | DCache_Ram_IP unit0 ( 24 | .clk (clk ), 25 | .we (wen [0] ), 26 | .a (addr ), 27 | .d (din [`Byte0] ), 28 | .spo (dout[`Byte0] ) 29 | ); 30 | 31 | DCache_Ram_IP unit1 ( 32 | .clk (clk ), 33 | .we (wen [1] ), 34 | .a (addr ), 35 | .d (din [`Byte1] ), 36 | .spo (dout[`Byte1] ) 37 | ); 38 | 39 | DCache_Ram_IP unit2 ( 40 | .clk (clk ), 41 | .we (wen [2] ), 42 | .a (addr ), 43 | .d (din [`Byte2] ), 44 | .spo (dout[`Byte2] ) 45 | ); 46 | 47 | DCache_Ram_IP unit3 ( 48 | .clk (clk ), 49 | .we (wen [3] ), 50 | .a (addr ), 51 | .d (din [`Byte3] ), 52 | .spo (dout[`Byte3] ) 53 | ); 54 | 55 | endmodule -------------------------------------------------------------------------------- /Src/Core/Reg_IF_ID.v: -------------------------------------------------------------------------------- 1 | /********************MangoMIPS32******************* 2 | Filename: Reg_IF_ID.v 3 | Author: RickyTino 4 | Version: v1.1.3 5 | **************************************************/ 6 | `include "../Config.v" 7 | `include "../Defines.v" 8 | 9 | module Reg_IF_ID 10 | ( 11 | input wire clk, 12 | input wire rst, 13 | input wire stall, 14 | input wire flush, 15 | input wire clrslot, 16 | 17 | input wire [`AddrBus] if_pc, 18 | input wire [`AddrBus] if_pcp4, 19 | input wire [`DataBus] if_inst, 20 | input wire [`ExcBus ] if_excp, 21 | input wire id_isbranch, 22 | 23 | 24 | output reg [`AddrBus] id_pc, 25 | output reg [`AddrBus] id_pcp4, 26 | output reg [`DataBus] id_inst, 27 | output reg [`ExcBus ] id_excp, 28 | output reg id_inslot, 29 | output reg id_null 30 | ); 31 | 32 | always @(posedge clk, posedge rst) begin 33 | if(rst) begin 34 | id_pc <= `ZeroWord; 35 | id_pcp4 <= `ZeroWord; 36 | id_inst <= `ZeroWord; 37 | id_excp <= `Exc_NoExc; 38 | id_inslot <= `false; 39 | id_null <= `true; 40 | end 41 | else begin 42 | casez ({flush, stall, clrslot}) 43 | 3'b1??, 3'b001: begin 44 | id_pc <= `ZeroWord; 45 | id_pcp4 <= `ZeroWord; 46 | id_inst <= `ZeroWord; 47 | id_excp <= `Exc_NoExc; 48 | id_inslot <= `false; 49 | id_null <= `true; 50 | end 51 | 3'b000: begin 52 | id_pc <= if_pc; 53 | id_pcp4 <= if_pcp4; 54 | id_inst <= if_inst; 55 | id_excp <= if_excp; 56 | id_inslot <= id_isbranch; 57 | id_null <= `false; 58 | end 59 | endcase 60 | end 61 | end 62 | 63 | endmodule -------------------------------------------------------------------------------- /Src/Config.v: -------------------------------------------------------------------------------- 1 | /********************MangoMIPS32******************* 2 | Filename: Config.v 3 | Author: RickyTino 4 | Version: v1.1.3 5 | **************************************************/ 6 | 7 | // Note: The result is UNPREDICTABLE if values are set out of the range indicated. 8 | // To disable a macro definition, add a "_" to the name or simply comment it out. 9 | 10 | //------------------------CP0 Options------------------------ 11 | // Define "Disable_User_Mode" to keep processor working under kernel mode regardless 12 | // of Status.UM bit. 13 | `define Disable_User_Mode 14 | 15 | // Define "Disable_Cause_IV" to disable the IV field of CP0 Cause register. 16 | // This setting is necessary to pass NSCSCC-2018 tests. 17 | `define Disable_Cause_IV 18 | 19 | //------------------------NSCSCC Options------------------------ 20 | // Define "Reset_Cacheable" to set the reset state of Config.K0/KU/K23 to a cacheable 21 | // state (value 3'd3). 22 | `define _Reset_Cacheable 23 | 24 | // Define "IF_Force_Cached" to set the cacheability of all instruction fetch 25 | // to a cacheable state. 26 | // Note that coherency problems might occur under other circumstances. It is strongly 27 | // NOT recommended to set this option when applying this CPU to any use other than 28 | // the NSCSCC tests. 29 | `define _IF_Force_Cached 30 | 31 | //------------------------MMU & Cache Options------------------------ 32 | // Define "Fixed_Mapping_MMU" to implement a Fixed Mapping MMU. 33 | // Otherwise implements a standard TLB-Based MMU. 34 | `define _Fixed_Mapping_MMU 35 | 36 | // The value of "ICache_N" and "DCache_N" refers to the size of inst-cache and 37 | // data-cache as described below: 38 | // Cache_Size | 2KB 4KB 8KB 16KB 32KB 64KB 128KB 39 | // Cache_N | 0 1 2 3 4 5 6 40 | // Note that the result is UNPREDICTABLE if this value is set different from the 41 | // actual size of the implemented cache memory. 42 | `define ICache_N 2 43 | `define DCache_N 2 44 | 45 | //------------------------Simulation Options------------------------ 46 | // Define "Output_Exception_Info" to output exception information to console during 47 | // simulation when exceptions occur. 48 | `define _Output_Exception_Info 49 | 50 | //------------------------------------------------ -------------------------------------------------------------------------------- /Src/Core/WriteBack.v: -------------------------------------------------------------------------------- 1 | /********************MangoMIPS32******************* 2 | Filename: WriteBack.v 3 | Author: RickyTino 4 | Version: v1.1.3 5 | **************************************************/ 6 | `include "../Config.v" 7 | `include "../Defines.v" 8 | 9 | module WriteBack 10 | ( 11 | input wire [`ALUOp ] aluop, 12 | input wire [`DataBus] alures, 13 | input wire [`DataBus] mulres, 14 | input wire [`AddrBus] m_vaddr, 15 | input wire [`DataBus] m_rdata, 16 | output reg [`DataBus] wrdata, 17 | output wire stallreq 18 | ); 19 | 20 | assign stallreq = (aluop == `ALU_WAIT); 21 | 22 | always @(*) begin 23 | case (aluop) 24 | `ALU_LB: begin 25 | case (m_vaddr[1:0]) 26 | 2'b00: wrdata <= {{24{m_rdata[ 7]}}, m_rdata[ 7: 0]}; 27 | 2'b01: wrdata <= {{24{m_rdata[15]}}, m_rdata[15: 8]}; 28 | 2'b10: wrdata <= {{24{m_rdata[23]}}, m_rdata[23:16]}; 29 | 2'b11: wrdata <= {{24{m_rdata[31]}}, m_rdata[31:24]}; 30 | endcase 31 | end 32 | 33 | `ALU_LBU: begin 34 | case (m_vaddr[1:0]) 35 | 2'b00: wrdata <= {24'b0, m_rdata[ 7: 0]}; 36 | 2'b01: wrdata <= {24'b0, m_rdata[15: 8]}; 37 | 2'b10: wrdata <= {24'b0, m_rdata[23:16]}; 38 | 2'b11: wrdata <= {24'b0, m_rdata[31:24]}; 39 | endcase 40 | end 41 | 42 | `ALU_LH: begin 43 | case (m_vaddr[1:0]) 44 | 2'b00: wrdata <= {{16{m_rdata[15]}}, m_rdata[15: 0]}; 45 | 2'b10: wrdata <= {{16{m_rdata[31]}}, m_rdata[31:16]}; 46 | default: wrdata <= `ZeroWord; 47 | endcase 48 | end 49 | 50 | `ALU_LHU: begin 51 | case (m_vaddr[1:0]) 52 | 2'b00: wrdata <= {16'b0, m_rdata[15: 0]}; 53 | 2'b10: wrdata <= {16'b0, m_rdata[31:16]}; 54 | default: wrdata <= `ZeroWord; 55 | endcase 56 | end 57 | 58 | `ALU_LW, 59 | `ALU_LL: begin 60 | wrdata <= m_rdata; 61 | end 62 | 63 | `ALU_LWL: begin 64 | case (m_vaddr[1:0]) 65 | 2'b00: wrdata <= {m_rdata[ 7:0], 24'b0}; 66 | 2'b01: wrdata <= {m_rdata[15:0], 16'b0}; 67 | 2'b10: wrdata <= {m_rdata[23:0], 8'b0}; 68 | 2'b11: wrdata <= m_rdata[31:0]; 69 | endcase 70 | end 71 | 72 | `ALU_LWR: begin 73 | case (m_vaddr[1:0]) 74 | 2'b00: wrdata <= m_rdata[31: 0]; 75 | 2'b01: wrdata <= { 8'b0, m_rdata[31: 8]}; 76 | 2'b10: wrdata <= {16'b0, m_rdata[31:16]}; 77 | 2'b11: wrdata <= {24'b0, m_rdata[31:24]}; 78 | endcase 79 | end 80 | 81 | `ALU_MUL: wrdata <= mulres; 82 | default: wrdata <= alures; 83 | endcase 84 | end 85 | 86 | endmodule -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MangoMIPS32 2 | MangoMIPS32 is a soft-core microprocessor written in Verilog HDL. It is compliant to MIPS32 release 1 architecture. 3 | 4 | ## Current Version 5 | MangoMIPS32 v1.1.3 6 | This version succeded running Linux 2.6.32 7 | 8 | ## CPU Core 9 | - Supports 100 instructions in MIPS32r1 ISA (Listed below) 10 | - Single-issued 5-stage pipeline structure 11 | - Speed: 100MHz on -2 level Xilinx XC7A200T FPGA Chip 12 | - No floating point units 13 | 14 | ## Interface and Caches 15 | - Implemented AMBA-AXI as on-chip bus interface 16 | - Instruction cache and data cache build with Xilinx Distributed Ram IP Core 17 | - Write-back, write-allocate, direct-mapped caches 18 | - size-configurable (2KB-128KB) 19 | 20 | ## Privilege Resources 21 | - Implemented 20 coprocessor 0 (CP0) registers 22 | - Support user mode (could be disabled with macros) 23 | - Avoided all CP0 Execution Hazards 24 | 25 | ## Address Mapping 26 | - Supports both Fixed-mapping MMU and TLB-based MMU 27 | - 32-items full-associative TLB 28 | - Support multiple page sizes starting from 4KB 29 | 30 | ## Details 31 | Instructions supported: 32 | - SLL/SRL/SRA/SLLV/SRLV/SRAV 33 | - SYNC/PREF (Decode as NOP) 34 | - AND/OR/XOR/NOR 35 | - MOVZ/MOVN/MFHI/MFLO/MTHI/MTLO 36 | - ANDI/ORI/XORI/LUI 37 | - ADD/ADDU/SUB/SUBU/SLT/SLTU/CLO/CLZ 38 | - ADDI/ADDIU/SLTI/SLTIU 39 | - MUL/MULT/MULTU/MADD/MADDU/MSUB/MSUBU/DIV/DIVU 40 | - J/JAL/JR/JALR 41 | - BEQ/BNE/BGTZ/BLEZ/BGEZ/BGEZAL/BLTZ/BLTZAL 42 | - BEQL/BNEL/BGTZL/BLEZL/BGEZL/BGEZALL/BLTZL/BLTZALL 43 | - LB/LBU/LH/LHU/LW/LWL/LWR/LL 44 | - SB/SH/SW/SWL/SWR/SC 45 | - MFC0/MTC0 46 | - SYSCALL/BREAK/ERET/WAIT 47 | - TEQ/TNE/TGE/TGEU/TLT/TLTU 48 | - TEQI/TNEI/TGEI/TGEIU/TLTI/TLTIU 49 | - TLBP/TLBWI/TLBWR/TLBR 50 | - CACHE: 51 | - I-Index Invalidate 52 | - D-Index Writeback Invalidate 53 | - I-Index Store Tag 54 | - D-Index Store Tag 55 | - I-Hit Invalidate 56 | - D-Hit Invalidate 57 | - D-Hit Writeback Invalidate 58 | 59 | CP0 Registers: 60 | 61 | | Name |Reg#|Sel#| 62 | |:---------|:--:|:--:| 63 | | Index | 0 | 0 | 64 | | Random | 1 | 0 | 65 | | EntryLo0 | 2 | 0 | 66 | | EntryLo1 | 3 | 0 | 67 | | Context | 4 | 0 | 68 | | PageMask | 5 | 0 | 69 | | Wired | 6 | 0 | 70 | | BadVAddr | 8 | 0 | 71 | | Count | 9 | 0 | 72 | | EntryHi | 10 | 0 | 73 | | Compare | 11 | 0 | 74 | | Status | 12 | 0 | 75 | | Cause | 13 | 0 | 76 | | EPC | 14 | 0 | 77 | | PrId | 15 | 0 | 78 | | Config | 16 | 0 | 79 | | Config1 | 16 | 1 | 80 | | TagLo | 28 | 0 | 81 | | TagHi | 29 | 0 | 82 | | ErrorEPC | 30 | 0 | 83 | 84 | Exceptions (priority ranking): 85 | - Reset 86 | - Interrupt 87 | - I-Address Error 88 | - I-TLB Refill 89 | - I-TLB Invalid 90 | - Coprocessor Unusable 91 | - Reserved Instruction 92 | - Overflow / Trap / Syscall / Breakpoint 93 | - D-Address Error 94 | - D-TLB Refill 95 | - D-TLB Invalid 96 | - D-TLB Modified 97 | - ERET 98 | 99 | ## Related Work 100 | MangoMIPS32 has an AXI master interface and can fit in these designs: 101 | - [NSCSCC](http://www.nscscc.org/) Environments 102 | - [HypoSoC_IoT](https://github.com/hitwh-nscscc/hyposoc_iot) 103 | - [CatnipSoC](https://github.com/RickyTino/CatnipSoC) 104 | -------------------------------------------------------------------------------- /Src/Core/Exception.v: -------------------------------------------------------------------------------- 1 | /********************MangoMIPS32******************* 2 | Filename: Exception.v 3 | Author: RickyTino 4 | Version: v1.1.3 5 | **************************************************/ 6 | `include "../Config.v" 7 | `include "../Defines.v" 8 | 9 | module Exception 10 | ( 11 | 12 | input wire [`ExcBus ] excp_i, 13 | input wire d_tlbr, 14 | input wire d_tlbi, 15 | input wire d_tlbm, 16 | input wire d_refs, 17 | input wire exc_intr, 18 | 19 | input wire [`AddrBus] pc, 20 | input wire m_en, 21 | input wire [`AddrBus] m_vaddr, 22 | input wire nullinst, 23 | 24 | output wire exc_flag, 25 | output reg exc_save, 26 | output reg [`ExcType] exc_type, 27 | output reg [`AddrBus] exc_baddr 28 | ); 29 | 30 | reg [`ExcBus] excp; 31 | 32 | always @(*) begin 33 | excp <= `Exc_NoExc; 34 | if(!nullinst) begin 35 | excp <= excp_i; 36 | excp[`Exc_Intr ] <= exc_intr & ~m_en; 37 | excp[`Exc_D_TLBR] <= d_tlbr; 38 | excp[`Exc_D_TLBI] <= d_tlbi; 39 | excp[`Exc_D_TLBM] <= d_tlbm; 40 | end 41 | end 42 | 43 | assign exc_flag = (excp != `Exc_NoExc); 44 | 45 | always @(*) begin 46 | casez (excp) 47 | // `Exc_W'b?????????????????1: exc_type <= `ExcT_NMI; //NMI 48 | `Exc_W'b????????????????10: exc_type <= `ExcT_Intr; 49 | `Exc_W'b???????????????100: exc_type <= `ExcT_AdE; 50 | `Exc_W'b??????????????1000: exc_type <= `ExcT_TLBR; 51 | `Exc_W'b?????????????10000: exc_type <= `ExcT_TLBI; 52 | `Exc_W'b????????????100000: exc_type <= `ExcT_IBE; 53 | `Exc_W'b???????????1000000: exc_type <= `ExcT_CpU; 54 | `Exc_W'b??????????10000000: exc_type <= `ExcT_RI; 55 | `Exc_W'b?????????100000000: exc_type <= `ExcT_Ov; 56 | `Exc_W'b????????1000000000: exc_type <= `ExcT_Trap; 57 | `Exc_W'b???????10000000000: exc_type <= `ExcT_SysC; 58 | `Exc_W'b??????100000000000: exc_type <= `ExcT_Bp; 59 | `Exc_W'b?????1000000000000: exc_type <= `ExcT_AdE; 60 | `Exc_W'b????10000000000000: exc_type <= `ExcT_TLBR; 61 | `Exc_W'b???100000000000000: exc_type <= `ExcT_TLBI; 62 | `Exc_W'b??1000000000000000: exc_type <= `ExcT_TLBM; 63 | `Exc_W'b?10000000000000000: exc_type <= `ExcT_DBE; 64 | `Exc_W'b100000000000000000: exc_type <= `ExcT_ERET; 65 | default: exc_type <= `ExcT_NoExc; 66 | endcase 67 | 68 | casez (excp) 69 | `Exc_W'b???????????????100, 70 | `Exc_W'b??????????????1000, 71 | `Exc_W'b?????????????10000: begin 72 | exc_baddr <= pc; 73 | exc_save <= `false; 74 | end 75 | 76 | `Exc_W'b?????1000000000000, 77 | `Exc_W'b????10000000000000, 78 | `Exc_W'b???100000000000000, 79 | `Exc_W'b??1000000000000000: begin 80 | exc_baddr <= m_vaddr; 81 | exc_save <= d_refs; 82 | end 83 | 84 | default: begin 85 | exc_baddr <= `ZeroWord; 86 | exc_save <= d_refs; 87 | end 88 | endcase 89 | end 90 | 91 | endmodule -------------------------------------------------------------------------------- /Src/Core/Reg_MEM_WB.v: -------------------------------------------------------------------------------- 1 | /********************MangoMIPS32******************* 2 | Filename: Reg_MEM_WB.v 3 | Author: RickyTino 4 | Version: v1.1.3 5 | **************************************************/ 6 | `include "../Config.v" 7 | `include "../Defines.v" 8 | 9 | module Reg_MEM_WB 10 | ( 11 | input wire clk, 12 | input wire rst, 13 | input wire stall, 14 | input wire flush, 15 | 16 | input wire [`AddrBus] mem_pc, 17 | input wire [`ALUOp ] mem_aluop, 18 | input wire [`DataBus] mem_alures, 19 | input wire [`DataBus] mem_mulres, 20 | input wire [`AddrBus] mem_m_vaddr, 21 | input wire [`DataBus] mem_m_rdata, 22 | input wire [`ByteWEn] mem_wreg, 23 | input wire [`RegAddr] mem_wraddr, 24 | input wire mem_hilo_wen, 25 | input wire [`DWord ] mem_hilo, 26 | input wire mem_llb_wen, 27 | input wire mem_llbit, 28 | 29 | output reg [`AddrBus] wb_pc, 30 | output reg [`ALUOp ] wb_aluop, 31 | output reg [`DataBus] wb_alures, 32 | output reg [`DataBus] wb_mulres, 33 | output reg [`AddrBus] wb_m_vaddr, 34 | output reg [`DataBus] wb_m_rdata, 35 | output reg [`ByteWEn] wb_wreg, 36 | output reg [`RegAddr] wb_wraddr, 37 | output reg wb_hilo_wen, 38 | output reg [`DWord ] wb_hilo, 39 | output reg wb_llb_wen, 40 | output reg wb_llbit 41 | ); 42 | 43 | always @(posedge clk, posedge rst) begin 44 | if(rst) begin 45 | wb_pc <= `ZeroWord; 46 | wb_aluop <= `ALU_NOP; 47 | wb_alures <= `ZeroWord; 48 | wb_mulres <= `ZeroWord; 49 | wb_m_vaddr <= `ZeroWord; 50 | wb_m_rdata <= `ZeroWord; 51 | wb_wreg <= `WrDisable; 52 | wb_wraddr <= `ZeroReg; 53 | wb_hilo_wen <= `false; 54 | wb_hilo <= `ZeroDWord; 55 | wb_llb_wen <= `false; 56 | wb_llbit <= `Zero; 57 | end 58 | else begin 59 | case ({flush, stall}) 60 | 2'b10, 2'b11: begin 61 | wb_pc <= `ZeroWord; 62 | wb_aluop <= `ALU_NOP; 63 | wb_alures <= `ZeroWord; 64 | wb_mulres <= `ZeroWord; 65 | wb_m_vaddr <= `ZeroWord; 66 | wb_m_rdata <= `ZeroWord; 67 | wb_wreg <= `WrDisable; 68 | wb_wraddr <= `ZeroReg; 69 | wb_hilo_wen <= `false; 70 | wb_hilo <= `ZeroDWord; 71 | wb_llb_wen <= `false; 72 | wb_llbit <= `Zero; 73 | end 74 | 2'b00: begin 75 | wb_pc <= mem_pc; 76 | wb_aluop <= mem_aluop; 77 | wb_alures <= mem_alures; 78 | wb_mulres <= mem_mulres; 79 | wb_m_vaddr <= mem_m_vaddr; 80 | wb_m_rdata <= mem_m_rdata; 81 | wb_wreg <= mem_wreg; 82 | wb_wraddr <= mem_wraddr; 83 | wb_hilo_wen <= mem_hilo_wen; 84 | wb_hilo <= mem_hilo; 85 | wb_llb_wen <= mem_llb_wen; 86 | wb_llbit <= mem_llbit; 87 | end 88 | endcase 89 | end 90 | end 91 | 92 | endmodule -------------------------------------------------------------------------------- /Testbench/Bin2Mem/Bin2Mem-BE.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | char *option_invalid = NULL; 5 | char *option_file_in = NULL; 6 | char *option_file_out = NULL; 7 | 8 | FILE *file_in_descriptor = NULL; 9 | FILE *file_out_descriptor = NULL; 10 | 11 | void exception_handler(int code) { 12 | switch (code) { 13 | case 0: 14 | break; 15 | case 10001: 16 | printf("Error (10001): No option recognized.\n"); 17 | printf("Please specify at least one valid option.\n"); 18 | break; 19 | case 10002: 20 | printf("Error (10002): Invalid option: %s\n", option_invalid); 21 | break; 22 | case 10003: 23 | printf("Error (10003): No input Binary file specified.\n"); 24 | break; 25 | case 10004: 26 | printf("Error (10004): Cannot open file: %s\n", option_file_in); 27 | break; 28 | case 10005: 29 | printf("Error (10005): Cannot create file: %s\n", option_file_out); 30 | break; 31 | default: 32 | break; 33 | } 34 | 35 | if (file_in_descriptor != NULL) { 36 | fclose(file_in_descriptor); 37 | } 38 | if (file_out_descriptor != NULL) { 39 | fclose(file_out_descriptor); 40 | } 41 | exit(0); 42 | } 43 | 44 | int main(int argc, char **argv) { 45 | 46 | int i=0,j=0; 47 | unsigned char temp1,temp2,temp3,temp4; 48 | unsigned int option_flag = 0; 49 | 50 | while (argc > 0) { 51 | if (**argv == '-') { 52 | (*argv) ++; 53 | switch (**argv) { 54 | case 'f': 55 | option_flag |= 0x4; 56 | argv ++; 57 | option_file_in = *argv; 58 | argc --; 59 | break; 60 | case 'o': 61 | option_flag |= 0x8; 62 | argv ++; 63 | option_file_out = *argv; 64 | argc --; 65 | break; 66 | default: 67 | option_flag |= 0x1; 68 | (*argv) --; 69 | option_invalid = *argv; 70 | break; 71 | } 72 | } 73 | argv ++; 74 | argc --; 75 | } 76 | 77 | 78 | file_in_descriptor = fopen(option_file_in, "rb"); 79 | if (file_in_descriptor == NULL) { 80 | exception_handler(10004); 81 | } 82 | 83 | file_out_descriptor = fopen(option_file_out, "w"); 84 | if (file_out_descriptor == NULL) { 85 | exception_handler(10005); 86 | } 87 | 88 | 89 | 90 | while (!feof(file_in_descriptor)) { 91 | 92 | fscanf(file_in_descriptor, "%c", &temp1); 93 | fscanf(file_in_descriptor, "%c", &temp2); 94 | fscanf(file_in_descriptor, "%c", &temp3); 95 | fscanf(file_in_descriptor, "%c", &temp4); 96 | 97 | if(!feof(file_in_descriptor)) 98 | { 99 | fprintf(file_out_descriptor, "%02x", temp1); 100 | fprintf(file_out_descriptor, "%02x", temp2); 101 | fprintf(file_out_descriptor, "%02x", temp3); 102 | fprintf(file_out_descriptor, "%02x", temp4); 103 | fprintf(file_out_descriptor, "\n"); 104 | } 105 | 106 | 107 | 108 | } 109 | 110 | exception_handler(0); 111 | return 0; 112 | } 113 | 114 | -------------------------------------------------------------------------------- /Src/Core/Reg_ID_EX.v: -------------------------------------------------------------------------------- 1 | /********************MangoMIPS32******************* 2 | Filename: Reg_ID_EX.v 3 | Author: RickyTino 4 | Version: v1.1.3 5 | **************************************************/ 6 | `include "../Config.v" 7 | `include "../Defines.v" 8 | 9 | module Reg_ID_EX 10 | ( 11 | input wire clk, 12 | input wire rst, 13 | input wire stall, 14 | input wire flush, 15 | 16 | input wire [`AddrBus] id_pc, 17 | input wire [`ALUOp ] id_aluop, 18 | input wire [`CacheOp] id_cacheop, 19 | input wire [`DataBus] id_opr1, 20 | input wire [`DataBus] id_opr2, 21 | input wire [`DataBus] id_offset, 22 | input wire [`CP0Addr] id_cp0sel, 23 | input wire id_wreg, 24 | input wire [`RegAddr] id_wraddr, 25 | input wire [`ExcBus ] id_excp, 26 | input wire [`CPNum ] id_ecpnum, 27 | input wire id_inslot, 28 | input wire id_null, 29 | 30 | output reg [`AddrBus] ex_pc, 31 | output reg [`ALUOp ] ex_aluop, 32 | output reg [`CacheOp] ex_cacheop, 33 | output reg [`DataBus] ex_opr1, 34 | output reg [`DataBus] ex_opr2, 35 | output reg [`DataBus] ex_offset, 36 | output reg [`CP0Addr] ex_cp0sel, 37 | output reg ex_wreg, 38 | output reg [`RegAddr] ex_wraddr, 39 | output reg [`ExcBus ] ex_excp, 40 | output reg [`CPNum ] ex_ecpnum, 41 | output reg ex_inslot, 42 | output reg ex_null 43 | ); 44 | 45 | always @(posedge clk, posedge rst) begin 46 | if(rst) begin 47 | ex_pc <= `ZeroWord; 48 | ex_aluop <= `ALU_NOP; 49 | ex_cacheop <= `COP_NOP; 50 | ex_opr1 <= `ZeroWord; 51 | ex_opr2 <= `ZeroWord; 52 | ex_offset <= `ZeroWord; 53 | ex_cp0sel <= `CP0_ZeroReg; 54 | ex_wreg <= `false; 55 | ex_wraddr <= `ZeroReg; 56 | ex_excp <= `Exc_NoExc; 57 | ex_ecpnum <= `CP0; 58 | ex_inslot <= `false; 59 | ex_null <= `true; 60 | end 61 | else begin 62 | case ({flush, stall}) 63 | 2'b10, 2'b11: begin 64 | ex_pc <= `ZeroWord; 65 | ex_aluop <= `ALU_NOP; 66 | ex_cacheop <= `COP_NOP; 67 | ex_opr1 <= `ZeroWord; 68 | ex_opr2 <= `ZeroWord; 69 | ex_offset <= `ZeroWord; 70 | ex_cp0sel <= `CP0_ZeroReg; 71 | ex_wreg <= `false; 72 | ex_wraddr <= `ZeroReg; 73 | ex_excp <= `Exc_NoExc; 74 | ex_ecpnum <= `CP0; 75 | ex_inslot <= `false; 76 | ex_null <= `true; 77 | end 78 | 2'b00: begin 79 | ex_pc <= id_pc; 80 | ex_aluop <= id_aluop; 81 | ex_cacheop <= id_cacheop; 82 | ex_opr1 <= id_opr1; 83 | ex_opr2 <= id_opr2; 84 | ex_offset <= id_offset; 85 | ex_cp0sel <= id_cp0sel; 86 | ex_wreg <= id_wreg; 87 | ex_wraddr <= id_wraddr; 88 | ex_excp <= id_excp; 89 | ex_ecpnum <= id_ecpnum; 90 | ex_inslot <= id_inslot; 91 | ex_null <= id_null; 92 | end 93 | endcase 94 | end 95 | end 96 | 97 | endmodule -------------------------------------------------------------------------------- /Src/Core/RegFile.v: -------------------------------------------------------------------------------- 1 | /********************MangoMIPS32******************* 2 | Filename: RegFile.v 3 | Author: RickyTino 4 | Version: v1.1.3 5 | **************************************************/ 6 | `include "../Config.v" 7 | `include "../Defines.v" 8 | 9 | module RegFile 10 | ( 11 | input wire clk, 12 | input wire rst, 13 | 14 | input wire re1, 15 | input wire [`RegAddr] r1addr, 16 | output reg [`DataBus] r1data, 17 | 18 | input wire re2, 19 | input wire [`RegAddr] r2addr, 20 | output reg [`DataBus] r2data, 21 | 22 | input wire [`ByteWEn] we, 23 | input wire [`RegAddr] waddr, 24 | input wire [`DataBus] wdata, 25 | 26 | input wire [`ByteWEn] ex_wreg, 27 | input wire [`RegAddr] ex_wraddr, 28 | input wire [`DataBus] ex_alures, 29 | input wire [`ByteWEn] mem_wreg, 30 | input wire [`RegAddr] mem_wraddr, 31 | input wire [`DataBus] mem_alures, 32 | 33 | output wire hazard_ex, 34 | output wire hazard_mem 35 | ); 36 | 37 | reg [`Word] GPR [0:31]; 38 | integer j; 39 | 40 | initial begin 41 | for(j = 0; j < 32; j = j + 1) 42 | GPR[j] <= `ZeroWord; 43 | end 44 | 45 | always @(posedge clk) begin 46 | if(waddr != `ZeroReg) begin 47 | if(we[0]) GPR[waddr][`Byte0] <= wdata[`Byte0]; 48 | if(we[1]) GPR[waddr][`Byte1] <= wdata[`Byte1]; 49 | if(we[2]) GPR[waddr][`Byte2] <= wdata[`Byte2]; 50 | if(we[3]) GPR[waddr][`Byte3] <= wdata[`Byte3]; 51 | end 52 | end 53 | 54 | wire r1_rvalid = re1 && (r1addr != `ZeroReg); 55 | wire [`ByteWEn] r1_ex_haz = ex_wreg & {4{(r1addr ^ ex_wraddr) == 0}}; 56 | wire [`ByteWEn] r1_mem_haz = mem_wreg & {4{(r1addr ^ mem_wraddr) == 0}}; 57 | wire [`ByteWEn] r1_wb_haz = we & {4{(r1addr ^ waddr) == 0}}; 58 | 59 | wire r2_rvalid = re2 && (r2addr != `ZeroReg); 60 | wire [`ByteWEn] r2_ex_haz = ex_wreg & {4{(r2addr ^ ex_wraddr) == 0}}; 61 | wire [`ByteWEn] r2_mem_haz = mem_wreg & {4{(r2addr ^ mem_wraddr) == 0}}; 62 | wire [`ByteWEn] r2_wb_haz = we & {4{(r2addr ^ waddr) == 0}}; 63 | 64 | `define ByteI 8*i+7 : 8*i 65 | 66 | genvar i; 67 | generate 68 | for(i = 0; i < 4; i = i + 1) begin 69 | always @(*) begin 70 | casez ({r1_rvalid, r1_ex_haz[i], r1_mem_haz[i], r1_wb_haz[i]}) 71 | 4'b0???: r1data[`ByteI] <= `ZeroByte; 72 | 4'b11??: r1data[`ByteI] <= ex_alures [`ByteI]; 73 | 4'b101?: r1data[`ByteI] <= mem_alures [`ByteI]; 74 | 4'b1001: r1data[`ByteI] <= wdata [`ByteI]; 75 | default: r1data[`ByteI] <= GPR[r1addr][`ByteI]; 76 | endcase 77 | 78 | casez ({r2_rvalid, r2_ex_haz[i], r2_mem_haz[i], r2_wb_haz[i]}) 79 | 4'b0???: r2data[`ByteI] <= `ZeroByte; 80 | 4'b11??: r2data[`ByteI] <= ex_alures [`ByteI]; 81 | 4'b101?: r2data[`ByteI] <= mem_alures [`ByteI]; 82 | 4'b1001: r2data[`ByteI] <= wdata [`ByteI]; 83 | default: r2data[`ByteI] <= GPR[r2addr][`ByteI]; 84 | endcase 85 | end 86 | end 87 | endgenerate 88 | 89 | assign hazard_ex = ((r1_ex_haz != `WrDisable) && r1_rvalid) || 90 | ((r2_ex_haz != `WrDisable) && r2_rvalid); 91 | assign hazard_mem = ((r1_mem_haz != `WrDisable) && r1_rvalid) || 92 | ((r2_mem_haz != `WrDisable) && r2_rvalid); 93 | 94 | endmodule -------------------------------------------------------------------------------- /Src/NSCSCC_Top/nscscc_sram_top.v: -------------------------------------------------------------------------------- 1 | module mycpu_top 2 | ( 3 | input wire clk, 4 | input wire resetn, 5 | input wire [ 5:0] int, 6 | 7 | input wire [31:0] inst_sram_rdata, 8 | output wire inst_sram_en, 9 | output wire [ 3:0] inst_sram_wen, 10 | output wire [31:0] inst_sram_addr, 11 | output wire [31:0] inst_sram_wdata, 12 | 13 | input wire [31:0] data_sram_rdata, 14 | output wire data_sram_en, 15 | output wire [ 3:0] data_sram_wen, 16 | output wire [31:0] data_sram_addr, 17 | output wire [31:0] data_sram_wdata, 18 | 19 | output wire [31:0] debug_wb_pc, 20 | output wire [ 3:0] debug_wb_rf_wen, 21 | output wire [ 4:0] debug_wb_rf_wnum, 22 | output wire [31:0] debug_wb_rf_wdata 23 | ); 24 | 25 | wire ibus_en; 26 | wire [`AddrBus] ibus_addr; 27 | wire [`DataBus] ibus_rdata; 28 | wire ibus_streq; 29 | 30 | wire dbus_en; 31 | wire [`AddrBus] dbus_addr; 32 | wire [`DataBus] dbus_rdata; 33 | wire [`ByteWEn] dbus_wen; 34 | wire [`DataBus] dbus_wdata; 35 | wire dbus_streq; 36 | 37 | MangoMIPS_Core_Top CPU ( 38 | .clk (clk ), 39 | .rst (!resetn ), 40 | .intr (int ), 41 | 42 | .ibus_en (ibus_en ), 43 | .ibus_addr (ibus_addr ), 44 | .ibus_rdata (ibus_rdata), 45 | .ibus_streq (ibus_streq), 46 | 47 | .dbus_en (dbus_en ), 48 | .dbus_wen (dbus_wen ), 49 | .dbus_addr (dbus_addr ), 50 | .dbus_wdata (dbus_wdata), 51 | .dbus_rdata (dbus_rdata), 52 | .dbus_streq (dbus_streq), 53 | 54 | .debug_wb_pc (debug_wb_pc), 55 | .debug_wb_wreg (debug_wb_rf_wen), 56 | .debug_wb_wraddr (debug_wb_rf_wnum), 57 | .debug_wb_wrdata (debug_wb_rf_wdata) 58 | ); 59 | 60 | assign inst_sram_en = ibus_en; 61 | assign inst_sram_wen = 4'b0; 62 | assign inst_sram_addr = ibus_addr; 63 | assign inst_sram_wdata = 32'b0; 64 | 65 | assign data_sram_en = dbus_en; 66 | assign data_sram_wen = dbus_wen; 67 | assign data_sram_addr = dbus_addr; 68 | assign data_sram_wdata = dbus_wdata; 69 | 70 | assign ibus_rdata = inst_sram_rdata; 71 | assign dbus_rdata = data_sram_rdata; 72 | 73 | reg istate, dstate; 74 | reg [31:0] i_addr, d_addr; 75 | 76 | wire i_hit = ibus_addr == i_addr; 77 | wire d_hit = dbus_addr == d_addr; 78 | 79 | assign ibus_streq = ibus_en && !i_hit; 80 | assign dbus_streq = dbus_en && !d_hit; 81 | 82 | always @(posedge clk, negedge resetn) begin 83 | if(!resetn) begin 84 | istate <= 1'b0; 85 | dstate <= 1'b0; 86 | i_addr <= 32'b0; 87 | d_addr <= 32'b0; 88 | end 89 | else begin 90 | case (istate) 91 | 1'b0: if(ibus_en && !i_hit) begin 92 | istate <= 1'b1; 93 | i_addr <= ibus_addr; 94 | end 95 | 1'b1: begin 96 | istate <= 1'b0; 97 | i_addr <= 32'b0; 98 | end 99 | endcase 100 | 101 | case (dstate) 102 | 1'b0: if(dbus_en && !d_hit) begin 103 | dstate <= 1'b1; 104 | d_addr <= dbus_addr; 105 | end 106 | 1'b1: begin 107 | dstate <= 1'b0; 108 | d_addr <= 32'b0; 109 | end 110 | endcase 111 | end 112 | end 113 | 114 | endmodule -------------------------------------------------------------------------------- /Testbench/Bin2Mem/Bin2Mem-LE.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | char *option_invalid = NULL; 5 | char *option_file_in = NULL; 6 | char *option_file_out = NULL; 7 | 8 | FILE *file_in_descriptor = NULL; 9 | FILE *file_out_descriptor = NULL; 10 | 11 | void exception_handler(int code) { 12 | switch (code) { 13 | case 0: 14 | break; 15 | case 10001: 16 | printf("Error (10001): No option recognized.\n"); 17 | printf("Please specify at least one valid option.\n"); 18 | break; 19 | case 10002: 20 | printf("Error (10002): Invalid option: %s\n", option_invalid); 21 | break; 22 | case 10003: 23 | printf("Error (10003): No input Binary file specified.\n"); 24 | break; 25 | case 10004: 26 | printf("Error (10004): Cannot open file: %s\n", option_file_in); 27 | break; 28 | case 10005: 29 | printf("Error (10005): Cannot create file: %s\n", option_file_out); 30 | break; 31 | default: 32 | break; 33 | } 34 | 35 | if (file_in_descriptor != NULL) { 36 | fclose(file_in_descriptor); 37 | } 38 | if (file_out_descriptor != NULL) { 39 | fclose(file_out_descriptor); 40 | } 41 | exit(0); 42 | } 43 | 44 | int main(int argc, char **argv) { 45 | 46 | int i=0,j=0; 47 | unsigned char temp1,temp2,temp3,temp4; 48 | unsigned int option_flag = 0; 49 | 50 | while (argc > 0) { 51 | if (**argv == '-') { 52 | (*argv) ++; 53 | switch (**argv) { 54 | case 'f': 55 | option_flag |= 0x4; 56 | argv ++; 57 | option_file_in = *argv; 58 | argc --; 59 | break; 60 | case 'o': 61 | option_flag |= 0x8; 62 | argv ++; 63 | option_file_out = *argv; 64 | argc --; 65 | break; 66 | default: 67 | option_flag |= 0x1; 68 | (*argv) --; 69 | option_invalid = *argv; 70 | break; 71 | } 72 | } 73 | argv ++; 74 | argc --; 75 | } 76 | 77 | 78 | file_in_descriptor = fopen(option_file_in, "rb"); 79 | if (file_in_descriptor == NULL) { 80 | exception_handler(10004); 81 | } 82 | 83 | file_out_descriptor = fopen(option_file_out, "w"); 84 | if (file_out_descriptor == NULL) { 85 | exception_handler(10005); 86 | } 87 | 88 | 89 | 90 | while (!feof(file_in_descriptor)) { 91 | 92 | fscanf(file_in_descriptor, "%c", &temp1); 93 | fscanf(file_in_descriptor, "%c", &temp2); 94 | fscanf(file_in_descriptor, "%c", &temp3); 95 | fscanf(file_in_descriptor, "%c", &temp4); 96 | 97 | if(!feof(file_in_descriptor)) 98 | { 99 | /* 100 | fprintf(file_out_descriptor, "%02x", temp1); 101 | fprintf(file_out_descriptor, "%02x", temp2); 102 | fprintf(file_out_descriptor, "%02x", temp3); 103 | fprintf(file_out_descriptor, "%02x", temp4); 104 | */ 105 | fprintf(file_out_descriptor, "%02x", temp4); 106 | fprintf(file_out_descriptor, "%02x", temp3); 107 | fprintf(file_out_descriptor, "%02x", temp2); 108 | fprintf(file_out_descriptor, "%02x", temp1); 109 | 110 | fprintf(file_out_descriptor, "\n"); 111 | } 112 | 113 | 114 | 115 | } 116 | 117 | exception_handler(0); 118 | return 0; 119 | } 120 | 121 | -------------------------------------------------------------------------------- /Src/NSCSCC_Top/nscscc_axi_top.v: -------------------------------------------------------------------------------- 1 | module mycpu_top 2 | ( 3 | input wire [ 5:0] int, 4 | input wire aclk, 5 | input wire aresetn, 6 | output wire [ 3:0] arid, 7 | output wire [31:0] araddr, 8 | output wire [ 3:0] arlen, 9 | output wire [ 2:0] arsize, 10 | output wire [ 1:0] arburst, 11 | output wire [ 1:0] arlock, 12 | output wire [ 3:0] arcache, 13 | output wire [ 2:0] arprot, 14 | output wire arvalid, 15 | input wire arready, 16 | input wire [ 3:0] rid, 17 | input wire [31:0] rdata, 18 | input wire [ 1:0] rresp, 19 | input wire rlast, 20 | input wire rvalid, 21 | output wire rready, 22 | output wire [ 3:0] awid, 23 | output wire [31:0] awaddr, 24 | output wire [ 3:0] awlen, 25 | output wire [ 2:0] awsize, 26 | output wire [ 1:0] awburst, 27 | output wire [ 1:0] awlock, 28 | output wire [ 3:0] awcache, 29 | output wire [ 2:0] awprot, 30 | output wire awvalid, 31 | input wire awready, 32 | output wire [ 3:0] wid, 33 | output wire [31:0] wdata, 34 | output wire [ 3:0] wstrb, 35 | output wire wlast, 36 | output wire wvalid, 37 | input wire wready, 38 | input wire [ 3:0] bid, 39 | input wire [ 1:0] bresp, 40 | input wire bvalid, 41 | output wire bready, 42 | 43 | output wire [31:0] debug_wb_pc, 44 | output wire [ 3:0] debug_wb_rf_wen, 45 | output wire [ 4:0] debug_wb_rf_wnum, 46 | output wire [31:0] debug_wb_rf_wdata 47 | ); 48 | 49 | MangoMIPS_Top mangomips32 ( 50 | .cpu_clk ( aclk ), 51 | .cpu_rstn ( aresetn ), 52 | .intr ( int ), 53 | 54 | .m_axi_arid ( arid ), 55 | .m_axi_araddr ( araddr ), 56 | .m_axi_arlen ( arlen ), 57 | .m_axi_arsize ( arsize ), 58 | .m_axi_arburst ( arburst ), 59 | .m_axi_arlock ( arlock ), 60 | .m_axi_arcache ( arcache ), 61 | .m_axi_arprot ( arprot ), 62 | .m_axi_arvalid ( arvalid ), 63 | .m_axi_arready ( arready ), 64 | .m_axi_rid ( rid ), 65 | .m_axi_rdata ( rdata ), 66 | .m_axi_rresp ( rresp ), 67 | .m_axi_rlast ( rlast ), 68 | .m_axi_rvalid ( rvalid ), 69 | .m_axi_rready ( rready ), 70 | .m_axi_awid ( awid ), 71 | .m_axi_awaddr ( awaddr ), 72 | .m_axi_awlen ( awlen ), 73 | .m_axi_awsize ( awsize ), 74 | .m_axi_awburst ( awburst ), 75 | .m_axi_awlock ( awlock ), 76 | .m_axi_awcache ( awcache ), 77 | .m_axi_awprot ( awprot ), 78 | .m_axi_awvalid ( awvalid ), 79 | .m_axi_awready ( awready ), 80 | .m_axi_wid ( wid ), 81 | .m_axi_wdata ( wdata ), 82 | .m_axi_wstrb ( wstrb ), 83 | .m_axi_wlast ( wlast ), 84 | .m_axi_wvalid ( wvalid ), 85 | .m_axi_wready ( wready ), 86 | .m_axi_bid ( bid ), 87 | .m_axi_bresp ( bresp ), 88 | .m_axi_bvalid ( bvalid ), 89 | .m_axi_bready ( bready ) 90 | 91 | // .debug_wb_pc ( debug_wb_pc ), 92 | // .debug_wb_wreg ( debug_wb_rf_wen ), 93 | // .debug_wb_wraddr ( debug_wb_rf_wnum ), 94 | // .debug_wb_wrdata ( debug_wb_rf_wdata ) 95 | 96 | ); 97 | 98 | assign debug_wb_pc = mangomips32.mips_core.wb_pc; 99 | assign debug_wb_rf_wen = mangomips32.mips_core.wb_wreg; 100 | assign debug_wb_rf_wnum = mangomips32.mips_core.wb_wraddr; 101 | assign debug_wb_rf_wdata = mangomips32.mips_core.wb_wrdata; 102 | 103 | endmodule -------------------------------------------------------------------------------- /Src/Core/ALU_MEM.v: -------------------------------------------------------------------------------- 1 | /********************MangoMIPS32******************* 2 | Filename: ALU_MEM.v 3 | Author: RickyTino 4 | Version: v1.1.3 5 | **************************************************/ 6 | `include "../Config.v" 7 | `include "../Defines.v" 8 | 9 | module ALU_MEM 10 | ( 11 | input wire [`ALUOp ] aluop, 12 | input wire [`DataBus] alures_i, 13 | input wire [`DWord ] mulhi, 14 | input wire [`DWord ] mullo, 15 | input wire mul_s, 16 | input wire [`DWord ] divres, 17 | input wire [`DWord ] hilo_i, 18 | input wire [`CP0Addr] cp0sel, 19 | input wire exc_flag, 20 | 21 | output reg [`DataBus] alures_o, 22 | output wire [`DataBus] mulres, 23 | output reg hilo_wen, 24 | output reg [`DWord ] hilo_o, 25 | output reg cp0_wen, 26 | output reg [`CP0Addr] cp0_addr, 27 | output reg [`DataBus] cp0_wdata, 28 | input wire [`DataBus] cp0_rdata, 29 | output reg resnrdy 30 | ); 31 | 32 | wire [47: 0 ] reslo = mullo[31:0] + (mullo[63:32] << 16); 33 | wire [47: 0 ] reshi = mulhi[31:0] + (mulhi[63:32] << 16); 34 | wire [`DWord] umres = reslo + (reshi << 16); 35 | wire [`DWord] smres = mul_s ? ~umres + 64'b1 : umres; 36 | 37 | assign mulres = smres; 38 | 39 | always @(*) begin 40 | alures_o <= alures_i; 41 | cp0_addr <= `CP0_ZeroReg; 42 | cp0_wen <= `false; 43 | cp0_wdata <= `ZeroWord; 44 | 45 | case (aluop) 46 | `ALU_MFHI: alures_o <= hilo_i[`Hi]; 47 | `ALU_MFLO: alures_o <= hilo_i[`Lo]; 48 | 49 | `ALU_MFC0: begin 50 | cp0_addr <= cp0sel; 51 | alures_o <= cp0_rdata; 52 | end 53 | 54 | `ALU_MTC0: begin 55 | cp0_addr <= cp0sel; 56 | cp0_wen <= !exc_flag; 57 | cp0_wdata <= alures_i; 58 | end 59 | endcase 60 | 61 | case (aluop) 62 | `ALU_MTHI: begin 63 | hilo_wen <= `true; 64 | hilo_o <= {alures_i, hilo_i[`Lo]}; 65 | end 66 | 67 | `ALU_MTLO: begin 68 | hilo_wen <= `true; 69 | hilo_o <= {hilo_i[`Hi], alures_i}; 70 | end 71 | 72 | `ALU_MULT: begin 73 | hilo_wen <= `true; 74 | hilo_o <= smres; 75 | end 76 | 77 | `ALU_MULTU: begin 78 | hilo_wen <= `true; 79 | hilo_o <= umres; 80 | end 81 | 82 | `ALU_MADD: begin 83 | hilo_wen <= `true; 84 | hilo_o <= hilo_i + smres; 85 | end 86 | 87 | `ALU_MADDU: begin 88 | hilo_wen <= `true; 89 | hilo_o <= hilo_i + umres; 90 | end 91 | 92 | `ALU_MSUB: begin 93 | hilo_wen <= `true; 94 | hilo_o <= hilo_i - smres; 95 | end 96 | 97 | `ALU_MSUBU: begin 98 | hilo_wen <= `true; 99 | hilo_o <= hilo_i - umres; 100 | end 101 | 102 | `ALU_DIV, 103 | `ALU_DIVU: begin 104 | hilo_wen <= `true; 105 | hilo_o <= divres; 106 | end 107 | 108 | default: begin 109 | hilo_wen <= `false; 110 | hilo_o <= hilo_i; 111 | end 112 | endcase 113 | 114 | case (aluop) 115 | `ALU_MUL, 116 | `ALU_LB, 117 | `ALU_LBU, 118 | `ALU_LH, 119 | `ALU_LHU, 120 | `ALU_LW, 121 | `ALU_LWL, 122 | `ALU_LWR, 123 | `ALU_LL: resnrdy <= `true; 124 | default: resnrdy <= `false; 125 | endcase 126 | end 127 | 128 | endmodule -------------------------------------------------------------------------------- /Src/Core/Divider.v: -------------------------------------------------------------------------------- 1 | /********************MangoMIPS32******************* 2 | Filename: Divider.v 3 | Author: RickyTino 4 | Version: v1.1.3 5 | **************************************************/ 6 | `include "../Config.v" 7 | `include "../Defines.v" 8 | 9 | `define DivFree 2'd0 10 | `define DivByZero 2'd1 11 | `define DivOn 2'd2 12 | `define DivEnd 2'd3 13 | 14 | module Divider 15 | ( 16 | input wire clk, 17 | input wire rst, 18 | input wire start, 19 | input wire abandon, 20 | input wire stall, 21 | input wire signdiv, 22 | input wire [`DataBus] opr1, 23 | input wire [`DataBus] opr2, 24 | 25 | output reg ready, 26 | output reg [`DWord ] res 27 | ); 28 | 29 | wire [32:0] temp; 30 | wire [31:0] topr1; 31 | wire [31:0] topr2; 32 | 33 | reg [ 1:0] state; 34 | reg [ 5:0] cnt; 35 | reg [64:0] dividend; 36 | reg [31:0] divisor; 37 | 38 | assign temp = {1'b0, dividend[63:32]} - {1'b0, divisor}; 39 | assign topr1 = signdiv && opr1[31] ? ~opr1 + 1 : opr1; 40 | assign topr2 = signdiv && opr2[31] ? ~opr2 + 1 : opr2; 41 | 42 | always @(posedge clk, posedge rst) begin 43 | if(rst) begin 44 | state <= `DivFree; 45 | ready <= `false; 46 | res <= `ZeroDWord; 47 | dividend <= 65'b0; 48 | divisor <= `ZeroWord; 49 | cnt <= 6'd0; 50 | end 51 | else if(abandon) begin 52 | state <= `DivFree; 53 | ready <= `false; 54 | res <= `ZeroDWord; 55 | dividend <= 65'b0; 56 | divisor <= `ZeroWord; 57 | cnt <= 6'd0; 58 | end 59 | else begin 60 | case (state) 61 | `DivFree: begin 62 | if(start) begin 63 | if(opr2 == `ZeroWord) state <= `DivByZero; 64 | else begin 65 | state <= `DivOn; 66 | cnt <= 6'd0; 67 | dividend <= {31'b0, topr1, 1'b0}; 68 | divisor <= topr2; 69 | end 70 | end 71 | else begin 72 | ready <= `false; 73 | res <= `ZeroDWord; 74 | end 75 | end 76 | 77 | `DivByZero: begin 78 | dividend <= `ZeroDWord; 79 | state <= `DivEnd; 80 | end 81 | 82 | `DivOn: begin 83 | if(cnt != 6'd32) begin 84 | dividend <= temp[32] ? 85 | {dividend[63:0], 1'b0} : 86 | {temp[31:0], dividend[31:0], 1'b1}; 87 | cnt <= cnt + 1; 88 | end 89 | else begin 90 | if(signdiv && (opr1[31] ^ opr2[31])) 91 | dividend[31: 0] <= ~dividend[31: 0] + 1; 92 | if(signdiv && (opr1[31] ^ dividend[64])) 93 | dividend[64:33] <= ~dividend[64:33] + 1; 94 | state <= `DivEnd; 95 | cnt <= 6'd0; 96 | end 97 | end 98 | 99 | `DivEnd: begin 100 | res <= {dividend[64:33], dividend[31:0]}; 101 | ready <= `true; 102 | if(!start && !stall) begin 103 | state <= `DivFree; 104 | ready <= `false; 105 | res <= `ZeroDWord; 106 | end 107 | end 108 | endcase 109 | end 110 | end 111 | 112 | endmodule -------------------------------------------------------------------------------- /Src/Core/Control.v: -------------------------------------------------------------------------------- 1 | /********************MangoMIPS32******************* 2 | Filename: Control.v 3 | Author: RickyTino 4 | Version: v1.1.3 5 | **************************************************/ 6 | `include "../Config.v" 7 | `include "../Defines.v" 8 | 9 | module Control 10 | ( 11 | input wire [`Stages] streq, 12 | output reg [`Stages] stall, 13 | 14 | input wire exc_flag, 15 | input wire [`ExcType] exc_type, 16 | input wire [`DataBus] cp0_Status, 17 | input wire [`DataBus] cp0_Cause, 18 | input wire [`DataBus] cp0_EPC, 19 | input wire [`DataBus] cp0_ErrorEPC, 20 | 21 | input wire ex_null, 22 | input wire mem_null, 23 | output reg [`Stages ] flush, 24 | output reg [`AddrBus] flush_pc 25 | ); 26 | 27 | wire bev = cp0_Status[`BEV]; 28 | wire exl = cp0_Status[`EXL]; 29 | wire erl = cp0_Status[`ERL]; 30 | wire iv = cp0_Cause [`IV ]; 31 | 32 | always @(*) begin 33 | if(exc_flag) begin 34 | stall <= 5'b00000; 35 | flush <= 5'b11111; 36 | 37 | case (exc_type) 38 | `ExcT_Intr: begin 39 | case ({bev, iv}) 40 | 2'b00: flush_pc <= `Normal_GenExc; 41 | 2'b01: flush_pc <= `Normal_SpIntr; 42 | 2'b10: flush_pc <= `Bootstrap_GenExc; 43 | 2'b11: flush_pc <= `Bootstrap_SpIntr; 44 | endcase 45 | end 46 | 47 | `ExcT_TLBR: begin 48 | case ({bev, exl}) 49 | 2'b00: flush_pc <= `Normal_Base; 50 | 2'b01: flush_pc <= `Normal_GenExc; 51 | 2'b10: flush_pc <= `Bootstrap_Base; 52 | 2'b11: flush_pc <= `Bootstrap_GenExc; 53 | endcase 54 | end 55 | 56 | `ExcT_RI, 57 | `ExcT_Ov, 58 | `ExcT_Trap, 59 | `ExcT_SysC, 60 | `ExcT_Bp, 61 | `ExcT_AdE, 62 | `ExcT_TLBI, 63 | `ExcT_TLBM, 64 | // `ExcT_IBE, 65 | // `ExcT_DBE, 66 | `ExcT_CpU: flush_pc <= bev ? `Bootstrap_GenExc : `Normal_GenExc; 67 | 68 | `ExcT_ERET: flush_pc <= erl ? cp0_ErrorEPC : cp0_EPC; 69 | 70 | default: flush_pc <= `ZeroWord; 71 | endcase 72 | end 73 | else begin 74 | flush_pc <= `ZeroWord; 75 | // casez (stallreq) 76 | // // 5'b00001: stall <= 5'b00011; // IF 77 | // // 5'b0001?: stall <= 5'b00011; // ID 78 | // // 5'b001??: stall <= 5'b00111; // EX 79 | // // 5'b01???: stall <= 5'b01111; // MEM 80 | // // 5'b1????: stall <= 5'b11111; // WB 81 | 82 | // 5'b00010: stall <= 5'b00011; // ID 83 | // 5'b001?0: stall <= 5'b00111; // EX 84 | // 5'b00??1: stall <= 5'b00111; // IF 85 | // 5'b01???: stall <= 5'b01111; // MEM 86 | // 5'b1????: stall <= 5'b11111; // WB 87 | // default: stall <= 5'b00000; 88 | // endcase 89 | 90 | // casez (stallreq) 91 | // // 5'b00001: flush <= 5'b00100; // IF 92 | // // 5'b0001?: flush <= 5'b00100; // ID 93 | // // 5'b001??: flush <= 5'b01000; // EX 94 | // // 5'b01???: flush <= 5'b10000; // MEM 95 | 96 | // 5'b00010: flush <= 5'b00100; // ID 97 | // 5'b001?0: flush <= 5'b01000; // EX 98 | // 5'b00??1: flush <= 5'b01000; // IF 99 | // 5'b01???: flush <= 5'b10000; // MEM 100 | // default: flush <= 5'b00000; 101 | // endcase 102 | 103 | // stall[`IF ] <= stall[`ID ]; 104 | // stall[`ID ] <= streq[`ID ] | streq[`IF ] | (stall[`EX ] && ~ex_null); 105 | // stall[`EX ] <= streq[`EX ] | streq[`IF ] | (stall[`MEM] && ~mem_null); 106 | // stall[`MEM] <= streq[`MEM] | stall[`WB]; 107 | // stall[`WB ] <= streq[`WB ]; 108 | 109 | // flush[`IF ] <= 0; 110 | // flush[`ID ] <= 0; 111 | // flush[`EX ] <= stall[`ID ] & ~stall[`EX ]; 112 | // flush[`MEM] <= stall[`EX ] & ~stall[`MEM]; 113 | // flush[`WB ] <= stall[`MEM] & ~stall[`WB ]; 114 | 115 | stall[`IF ] <= stall[`ID ]; 116 | stall[`ID ] <= streq[`ID ] | streq[`IF ] | stall[`EX ]; 117 | stall[`EX ] <= streq[`EX ] | streq[`IF ] | (stall[`MEM] && ~ex_null ); 118 | stall[`MEM] <= streq[`MEM] | (stall[`WB ] && ~mem_null); 119 | stall[`WB ] <= streq[`WB ]; 120 | 121 | flush[`IF ] <= 0; 122 | flush[`ID ] <= 0; 123 | flush[`EX ] <= stall[`ID ] & ~stall[`EX ]; 124 | flush[`MEM] <= stall[`EX ] & ~stall[`MEM]; 125 | flush[`WB ] <= stall[`MEM] & ~stall[`WB ]; 126 | end 127 | end 128 | 129 | endmodule -------------------------------------------------------------------------------- /Src/Core/MMU.v: -------------------------------------------------------------------------------- 1 | /********************MangoMIPS32******************* 2 | Filename: MMU.v 3 | Author: RickyTino 4 | Version: v1.1.3 5 | **************************************************/ 6 | `include "../Config.v" 7 | `include "../Defines.v" 8 | 9 | module MMU 10 | ( 11 | input wire en, 12 | input wire [`ByteWEn] wen, 13 | input wire [`AddrBus] vaddr, 14 | input wire [`DataBus] wdata, 15 | output wire [`DataBus] rdata, 16 | input wire [`AXISize] size, 17 | output wire refs, 18 | 19 | output reg bus_en, 20 | output wire [`ByteWEn] bus_wen, 21 | output reg [`AddrBus] bus_paddr, 22 | output wire [`DataBus] bus_wdata, 23 | input wire [`DataBus] bus_rdata, 24 | output wire [`AXISize] bus_size, 25 | input wire bus_streq, 26 | output reg bus_cached, 27 | 28 | output reg tlb_en, 29 | output reg [`AddrBus] tlb_vaddr, 30 | // output reg tlb_refs, 31 | input wire tlb_rdy, 32 | input wire [`AddrBus] tlb_paddr, 33 | input wire tlb_cat, 34 | input wire tlb_tlbr, 35 | input wire tlb_tlbi, 36 | input wire tlb_tlbm, 37 | 38 | input wire exc_flag, 39 | input wire [`DataBus] cp0_Status, 40 | input wire [`DataBus] cp0_Config, 41 | output reg exc_tlbr, 42 | output reg exc_tlbi, 43 | output reg exc_tlbm, 44 | 45 | output wire stallreq 46 | ); 47 | 48 | `ifdef Fixed_Mapping_MMU 49 | 50 | assign bus_wen = en ? wen : `WrDisable; 51 | assign bus_wdata = wdata; 52 | assign bus_size = size; 53 | assign rdata = en ? bus_rdata : `ZeroWord; 54 | assign refs = wen != `WrDisable; 55 | assign stallreq = bus_streq; 56 | 57 | always @(*) begin 58 | exc_tlbr <= `false; 59 | exc_tlbi <= `false; 60 | exc_tlbm <= `false; 61 | 62 | bus_en <= en && !exc_flag; 63 | case (vaddr[`Seg]) 64 | `kseg0: begin // kseg0: unmapped 65 | bus_paddr <= {3'b000, vaddr[28:0]}; 66 | bus_cached <= cp0_Config[`K0] == 3'd3; 67 | end 68 | 69 | `kseg1: begin // kseg1: unmapped, uncached 70 | bus_paddr <= {3'b000, vaddr[28:0]}; 71 | bus_cached <= `false; 72 | end 73 | 74 | `kseg2, `kseg3: begin // kseg2 & kseg3: mapped 75 | bus_paddr <= vaddr; 76 | bus_cached <= cp0_Config[`K23] == 3'd3; 77 | end 78 | 79 | default: begin // kuseg: mapped 80 | bus_paddr <= cp0_Status[`ERL] ? vaddr : {vaddr[31:28] + 4'd4, vaddr[27:0]}; 81 | bus_cached <= cp0_Config[`KU] == 3'd3; 82 | end 83 | endcase 84 | end 85 | 86 | `else // TLB-based MMU 87 | 88 | reg tlb_streq; 89 | 90 | assign bus_wen = en ? wen : `WrDisable; 91 | assign bus_wdata = wdata; 92 | assign bus_size = size; 93 | assign rdata = en ? bus_rdata : `ZeroWord; 94 | assign refs = wen != `WrDisable; 95 | assign stallreq = bus_streq || tlb_streq; 96 | 97 | always @(*) begin 98 | tlb_en <= `false; 99 | tlb_vaddr <= `ZeroWord; 100 | // tlb_refs <= `false; 101 | tlb_streq <= `false; 102 | bus_en <= `false; 103 | bus_paddr <= `ZeroWord; 104 | bus_cached <= `false; 105 | exc_tlbr <= `false; 106 | exc_tlbi <= `false; 107 | exc_tlbm <= `false; 108 | 109 | // if(en && !exc_flag) begin 110 | case (vaddr[`Seg]) 111 | `kseg0: begin // kseg0: unmapped 112 | bus_paddr <= {3'b000, vaddr[28:0]}; 113 | bus_en <= en && !exc_flag; 114 | bus_cached <= cp0_Config[`K0] == 3'd3; 115 | end 116 | 117 | `kseg1: begin // kseg1: unmapped, uncached 118 | bus_paddr <= {3'b000, vaddr[28:0]}; 119 | bus_en <= en && !exc_flag; 120 | bus_cached <= `false; 121 | end 122 | 123 | default: begin // kseg2, kseg3, kuseg: mapped 124 | if(cp0_Status[`ERL]) begin 125 | bus_paddr <= {3'b000, vaddr[28:0]}; 126 | bus_en <= en && !exc_flag; 127 | bus_cached <= `false; 128 | end 129 | else if(en) begin 130 | tlb_en <= `true; 131 | // tlb_refs <= wen != `WrDisable; 132 | tlb_vaddr <= vaddr; 133 | tlb_streq <= !tlb_rdy; 134 | bus_paddr <= tlb_paddr; 135 | bus_en <= tlb_rdy & !exc_flag; 136 | bus_cached <= tlb_cat; 137 | exc_tlbr <= tlb_tlbr; 138 | exc_tlbi <= tlb_tlbi; 139 | exc_tlbm <= tlb_tlbm; 140 | end 141 | end 142 | endcase 143 | end 144 | `endif 145 | 146 | endmodule -------------------------------------------------------------------------------- /Src/Core/Reg_EX_MEM.v: -------------------------------------------------------------------------------- 1 | /********************MangoMIPS32******************* 2 | Filename: Reg_EX_MEM.v 3 | Author: RickyTino 4 | Version: v1.1.3 5 | **************************************************/ 6 | `include "../Config.v" 7 | `include "../Defines.v" 8 | 9 | module Reg_EX_MEM 10 | ( 11 | input wire clk, 12 | input wire rst, 13 | input wire stall, 14 | input wire flush, 15 | 16 | input wire [`AddrBus] ex_pc, 17 | input wire [`ALUOp ] ex_aluop, 18 | input wire [`CacheOp] ex_cacheop, 19 | input wire [`DataBus] ex_alures, 20 | input wire [`DWord ] ex_mulhi, 21 | input wire [`DWord ] ex_mullo, 22 | input wire ex_mul_s, 23 | input wire [`DWord ] ex_divres, 24 | input wire [`CP0Addr] ex_cp0sel, 25 | input wire ex_m_en, 26 | input wire [`ByteWEn] ex_m_wen, 27 | input wire [`AddrBus] ex_m_vaddr, 28 | input wire [`DataBus] ex_m_wdata, 29 | input wire [`AXISize] ex_m_size, 30 | input wire [`ByteWEn] ex_wreg, 31 | input wire [`RegAddr] ex_wraddr, 32 | input wire ex_llb_wen, 33 | input wire ex_llbit, 34 | input wire [`ExcBus ] ex_excp, 35 | input wire [`CPNum ] ex_ecpnum, 36 | input wire [`TLBOp ] ex_tlbop, 37 | input wire ex_inslot, 38 | input wire ex_null, 39 | 40 | output reg [`AddrBus] mem_pc, 41 | output reg [`ALUOp ] mem_aluop, 42 | output reg [`CacheOp] mem_cacheop, 43 | output reg [`DataBus] mem_alures, 44 | output reg [`DWord ] mem_mulhi, 45 | output reg [`DWord ] mem_mullo, 46 | output reg mem_mul_s, 47 | output reg [`DWord ] mem_divres, 48 | output reg [`CP0Addr] mem_cp0sel, 49 | output reg mem_m_en, 50 | output reg [`ByteWEn] mem_m_wen, 51 | output reg [`AddrBus] mem_m_vaddr, 52 | output reg [`DataBus] mem_m_wdata, 53 | output reg [`AXISize] mem_m_size, 54 | output reg [`ByteWEn] mem_wreg, 55 | output reg [`RegAddr] mem_wraddr, 56 | output reg mem_llb_wen, 57 | output reg mem_llbit, 58 | output reg [`ExcBus ] mem_excp, 59 | output reg [`CPNum ] mem_ecpnum, 60 | output reg [`TLBOp ] mem_tlbop, 61 | output reg mem_inslot, 62 | output reg mem_null 63 | ); 64 | 65 | always @(posedge clk, posedge rst) begin 66 | if(rst) begin 67 | mem_pc <= `ZeroWord; 68 | mem_aluop <= `ALU_NOP; 69 | mem_cacheop <= `COP_NOP; 70 | mem_alures <= `ZeroWord; 71 | mem_mulhi <= `ZeroDWord; 72 | mem_mullo <= `ZeroDWord; 73 | mem_mul_s <= `Zero; 74 | mem_divres <= `ZeroDWord; 75 | mem_cp0sel <= `CP0_ZeroReg; 76 | mem_m_en <= `false; 77 | mem_m_wen <= `WrDisable; 78 | mem_m_vaddr <= `ZeroWord; 79 | mem_m_wdata <= `ZeroWord; 80 | mem_m_size <= `ASize_Word; 81 | mem_wreg <= `WrDisable; 82 | mem_wraddr <= `ZeroReg; 83 | mem_llb_wen <= `false; 84 | mem_llbit <= `Zero; 85 | mem_excp <= `Exc_NoExc; 86 | mem_ecpnum <= `CP0; 87 | mem_tlbop <= `TOP_NOP; 88 | mem_inslot <= `false; 89 | mem_null <= `true; 90 | end 91 | else begin 92 | case ({flush, stall}) 93 | 2'b10, 2'b11: begin 94 | mem_pc <= `ZeroWord; 95 | mem_aluop <= `ALU_NOP; 96 | mem_cacheop <= `COP_NOP; 97 | mem_alures <= `ZeroWord; 98 | mem_mulhi <= `ZeroDWord; 99 | mem_mullo <= `ZeroDWord; 100 | mem_mul_s <= `Zero; 101 | mem_divres <= `ZeroDWord; 102 | mem_cp0sel <= `CP0_ZeroReg; 103 | mem_m_en <= `false; 104 | mem_m_wen <= `WrDisable; 105 | mem_m_vaddr <= `ZeroWord; 106 | mem_m_wdata <= `ZeroWord; 107 | mem_m_size <= `ASize_Word; 108 | mem_wreg <= `WrDisable; 109 | mem_wraddr <= `ZeroReg; 110 | mem_llb_wen <= `false; 111 | mem_llbit <= `Zero; 112 | mem_excp <= `Exc_NoExc; 113 | mem_ecpnum <= `CP0; 114 | mem_tlbop <= `TOP_NOP; 115 | mem_inslot <= `false; 116 | mem_null <= `true; 117 | end 118 | 2'b00: begin 119 | mem_pc <= ex_pc; 120 | mem_aluop <= ex_aluop; 121 | mem_cacheop <= ex_cacheop; 122 | mem_alures <= ex_alures; 123 | mem_mulhi <= ex_mulhi; 124 | mem_mullo <= ex_mullo; 125 | mem_mul_s <= ex_mul_s; 126 | mem_divres <= ex_divres; 127 | mem_cp0sel <= ex_cp0sel; 128 | mem_m_en <= ex_m_en; 129 | mem_m_wen <= ex_m_wen; 130 | mem_m_vaddr <= ex_m_vaddr; 131 | mem_m_wdata <= ex_m_wdata; 132 | mem_m_size <= ex_m_size; 133 | mem_wreg <= ex_wreg; 134 | mem_wraddr <= ex_wraddr; 135 | mem_llb_wen <= ex_llb_wen; 136 | mem_llbit <= ex_llbit; 137 | mem_excp <= ex_excp; 138 | mem_ecpnum <= ex_ecpnum; 139 | mem_tlbop <= ex_tlbop; 140 | mem_inslot <= ex_inslot; 141 | mem_null <= ex_null; 142 | end 143 | endcase 144 | end 145 | end 146 | 147 | endmodule -------------------------------------------------------------------------------- /Testbench/Cache_Test/test.S: -------------------------------------------------------------------------------- 1 | #********************MangoMIPS32******************* 2 | # Filename: Cache_test/test.S 3 | # Author: RickyTino 4 | # Version: v1.0.0 5 | #************************************************** 6 | 7 | # Cache Operation test for MangoMIPS32 8 | 9 | .globl _start 10 | .set noreorder 11 | .text 12 | .org 0x0 13 | _start: 14 | li $t0, 0x0040FF01 15 | mtc0 $t0, $12 # Status = 0x0040FF01 16 | li $t1, 0x00000003 17 | mtc0 $t1, $16 # Config.K0 = 3 (Cacheable) 18 | la $sp, 0x80008000 # stack pointer: 0x80008000 19 | la $t2, 0x80000600 20 | jalr $t2 21 | nop 22 | wait 23 | 24 | .org 0x380 25 | _ex_start: 26 | mfc0 $k0, $13 # k0 = CP0.Cause 27 | andi $k1, $k0, 0x7C 28 | srl $k1, $k1, 2 # k1 = CP0.Cause.ExcCode 29 | 30 | # li $k0, 0x08 31 | # beq $k0, $k1, _syscall_ex 32 | # nop 33 | # li $k0, 0x0D 34 | # beq $k0, $k1, _trap_ex 35 | # nop 36 | # b _ex_finish 37 | # nop 38 | 39 | # _trap_ex: 40 | # b _ex_finish 41 | # nop 42 | 43 | _ex_finish: 44 | mfc0 $k0, $14 45 | addi $k0, 4 46 | mtc0 $k0, $14 47 | eret 48 | 49 | # Test 1: ICache - Index Invalidate (0x0) 50 | _test1: 51 | .org 0x600 52 | la $s0, 0x80000000 # s0 = 0x80000000, kseg0 base 53 | la $s1, 0xA0000000 # s1 = 0xA0000000, kseg1 base 54 | li $s2, 0xC # s2 = 0x0000000C (syscall) 55 | li $s3, 0xD # s3 = 0x0000000D (break) 56 | sw $s2, 0x630($s1) # save a syscall to 0xA0000630 57 | cache 0x0, 0x60A($s0) 58 | nop 59 | # 0x80000630 should be a syscall after cache operation 60 | 61 | # Test 2: ICache - Index Store Tag (0x8) 62 | _test2: 63 | .org 0x640 64 | sw $s2, 0x670($s1) # save a syscall to 0xA0000670 65 | li $t0, 0x98765400 66 | mtc0 $t0, $28 # ITagLo = 0x98765400 67 | cache 0x8, 0x658($s0) 68 | nop 69 | # 0x80000670 should be a syscall after cache operation 70 | 71 | # Test 3: ICache - Hit Invalidate (0x10) 72 | _test3: 73 | .org 0x680 74 | sw $s3, 0x6A0($s1) # save a break to 0xA00006A0 75 | la $t0, 0x81000000 76 | cache 0x10, 0x6AC($t0) # should be an unhit 77 | nop 78 | # newly-added break at 0x800006A0 should not be executed. 79 | .org 0x6C0 80 | sw $s2, 0x6F0($s1) # save a break to 0xA00006F0 81 | cache 0x10, 0x6F4($s0) # should be a hit 82 | nop 83 | # 0x800006F0 should be a syscall after cache operation 84 | 85 | # Test 4: DCache - Index Writeback Invalidate (0x1) 86 | _test4: 87 | .org 0x700 88 | li $t0, 0x10 89 | li $t1, 0 90 | 91 | # loop1: save 0x1 to 0x10 to 0x80001000 ~ 0x80001010, 16 Bytes, cached 92 | loop1: 93 | add $t2, $t1, $s0 94 | sb $t1, 0x1000($t2) 95 | slt $t3, $t1, $t0 96 | bne $t3, $zero, loop1 97 | addi $t1, $t1, 1 98 | # DCache data after loop1: 99 | # +0 +2 +4 +6 100 | # 0x80001000 00 01 02 03 04 05 06 07 101 | # 0x80001008 08 09 0A 0B 0C 0D 0E 0F 102 | 103 | li $t0, 0x13121110 # t0 = 0x13121110 104 | sw $t0, 0x1000($s1) # uncached save t0 to 0x80001000 105 | cache 0x1, 0x1000($s0) # DCache Index Writeback Invalidate 106 | lw $t1, 0x1000($s0) # uncached load from 0x80001004 107 | teq $t1, $t0 # t0 should be overwritten 108 | lw $t2, 0x1000($s1) # data in cache is now the same with data in RAM 109 | tne $t1, $t2 # trap if unequal 110 | nop 111 | 112 | # Test 5: DCache - Index Store Tag (0x9) 113 | _test5: 114 | li $t0, 0x27262524 115 | sw $t0, 0x1004($s0) # save 0x27262524 to DCache id1004 116 | li $t1, 0x17161514 117 | sw $t1, 0x1004($s1) # save 0x17161514 to RAM 0x1004 118 | li $t2, 0 119 | mtc0 $t2, $28, 2 # DTagLo = 0x00000000 120 | cache 0x9, 0x1010($s0) # store tag to index 121 | nop 122 | lw $t3, 0x1004($s0) # load from 0x80001000, fill cache 123 | tne $t3, $t1 # t3 should equal t1 124 | teq $t3, $t0 # t3 should not equal t0 125 | nop 126 | 127 | # Test 6: DCache - Hit Invalidate (0x11) 128 | _test6: 129 | li $t0, 0x2B2A2928 130 | sw $t0, 0x1008($s0) # save 0x2B2A2928 to DCache id1008 131 | li $t1, 0x1B1A1918 132 | sw $t1, 0x1008($s1) # save 0x1B1A1918 to RAM 0x1008 133 | li $t2, 0x81000000 # wrong tag 0x81000000 134 | cache 0x11, 0x1014($t2) # should be an unhit 135 | nop 136 | lw $t3, 0x1008($s0) # load from 0x80001008, cache 137 | teq $t3, $t1 # t3 should not equal t1 138 | tne $t3, $t0 # t3 should equal t0 139 | nop 140 | cache 0x11, 0x1016($s0) # should be a hit 141 | nop 142 | lw $t3, 0x1008($s0) # load from 0x80001008, fill cache 143 | tne $t3, $t1 # t3 should equal t1 144 | teq $t3, $t0 # t3 should not equal t0 145 | 146 | # Test 7: DCache - Hit Writeback Invalidate (0x15) 147 | _test7: 148 | li $t0, 0x2F2E2D2C 149 | sw $t0, 0x100C($s0) # save 0x2F2E2D2C to DCache id100C 150 | li $t1, 0x1F1E1D1C 151 | sw $t1, 0x100C($s1) # save 0x1F1E1D1C to RAM 0x100C 152 | li $t2, 0x82000000 # wrong tag 0x81000000 153 | cache 0x15, 0x101C($t2) # should be an unhit 154 | nop 155 | lw $t3, 0x100C($s1) # load from 0x80001008, RAM 156 | teq $t3, $t0 # t3 should not equal t0 157 | tne $t3, $t1 # t3 should equal t1 158 | nop 159 | cache 0x15, 0x1016($s0) # should be a hit writeback 160 | nop 161 | lw $t3, 0x100C($s1) # load from 0x80001008, RAM 162 | tne $t3, $t0 # t3 should equal t0 163 | teq $t3, $t1 # t3 should not equal t1 164 | nop 165 | 166 | # Cache test end, return 167 | _test_return: 168 | jr $ra 169 | nop 170 | -------------------------------------------------------------------------------- /Testbench/Cache_Test/test_ram.data: -------------------------------------------------------------------------------- 1 | 3c080040 2 | 3508ff01 3 | 40886000 4 | 24090003 5 | 40898000 6 | 3c1d8000 7 | 37bd8000 8 | 3c0a8000 9 | 354a0600 10 | 0140f809 11 | 00000000 12 | 42000020 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 | 00000000 34 | 00000000 35 | 00000000 36 | 00000000 37 | 00000000 38 | 00000000 39 | 00000000 40 | 00000000 41 | 00000000 42 | 00000000 43 | 00000000 44 | 00000000 45 | 00000000 46 | 00000000 47 | 00000000 48 | 00000000 49 | 00000000 50 | 00000000 51 | 00000000 52 | 00000000 53 | 00000000 54 | 00000000 55 | 00000000 56 | 00000000 57 | 00000000 58 | 00000000 59 | 00000000 60 | 00000000 61 | 00000000 62 | 00000000 63 | 00000000 64 | 00000000 65 | 00000000 66 | 00000000 67 | 00000000 68 | 00000000 69 | 00000000 70 | 00000000 71 | 00000000 72 | 00000000 73 | 00000000 74 | 00000000 75 | 00000000 76 | 00000000 77 | 00000000 78 | 00000000 79 | 00000000 80 | 00000000 81 | 00000000 82 | 00000000 83 | 00000000 84 | 00000000 85 | 00000000 86 | 00000000 87 | 00000000 88 | 00000000 89 | 00000000 90 | 00000000 91 | 00000000 92 | 00000000 93 | 00000000 94 | 00000000 95 | 00000000 96 | 00000000 97 | 00000000 98 | 00000000 99 | 00000000 100 | 00000000 101 | 00000000 102 | 00000000 103 | 00000000 104 | 00000000 105 | 00000000 106 | 00000000 107 | 00000000 108 | 00000000 109 | 00000000 110 | 00000000 111 | 00000000 112 | 00000000 113 | 00000000 114 | 00000000 115 | 00000000 116 | 00000000 117 | 00000000 118 | 00000000 119 | 00000000 120 | 00000000 121 | 00000000 122 | 00000000 123 | 00000000 124 | 00000000 125 | 00000000 126 | 00000000 127 | 00000000 128 | 00000000 129 | 00000000 130 | 00000000 131 | 00000000 132 | 00000000 133 | 00000000 134 | 00000000 135 | 00000000 136 | 00000000 137 | 00000000 138 | 00000000 139 | 00000000 140 | 00000000 141 | 00000000 142 | 00000000 143 | 00000000 144 | 00000000 145 | 00000000 146 | 00000000 147 | 00000000 148 | 00000000 149 | 00000000 150 | 00000000 151 | 00000000 152 | 00000000 153 | 00000000 154 | 00000000 155 | 00000000 156 | 00000000 157 | 00000000 158 | 00000000 159 | 00000000 160 | 00000000 161 | 00000000 162 | 00000000 163 | 00000000 164 | 00000000 165 | 00000000 166 | 00000000 167 | 00000000 168 | 00000000 169 | 00000000 170 | 00000000 171 | 00000000 172 | 00000000 173 | 00000000 174 | 00000000 175 | 00000000 176 | 00000000 177 | 00000000 178 | 00000000 179 | 00000000 180 | 00000000 181 | 00000000 182 | 00000000 183 | 00000000 184 | 00000000 185 | 00000000 186 | 00000000 187 | 00000000 188 | 00000000 189 | 00000000 190 | 00000000 191 | 00000000 192 | 00000000 193 | 00000000 194 | 00000000 195 | 00000000 196 | 00000000 197 | 00000000 198 | 00000000 199 | 00000000 200 | 00000000 201 | 00000000 202 | 00000000 203 | 00000000 204 | 00000000 205 | 00000000 206 | 00000000 207 | 00000000 208 | 00000000 209 | 00000000 210 | 00000000 211 | 00000000 212 | 00000000 213 | 00000000 214 | 00000000 215 | 00000000 216 | 00000000 217 | 00000000 218 | 00000000 219 | 00000000 220 | 00000000 221 | 00000000 222 | 00000000 223 | 00000000 224 | 00000000 225 | 401a6800 226 | 335b007c 227 | 001bd882 228 | 401a7000 229 | 235a0004 230 | 409a7000 231 | 42000018 232 | 00000000 233 | 00000000 234 | 00000000 235 | 00000000 236 | 00000000 237 | 00000000 238 | 00000000 239 | 00000000 240 | 00000000 241 | 00000000 242 | 00000000 243 | 00000000 244 | 00000000 245 | 00000000 246 | 00000000 247 | 00000000 248 | 00000000 249 | 00000000 250 | 00000000 251 | 00000000 252 | 00000000 253 | 00000000 254 | 00000000 255 | 00000000 256 | 00000000 257 | 00000000 258 | 00000000 259 | 00000000 260 | 00000000 261 | 00000000 262 | 00000000 263 | 00000000 264 | 00000000 265 | 00000000 266 | 00000000 267 | 00000000 268 | 00000000 269 | 00000000 270 | 00000000 271 | 00000000 272 | 00000000 273 | 00000000 274 | 00000000 275 | 00000000 276 | 00000000 277 | 00000000 278 | 00000000 279 | 00000000 280 | 00000000 281 | 00000000 282 | 00000000 283 | 00000000 284 | 00000000 285 | 00000000 286 | 00000000 287 | 00000000 288 | 00000000 289 | 00000000 290 | 00000000 291 | 00000000 292 | 00000000 293 | 00000000 294 | 00000000 295 | 00000000 296 | 00000000 297 | 00000000 298 | 00000000 299 | 00000000 300 | 00000000 301 | 00000000 302 | 00000000 303 | 00000000 304 | 00000000 305 | 00000000 306 | 00000000 307 | 00000000 308 | 00000000 309 | 00000000 310 | 00000000 311 | 00000000 312 | 00000000 313 | 00000000 314 | 00000000 315 | 00000000 316 | 00000000 317 | 00000000 318 | 00000000 319 | 00000000 320 | 00000000 321 | 00000000 322 | 00000000 323 | 00000000 324 | 00000000 325 | 00000000 326 | 00000000 327 | 00000000 328 | 00000000 329 | 00000000 330 | 00000000 331 | 00000000 332 | 00000000 333 | 00000000 334 | 00000000 335 | 00000000 336 | 00000000 337 | 00000000 338 | 00000000 339 | 00000000 340 | 00000000 341 | 00000000 342 | 00000000 343 | 00000000 344 | 00000000 345 | 00000000 346 | 00000000 347 | 00000000 348 | 00000000 349 | 00000000 350 | 00000000 351 | 00000000 352 | 00000000 353 | 00000000 354 | 00000000 355 | 00000000 356 | 00000000 357 | 00000000 358 | 00000000 359 | 00000000 360 | 00000000 361 | 00000000 362 | 00000000 363 | 00000000 364 | 00000000 365 | 00000000 366 | 00000000 367 | 00000000 368 | 00000000 369 | 00000000 370 | 00000000 371 | 00000000 372 | 00000000 373 | 00000000 374 | 00000000 375 | 00000000 376 | 00000000 377 | 00000000 378 | 00000000 379 | 00000000 380 | 00000000 381 | 00000000 382 | 00000000 383 | 00000000 384 | 00000000 385 | 3c108000 386 | 3c11a000 387 | 2412000c 388 | 2413000d 389 | ae320630 390 | be00060a 391 | 00000000 392 | 00000000 393 | 00000000 394 | 00000000 395 | 00000000 396 | 00000000 397 | 00000000 398 | 00000000 399 | 00000000 400 | 00000000 401 | ae320670 402 | 3c089876 403 | 35085400 404 | 4088e000 405 | be080658 406 | 00000000 407 | 00000000 408 | 00000000 409 | 00000000 410 | 00000000 411 | 00000000 412 | 00000000 413 | 00000000 414 | 00000000 415 | 00000000 416 | 00000000 417 | ae3306a0 418 | 3c088100 419 | bd1006ac 420 | 00000000 421 | 00000000 422 | 00000000 423 | 00000000 424 | 00000000 425 | 00000000 426 | 00000000 427 | 00000000 428 | 00000000 429 | 00000000 430 | 00000000 431 | 00000000 432 | 00000000 433 | ae3206f0 434 | be1006f4 435 | 00000000 436 | 00000000 437 | 00000000 438 | 00000000 439 | 00000000 440 | 00000000 441 | 00000000 442 | 00000000 443 | 00000000 444 | 00000000 445 | 00000000 446 | 00000000 447 | 00000000 448 | 00000000 449 | 24080010 450 | 24090000 451 | 01305020 452 | a1491000 453 | 0128582a 454 | 1560fffc 455 | 21290001 456 | 3c081312 457 | 35081110 458 | ae281000 459 | be011000 460 | 8e091000 461 | 01280034 462 | 8e2a1000 463 | 012a0036 464 | 00000000 465 | 3c082726 466 | 35082524 467 | ae081004 468 | 3c091716 469 | 35291514 470 | ae291004 471 | 240a0000 472 | 408ae002 473 | be091010 474 | 00000000 475 | 8e0b1004 476 | 01690036 477 | 01680034 478 | 00000000 479 | 3c082b2a 480 | 35082928 481 | ae081008 482 | 3c091b1a 483 | 35291918 484 | ae291008 485 | 3c0a8100 486 | bd511014 487 | 00000000 488 | 8e0b1008 489 | 01690034 490 | 01680036 491 | 00000000 492 | be111016 493 | 00000000 494 | 8e0b1008 495 | 01690036 496 | 01680034 497 | 3c082f2e 498 | 35082d2c 499 | ae08100c 500 | 3c091f1e 501 | 35291d1c 502 | ae29100c 503 | 3c0a8200 504 | bd55101c 505 | 00000000 506 | 8e2b100c 507 | 01680034 508 | 01690036 509 | 00000000 510 | be151016 511 | 00000000 512 | 8e2b100c 513 | 01680036 514 | 01690034 515 | 00000000 516 | 03e00008 517 | 00000000 518 | 00000000 519 | 00000000 520 | 00000000 521 | ac0f0f00 522 | 00000000 523 | 00000000 524 | 00000000 525 | 00000000 526 | 00000000 527 | -------------------------------------------------------------------------------- /Testbench/TLB_Test/test_ram.data: -------------------------------------------------------------------------------- 1 | 3c1da000 2 | 37bda000 3 | 3c048000 4 | 3c05a000 5 | 3c100101 6 | 36100101 7 | 3c110202 8 | 36310202 9 | 3c120303 10 | 36520303 11 | 3c130404 12 | 36730404 13 | 24081314 14 | aca81000 15 | 8d291000 16 | 3c0a0040 17 | 354aff01 18 | 408a6000 19 | 00000000 20 | 01090036 21 | 240b0003 22 | 408b8000 23 | 0ff001c0 24 | 00000000 25 | 42000020 26 | 00000000 27 | 00000000 28 | 00000000 29 | 00000000 30 | 00000000 31 | 00000000 32 | 00000000 33 | 00000000 34 | 00000000 35 | 00000000 36 | 00000000 37 | 00000000 38 | 00000000 39 | 00000000 40 | 00000000 41 | 00000000 42 | 00000000 43 | 00000000 44 | 00000000 45 | 00000000 46 | 00000000 47 | 00000000 48 | 00000000 49 | 00000000 50 | 00000000 51 | 00000000 52 | 00000000 53 | 00000000 54 | 00000000 55 | 00000000 56 | 00000000 57 | 00000000 58 | 00000000 59 | 00000000 60 | 00000000 61 | 00000000 62 | 00000000 63 | 00000000 64 | 00000000 65 | 00000000 66 | 00000000 67 | 00000000 68 | 00000000 69 | 00000000 70 | 00000000 71 | 00000000 72 | 00000000 73 | 00000000 74 | 00000000 75 | 00000000 76 | 00000000 77 | 00000000 78 | 00000000 79 | 00000000 80 | 00000000 81 | 00000000 82 | 00000000 83 | 00000000 84 | 00000000 85 | 00000000 86 | 00000000 87 | 00000000 88 | 00000000 89 | 00000000 90 | 00000000 91 | 00000000 92 | 00000000 93 | 00000000 94 | 00000000 95 | 00000000 96 | 00000000 97 | 00000000 98 | 00000000 99 | 00000000 100 | 00000000 101 | 00000000 102 | 00000000 103 | 00000000 104 | 00000000 105 | 00000000 106 | 00000000 107 | 00000000 108 | 00000000 109 | 00000000 110 | 00000000 111 | 00000000 112 | 00000000 113 | 00000000 114 | 00000000 115 | 00000000 116 | 00000000 117 | 00000000 118 | 00000000 119 | 00000000 120 | 00000000 121 | 00000000 122 | 00000000 123 | 00000000 124 | 00000000 125 | 00000000 126 | 00000000 127 | 00000000 128 | 00000000 129 | 1000005f 130 | 00000000 131 | 00000000 132 | 00000000 133 | 00000000 134 | 00000000 135 | 00000000 136 | 00000000 137 | 00000000 138 | 00000000 139 | 00000000 140 | 00000000 141 | 00000000 142 | 00000000 143 | 00000000 144 | 00000000 145 | 00000000 146 | 00000000 147 | 00000000 148 | 00000000 149 | 00000000 150 | 00000000 151 | 00000000 152 | 00000000 153 | 00000000 154 | 00000000 155 | 00000000 156 | 00000000 157 | 00000000 158 | 00000000 159 | 00000000 160 | 00000000 161 | 00000000 162 | 00000000 163 | 00000000 164 | 00000000 165 | 00000000 166 | 00000000 167 | 00000000 168 | 00000000 169 | 00000000 170 | 00000000 171 | 00000000 172 | 00000000 173 | 00000000 174 | 00000000 175 | 00000000 176 | 00000000 177 | 00000000 178 | 00000000 179 | 00000000 180 | 00000000 181 | 00000000 182 | 00000000 183 | 00000000 184 | 00000000 185 | 00000000 186 | 00000000 187 | 00000000 188 | 00000000 189 | 00000000 190 | 00000000 191 | 00000000 192 | 00000000 193 | 00000000 194 | 00000000 195 | 00000000 196 | 00000000 197 | 00000000 198 | 00000000 199 | 00000000 200 | 00000000 201 | 00000000 202 | 00000000 203 | 00000000 204 | 00000000 205 | 00000000 206 | 00000000 207 | 00000000 208 | 00000000 209 | 00000000 210 | 00000000 211 | 00000000 212 | 00000000 213 | 00000000 214 | 00000000 215 | 00000000 216 | 00000000 217 | 00000000 218 | 00000000 219 | 00000000 220 | 00000000 221 | 00000000 222 | 00000000 223 | 00000000 224 | 00000000 225 | 23180001 226 | 401a6800 227 | 335a007c 228 | 001ad082 229 | 241b0008 230 | 137a0003 231 | 00000000 232 | 1000000a 233 | 00000000 234 | 00431024 235 | 00601827 236 | 401a7000 237 | 0343d024 238 | 0342d025 239 | 235a0004 240 | 409a7000 241 | 00000000 242 | 42000018 243 | 401a7000 244 | 235a0004 245 | 409a7000 246 | 42000018 247 | 00000000 248 | 00000000 249 | 00000000 250 | 00000000 251 | 00000000 252 | 00000000 253 | 00000000 254 | 00000000 255 | 00000000 256 | 00000000 257 | 00000000 258 | 00000000 259 | 00000000 260 | 00000000 261 | 00000000 262 | 00000000 263 | 00000000 264 | 00000000 265 | 00000000 266 | 00000000 267 | 00000000 268 | 00000000 269 | 00000000 270 | 00000000 271 | 00000000 272 | 00000000 273 | 00000000 274 | 00000000 275 | 00000000 276 | 00000000 277 | 00000000 278 | 00000000 279 | 00000000 280 | 00000000 281 | 00000000 282 | 00000000 283 | 00000000 284 | 00000000 285 | 00000000 286 | 00000000 287 | 00000000 288 | 00000000 289 | 00000000 290 | 00000000 291 | 00000000 292 | 00000000 293 | 00000000 294 | 00000000 295 | 00000000 296 | 00000000 297 | 00000000 298 | 00000000 299 | 00000000 300 | 00000000 301 | 00000000 302 | 00000000 303 | 00000000 304 | 00000000 305 | 00000000 306 | 00000000 307 | 00000000 308 | 00000000 309 | 00000000 310 | 00000000 311 | 00000000 312 | 00000000 313 | 00000000 314 | 00000000 315 | 00000000 316 | 00000000 317 | 00000000 318 | 00000000 319 | 00000000 320 | 00000000 321 | 00000000 322 | 00000000 323 | 00000000 324 | 00000000 325 | 00000000 326 | 00000000 327 | 00000000 328 | 00000000 329 | 00000000 330 | 00000000 331 | 00000000 332 | 00000000 333 | 00000000 334 | 00000000 335 | 00000000 336 | 00000000 337 | 00000000 338 | 00000000 339 | 00000000 340 | 00000000 341 | 00000000 342 | 00000000 343 | 00000000 344 | 00000000 345 | 00000000 346 | 00000000 347 | 00000000 348 | 00000000 349 | 00000000 350 | 00000000 351 | 00000000 352 | 00000000 353 | 00000000 354 | 00000000 355 | 00000000 356 | 00000000 357 | 00000000 358 | 00000000 359 | 00000000 360 | 00000000 361 | 00000000 362 | 00000000 363 | 00000000 364 | 00000000 365 | 00000000 366 | 00000000 367 | 00000000 368 | 00000000 369 | 00000000 370 | 00000000 371 | 00000000 372 | 00000000 373 | 00000000 374 | 00000000 375 | 00000000 376 | 00000000 377 | 00000000 378 | 00000000 379 | 00000000 380 | 00000000 381 | 00000000 382 | 00000000 383 | 00000000 384 | 00000000 385 | 00000000 386 | 00000000 387 | 00000000 388 | 00000000 389 | 00000000 390 | 00000000 391 | 00000000 392 | 00000000 393 | 00000000 394 | 00000000 395 | 00000000 396 | 00000000 397 | 00000000 398 | 00000000 399 | 00000000 400 | 00000000 401 | 00000000 402 | 00000000 403 | 00000000 404 | 00000000 405 | 00000000 406 | 00000000 407 | 00000000 408 | 00000000 409 | 00000000 410 | 00000000 411 | 00000000 412 | 00000000 413 | 00000000 414 | 00000000 415 | 00000000 416 | 00000000 417 | 00000000 418 | 00000000 419 | 00000000 420 | 00000000 421 | 00000000 422 | 00000000 423 | 00000000 424 | 00000000 425 | 00000000 426 | 00000000 427 | 00000000 428 | 00000000 429 | 00000000 430 | 00000000 431 | 00000000 432 | 00000000 433 | 00000000 434 | 00000000 435 | 00000000 436 | 00000000 437 | 00000000 438 | 00000000 439 | 00000000 440 | 00000000 441 | 00000000 442 | 00000000 443 | 00000000 444 | 00000000 445 | 00000000 446 | 00000000 447 | 00000000 448 | 00000000 449 | 24080010 450 | 40883000 451 | 24090003 452 | 40895000 453 | 240a0046 454 | 408a1000 455 | 240b0006 456 | 408b1800 457 | 42000006 458 | 24080000 459 | 40880000 460 | 24092005 461 | 40895000 462 | 240a0007 463 | 408a1000 464 | 240b0047 465 | 408b1800 466 | 42000002 467 | 24090005 468 | 40895000 469 | 42000008 470 | 40080000 471 | 05080000 472 | 24090003 473 | 40895000 474 | 42000008 475 | 400a0000 476 | 054a0000 477 | ac100000 478 | acb11004 479 | 0000000f 480 | 8c0b0004 481 | 01710036 482 | 8cac1000 483 | 01900036 484 | 8c0d1380 485 | 3c0e2318 486 | 35ce0001 487 | 01ae0036 488 | 24022000 489 | 2403e000 490 | 0000000c 491 | 00000000 492 | 240a2000 493 | 408a5000 494 | 42000008 495 | 00000000 496 | 400b0000 497 | 056a0000 498 | 8c082000 499 | 8ca90000 500 | 01090036 501 | 8c0a3000 502 | 01500036 503 | 8c0b3004 504 | 01710036 505 | ac123008 506 | 24080001 507 | 40880000 508 | 3c090001 509 | 40895000 510 | 240a0006 511 | 408a1000 512 | 240b0006 513 | 408b1800 514 | 240c6000 515 | 408c2800 516 | 42000002 517 | 3c080001 518 | 8d091000 519 | 01300036 520 | 8d0a1004 521 | 01510036 522 | 8d0b1008 523 | 01720036 524 | acb33000 525 | 8d0e3000 526 | 01d30036 527 | 8d0f7000 528 | 01f30036 529 | 24096000 530 | 40895000 531 | 240a001f 532 | 408a1000 533 | 240b005f 534 | 408b1800 535 | 240c0000 536 | 408c2800 537 | 42000006 538 | 8c08600c 539 | 8c89000c 540 | 8c0a7004 541 | 01510036 542 | 8c084000 543 | ac084000 544 | 24080002 545 | 40880000 546 | 24094000 547 | 40895000 548 | 240a0005 549 | 408a1000 550 | 240b0043 551 | 408b1800 552 | 42000002 553 | 8c084000 554 | ac084000 555 | 8c095000 556 | 01300036 557 | ac095000 558 | 0000000f 559 | 3c02bfc0 560 | 2403e000 561 | 0000000c 562 | 00000000 563 | 03e00008 564 | 00000000 565 | ad0fff3c 566 | 00000000 567 | 00000000 568 | 00000000 569 | 00000000 570 | 00000000 571 | -------------------------------------------------------------------------------- /Testbench/TLB_Test/test.S: -------------------------------------------------------------------------------- 1 | #********************MangoMIPS32******************* 2 | # Filename: TLB_test/test.S 3 | # Author: RickyTino 4 | # Version: v1.0.1 5 | #************************************************** 6 | 7 | # TLB_test for MangoMIPS32 8 | # Register Usage: 9 | # a0: base address of kseg0 (0x80000000) 10 | # a1: base address of kseg1 (0xA0000000) 11 | # s0-s3: consts. s0 = 0x01010101, s1 = 0x02020202, and so on. 12 | # t8: times of exceptions 13 | # v0: parameter of Syscall, refers to the address to switch to 14 | # v1: parameter of Syscall, the mask of switching address 15 | 16 | .global __start 17 | .set noreorder 18 | .text 19 | .org 0x0 20 | __start: 21 | # initialize test environment 22 | la $sp, 0xa000a000 # stack pointer: 0xA000A000(p0xA000) 23 | li $a0, 0x80000000 24 | li $a1, 0xA0000000 25 | li $s0, 0x01010101 26 | li $s1, 0x02020202 27 | li $s2, 0x03030303 28 | li $s3, 0x04040404 29 | 30 | # Test 0: Mapping when ERL=1 31 | li $t0, 0x1314 32 | sw $t0, 0x1000($a1) # save: 0x1314 to v0xA0001000(p0x1000) 33 | lw $t1, 0x1000($t1) # load: v0x00001000(p0x1000) 34 | li $t2, 0x0040FF01 35 | mtc0 $t2, $12 # Status = 0x0040FF01 36 | nop 37 | tne $t0, $t1 # Trap if unequal 38 | li $t3, 0x00000003 39 | mtc0 $t3, $16 # Config.K0 = 3 (Cacheable) 40 | jal TLB_test # branch and link to test 41 | nop 42 | wait 43 | 44 | .org 0x200 # TLB Refill Entrance 45 | b excp 46 | nop 47 | 48 | .org 0x380 49 | excp: 50 | addi $t8, $t8, 1 51 | mfc0 $k0, $13 # k0 = cp0.cause 52 | andi $k0, $k0, 0x7C 53 | srl $k0, $k0, 2 # k0 = cp0.cause.exccode 54 | 55 | li $k1, 8 56 | beq $k1, $k0, excp_syscall 57 | nop 58 | b excp_end 59 | nop 60 | 61 | excp_syscall: 62 | and $v0, $v0, $v1 # v0 = v0 & v1(mask) 63 | nor $v1, $v1, $zero # v1 = ~v1 64 | mfc0 $k0, $14 # k0 = EPC 65 | and $k0, $k0, $v1 # k0 = k0 & v1(mask) 66 | or $k0, $k0, $v0 # k0 = v0 | k0 67 | addi $k0, 4 68 | mtc0 $k0, $14 # EPC = k0 69 | nop 70 | eret 71 | 72 | excp_end: 73 | mfc0 $k0, $14 74 | addi $k0, 4 75 | mtc0 $k0, $14 # EPC = EPC + 4 76 | eret 77 | 78 | .org 0x700 79 | TLB_test: 80 | li $t0, 0x10 81 | mtc0 $t0, $6 # Wired = 16 82 | 83 | # Test1: Basic translation & tlb instructions (ASID Match) 84 | li $t1, 0x0003 85 | mtc0 $t1, $10 # EntryHi: VPN2=0x00000/2, ASID=0x03 86 | li $t2, 0x0046 87 | mtc0 $t2, $2 # EntryLo0: PFN=0x00001, DV 88 | li $t3, 0x0006 89 | mtc0 $t3, $3 # EntryLo1: PFN=0x00000, DV 90 | tlbwr 91 | li $t0, 0 92 | mtc0 $t0, $0 # Index=0x00 93 | li $t1, 0x2005 94 | mtc0 $t1, $10 # EntryHi: VPN2=0x00002/2, ASID=0x05 95 | li $t2, 0x0007 96 | mtc0 $t2, $2 # EntryLo0: PFN=0x00000, DVG 97 | li $t3, 0x0047 98 | mtc0 $t3, $3 # EntryLo1: PFN=0x00001, DVG 99 | tlbwi 100 | 101 | li $t1, 0x0005 102 | mtc0 $t1, $10 # EntryHi: VPN2=0x00000/2, ASID=0x05 103 | tlbp # Probe 104 | mfc0 $t0, $0 # t0 = Index 105 | tgei $t0, 0 # Trap if match 106 | 107 | li $t1, 0x0003 108 | mtc0 $t1, $10 # EntryHi: VPN2=0x00000/2, ASID=0x03 109 | tlbp 110 | mfc0 $t2, $0 111 | tlti $t2, 0 # Trap if unmatch 112 | 113 | sw $s0, 0x0000 # save s0 to v0x00000000(p0x1000) 114 | sw $s1, 0x1004($a1) # save s1 to v0xA0001004(p0x1004) 115 | sync 116 | lw $t3, 0x0004 # load from v0x00000004(p0x1004) 117 | tne $t3, $s1 # trap if unequal 118 | lw $t4, 0x1000($a1) # load from v0xA0001000(p0x1000) 119 | tne $t4, $s0 # trap if unequal 120 | lw $t5, 0x1380 # load from v0x00001380(p0x0380) 121 | li $t6, 0x23180001 # <- the first instruction of exception 122 | tne $t5, $t6 # trap if unequal 123 | 124 | # Test1+: executing instruction in an TLB-translated virtual address space 125 | # sw $ra, ($sp) # push ra to stack 126 | # la $ra, Label1 127 | # bal L1 # ra <= PC 128 | # nop 129 | 130 | # L1: 131 | # andi $t0, $ra, 0xFFFF 132 | # addi $t0, $t0, 0x2010 # t0[31:16] = 0x0000, points at Test 2 133 | # jr $t0 134 | # nop # the following instruction is in page 0x00002000 135 | 136 | li $v0, 0x00002000 137 | li $v1, 0xFFFFE000 138 | syscall 139 | nop # the following instruction is in page 0x00002000 140 | 141 | # Test2: field G 142 | li $t2, 0x2000 143 | mtc0 $t2, $10 # EntryHi: VPN2=0x00002/2, ASID=0x00 144 | tlbp # probe for matching page 145 | nop 146 | mfc0 $t3, $0 147 | tlti $t3, 0 # Trap if unmatch 148 | 149 | lw $t0, 0x2000 # load from v0x00002000(p0x0000) 150 | lw $t1, 0x0000($a1) # <- the very first instruction 151 | # li $t1, 0x24090000 152 | tne $t0, $t1 # trap if unequal 153 | lw $t2, 0x3000 # load from v0x00003000(p0x1000) 154 | tne $t2, $s0 # trap if unequal 155 | lw $t3, 0x3004 # load from v0x00003004(p0x1004) 156 | tne $t3, $s1 # trap if unequal 157 | sw $s2, 0x3008 # save s2 to v0x00003008(p0x1008) 158 | 159 | # Test3: 16KB big page (mask) 160 | li $t0, 1 161 | mtc0 $t0, $0 # Index=0x01 162 | li $t1, 0x00010000 163 | mtc0 $t1, $10 # EntryHi: VPN2=0x00010/2, ASID=0x00 164 | li $t2, 0x0006 165 | mtc0 $t2, $2 # EntryLo0: PFN=0x00000, DV 166 | li $t3, 0x0006 167 | mtc0 $t3, $3 # EntryLo1: PFN=0x00000, DV 168 | li $t4, 0x6000 169 | mtc0 $t4, $5 # PageMask: Mask=0x0003 170 | tlbwi 171 | 172 | lui $t0, 0x0001 173 | lw $t1, 0x1000($t0) # load from v0x00011000(p0x1000) 174 | tne $t1, $s0 175 | lw $t2, 0x1004($t0) # load from v0x00011004(p0x1004) 176 | tne $t2, $s1 177 | lw $t3, 0x1008($t0) # load from v0x00011008(p0x1008) 178 | tne $t3, $s2 179 | 180 | sw $s3, 0x3000($a1) # save s3 to v0xA0003000(p0x3000) 181 | lw $t6, 0x3000($t0) # load from v0x00013000(p0x3000) 182 | tne $t6, $s3 183 | lw $t7, 0x7000($t0) # load from v0x00017000(p0x3000) 184 | tne $t7, $s3 185 | 186 | # Test 4: Cacheability test 187 | li $t1, 0x00006000 188 | mtc0 $t1, $10 # EntryHi: VPN2=0x00006/2, ASID=0x00 189 | li $t2, 0x001F 190 | mtc0 $t2, $2 # EntryLo0: PFN=0x00000, CDVG 191 | li $t3, 0x005F 192 | mtc0 $t3, $3 # EntryLo1: PFN=0x00001, CDVG 193 | li $t4, 0x00 194 | mtc0 $t4, $5 # PageMask: Mask=0x0000 195 | tlbwr 196 | 197 | lw $t0, 0x600C # load from v0x0000600C(p0x000C) 198 | lw $t1, 0x000C($a0) 199 | lw $t2, 0x7004 # load from v0x00007004(p0x1004) 200 | tne $t2, $s1 201 | 202 | # Test 5: TLB exceptions 203 | lw $t0, 0x4000 # load: TLBRefill-TLBL 204 | sw $t0, 0x4000 # save: TLBRefill-TLBS 205 | 206 | li $t0, 2 207 | mtc0 $t0, $0 # Index=0x02 208 | li $t1, 0x4000 209 | mtc0 $t1, $10 # EntryHi: VPN2=0x00004/2, ASID=0x00 210 | li $t2, 0x0005 211 | mtc0 $t2, $2 # EntryLo0: PFN=0x00000, DG 212 | li $t3, 0x0043 213 | mtc0 $t3, $3 # EntryLo1: PFN=0x00001, VG 214 | tlbwi 215 | lw $t0, 0x4000 # load: TLBInvalid-TLBL 216 | sw $t0, 0x4000 # save: TLBInvalid-TLBS 217 | lw $t1, 0x5000 # load from v0x00005000(p0x1000) 218 | tne $t1, $s0 219 | sw $t1, 0x5000 # save: TLBModified-TLBS 220 | sync 221 | 222 | # Test 6: Getting back to kseg1 address space 223 | # bal L2 224 | # nop 225 | # L2: 226 | # lui $t0, 0xBFC0 227 | # addi $ra, $ra, -0x1FEC 228 | # add $t0, $t0, $ra 229 | # jr $t0 230 | # nop 231 | li $v0, 0xBFC00000 232 | li $v1, 0xFFFFE000 233 | syscall 234 | nop 235 | 236 | # Test end, return 237 | # lw $ra, ($sp) 238 | jr $ra 239 | nop 240 | -------------------------------------------------------------------------------- /Src/Xilinx_IP/DCache_Ram_IP/DCache_Ram_IP.xci: -------------------------------------------------------------------------------- 1 | 2 | 3 | xilinx.com 4 | xci 5 | unknown 6 | 1.0 7 | 8 | 9 | DCache_Ram_IP 10 | 11 | 12 | 11 13 | 0 14 | 2048 15 | ./ 16 | artix7 17 | 1 18 | 1 19 | 0 20 | 0 21 | 0 22 | 0 23 | 0 24 | 0 25 | 0 26 | 0 27 | 0 28 | 0 29 | 0 30 | 0 31 | 1 32 | 1 33 | no_coe_file_loaded 34 | 1 35 | 1 36 | 0 37 | 0 38 | 0 39 | 0 40 | 0 41 | 0 42 | 1 43 | 8 44 | DCache_Ram_IP 45 | 0 46 | ce_overrides_sync_controls 47 | no_coe_file_loaded 48 | false 49 | false 50 | 8 51 | 0 52 | 16 53 | 2048 54 | non_registered 55 | false 56 | false 57 | non_registered 58 | single_port_ram 59 | non_registered 60 | false 61 | false 62 | false 63 | false 64 | non_registered 65 | false 66 | false 67 | false 68 | false 69 | false 70 | artix7 71 | 72 | xc7a200t 73 | fbg676 74 | VERILOG 75 | 76 | MIXED 77 | -2 78 | 79 | TRUE 80 | TRUE 81 | IP_Flow 82 | 12 83 | TRUE 84 | . 85 | 86 | . 87 | 2018.1 88 | OUT_OF_CONTEXT 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /Src/Xilinx_IP/ICache_Ram_IP/ICache_Ram_IP.xci: -------------------------------------------------------------------------------- 1 | 2 | 3 | xilinx.com 4 | xci 5 | unknown 6 | 1.0 7 | 8 | 9 | ICache_Ram_IP 10 | 11 | 12 | 11 13 | 0 14 | 2048 15 | ./ 16 | artix7 17 | 1 18 | 1 19 | 1 20 | 1 21 | 0 22 | 0 23 | 0 24 | 0 25 | 0 26 | 0 27 | 0 28 | 0 29 | 0 30 | 0 31 | 0 32 | 1 33 | no_coe_file_loaded 34 | 4 35 | 1 36 | 0 37 | 0 38 | 0 39 | 0 40 | 0 41 | 0 42 | 1 43 | 32 44 | ICache_Ram_IP 45 | 0 46 | ce_overrides_sync_controls 47 | no_coe_file_loaded 48 | false 49 | false 50 | 32 51 | 0 52 | 16 53 | 2048 54 | non_registered 55 | false 56 | false 57 | non_registered 58 | simple_dual_port_ram 59 | non_registered 60 | false 61 | false 62 | false 63 | false 64 | non_registered 65 | false 66 | false 67 | false 68 | false 69 | false 70 | artix7 71 | 72 | xc7a200t 73 | fbg676 74 | VERILOG 75 | 76 | MIXED 77 | -2 78 | 79 | TRUE 80 | TRUE 81 | IP_Flow 82 | 12 83 | TRUE 84 | . 85 | 86 | . 87 | 2018.1 88 | OUT_OF_CONTEXT 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /Src/Cache/ICache_Controller.v: -------------------------------------------------------------------------------- 1 | /********************MangoMIPS32******************* 2 | Filename : ICache_Controller.v 3 | Author : RickyTino 4 | Version : v1.1.3 5 | **************************************************/ 6 | `include "../Config.v" 7 | `include "../Defines.v" 8 | 9 | module ICache_Controller 10 | ( 11 | input wire aclk, 12 | input wire aresetn, 13 | output reg [ 3 : 0 ] arid, 14 | output reg [ 31 : 0 ] araddr, 15 | output reg [ 3 : 0 ] arlen, 16 | output wire [ 2 : 0 ] arsize, 17 | output wire [ 1 : 0 ] arburst, 18 | output wire [ 1 : 0 ] arlock, 19 | output wire [ 3 : 0 ] arcache, 20 | output wire [ 2 : 0 ] arprot, 21 | output reg arvalid, 22 | input wire arready, 23 | input wire [ 3 : 0 ] rid, 24 | input wire [ 31 : 0 ] rdata, 25 | input wire [ 1 : 0 ] rresp, 26 | input wire rlast, 27 | input wire rvalid, 28 | output wire rready, 29 | output wire [ 3 : 0 ] awid, 30 | output wire [ 31 : 0 ] awaddr, 31 | output wire [ 3 : 0 ] awlen, 32 | output wire [ 2 : 0 ] awsize, 33 | output wire [ 1 : 0 ] awburst, 34 | output wire [ 1 : 0 ] awlock, 35 | output wire [ 3 : 0 ] awcache, 36 | output wire [ 2 : 0 ] awprot, 37 | output wire awvalid, 38 | input wire awready, 39 | output wire [ 3 : 0 ] wid, 40 | output wire [ 31 : 0 ] wdata, 41 | output wire [ 3 : 0 ] wstrb, 42 | output wire wlast, 43 | output wire wvalid, 44 | input wire wready, 45 | input wire [ 3 : 0 ] bid, 46 | input wire [ 1 : 0 ] bresp, 47 | input wire bvalid, 48 | output wire bready, 49 | 50 | input wire bus_en, 51 | input wire [`ByteWEn] bus_wen, 52 | input wire [`AddrBus] bus_addr, 53 | output wire [`DataBus] bus_rdata, 54 | input wire [`DataBus] bus_wdata, 55 | input wire [`AXISize] bus_size, 56 | output wire bus_streq, 57 | input wire bus_stall, 58 | input wire bus_cached, 59 | 60 | input wire [`CacheOp] cacheop, 61 | input wire cop_en, 62 | input wire [`AddrBus] cop_addr, 63 | input wire [`DataBus] cop_itag 64 | ); 65 | 66 | assign arsize = 3'b010; 67 | assign arburst = 2'b01; 68 | assign arlock = 2'b0; 69 | assign arcache = 4'b0; 70 | assign arprot = 3'b0; 71 | assign rready = 1'b1; 72 | assign awid = 4'b0; 73 | assign awaddr = 32'b0; 74 | assign awlen = 4'b0; 75 | assign awsize = 3'b010; 76 | assign awburst = 2'b01; 77 | assign awlock = 2'b0; 78 | assign awcache = 4'b0; 79 | assign awprot = 3'b0; 80 | assign awvalid = 1'b0; 81 | assign wid = 4'b0; 82 | assign wdata = 32'b0; 83 | assign wstrb = 4'b0; 84 | assign wlast = 1'b0; 85 | assign wvalid = 1'b0; 86 | assign bready = 1'b1; 87 | 88 | wire cop_nop = !cacheop[0]; // See Cache Op definition 89 | wire cached; 90 | 91 | `ifdef IF_Force_Cached 92 | assign cached = 1'b1; 93 | `else 94 | assign cached = bus_cached; 95 | `endif 96 | 97 | // Sync Reset 98 | reg ca_rstn; 99 | always @(posedge aclk) ca_rstn <= aresetn; 100 | 101 | // Cached Channel 102 | reg ca_wen; 103 | reg [`I_ramad] ca_adw; 104 | wire [`I_ramad] ca_adr; 105 | reg [`DataBus] ca_din; 106 | wire [`DataBus] ca_dout; 107 | 108 | ICache_Ram icache_ram ( 109 | .clk (aclk ), 110 | .wen (ca_wen ), 111 | .adw (ca_adw ), 112 | .adr (ca_adr ), 113 | .din (ca_din ), 114 | .dout (ca_dout) 115 | ); 116 | 117 | reg [`I_ptag] ca_ptag [`I_lnNum]; 118 | reg ca_valid [`I_lnNum]; 119 | 120 | wire [`I_idx ] ad_idx = bus_addr[`I_addr_idx ]; 121 | wire [`I_ptag] ad_ptag = bus_addr[`I_addr_ptag]; 122 | wire [`I_ptag] ln_ptag = ca_ptag [ad_idx]; 123 | wire ln_valid = ca_valid[ad_idx]; 124 | wire ln_hit = (ln_ptag ^ ad_ptag) == 0 && ln_valid; 125 | 126 | assign ca_adr = bus_addr[`I_addr_ramad]; 127 | 128 | //Cache Operation Channel 129 | wire [`I_idx ] cad_idx = cop_addr[`I_addr_idx ]; 130 | wire [`I_ptag] cad_ptag = cop_addr[`I_addr_ptag]; 131 | wire [`I_ptag] cln_ptag = ca_ptag [cad_idx]; 132 | wire cln_valid = ca_valid[cad_idx]; 133 | wire cln_hit = (cln_ptag ^ cad_ptag) == 0 && cln_valid; 134 | 135 | // Uncached Channel 136 | reg [`Word] uc_data; 137 | reg [`Word] uc_addr; 138 | reg uc_valid; 139 | wire uc_hit = (uc_addr ^ bus_addr) == 0 && uc_valid; 140 | 141 | reg r_streq; 142 | reg cop_streq; 143 | 144 | always @(*) begin 145 | cop_streq <= `false; 146 | r_streq <= `false; 147 | 148 | if(bus_en) begin 149 | if(!cop_nop) begin 150 | case (cacheop) 151 | `COP_III, 152 | `COP_IIST, 153 | `COP_IHI: cop_streq <= `true; 154 | endcase 155 | end 156 | else begin 157 | r_streq <= cached ? !ln_hit : !uc_hit; 158 | end 159 | end 160 | end 161 | 162 | assign bus_streq = r_streq || cop_streq; 163 | 164 | reg [ 3 : 0] cnt; 165 | reg [ 2 : 0] state; 166 | reg [`Word ] lk_addr; 167 | reg lk_cached; 168 | 169 | wire [`I_idx] lk_idx = lk_addr[`I_addr_idx]; 170 | 171 | parameter S_IDLE = 3'h0; 172 | parameter S_FILLCACHE_PREPARE = 3'h1; 173 | parameter S_FILLCACHE_TRANSFER = 3'h2; 174 | parameter S_FILLCACHE_END = 3'h3; 175 | parameter S_UC_READ_PREPARE = 3'h4; 176 | parameter S_UC_READ_TRANSFER = 3'h5; 177 | parameter S_UC_READ_WAITEND = 3'h6; 178 | 179 | always @(posedge aclk, negedge ca_rstn) begin 180 | if(!ca_rstn) begin 181 | state <= 0; 182 | cnt <= 0; 183 | lk_addr <= `ZeroWord; 184 | lk_cached <= `false; 185 | 186 | arid <= 0; 187 | araddr <= 0; 188 | arlen <= 0; 189 | arvalid <= 0; 190 | 191 | ca_wen <= `false; 192 | ca_adw <= 0; 193 | ca_din <= `ZeroWord; 194 | 195 | uc_data <= `ZeroWord; 196 | uc_addr <= `ZeroWord; 197 | uc_valid <= `false; 198 | end 199 | else begin 200 | arvalid <= 0; 201 | 202 | ca_wen <= `false; 203 | ca_adw <= 0; 204 | ca_din <= `ZeroWord; 205 | 206 | case (state) 207 | S_IDLE: 208 | // if(!cop_nop) begin 209 | // case (cacheop) 210 | // `COP_III: ca_valid[ad_idx] <= `false; 211 | 212 | // `COP_IIST: begin 213 | // ca_ptag [ad_idx] <= cop_itag[`ITag_Tag]; 214 | // ca_valid[ad_idx] <= cop_itag[`ITag_Vld]; 215 | // end 216 | 217 | // `COP_IHI: 218 | // if(ln_hit) ca_valid[ad_idx] <= `false; 219 | // endcase 220 | // end 221 | // else begin 222 | if(cop_nop) begin 223 | if(cached) begin 224 | if(bus_en && !ln_hit) begin 225 | lk_addr <= {bus_addr[31 : 6], 6'b0}; 226 | lk_cached <= `true; 227 | cnt <= 0; 228 | state <= S_FILLCACHE_PREPARE; 229 | // ca_ptag [ad_idx] <= bus_addr[`I_addr_ptag]; 230 | // ca_valid[ad_idx] <= `false; 231 | end 232 | end 233 | else begin 234 | if(bus_en && !uc_hit) begin 235 | lk_addr <= bus_addr; 236 | lk_cached <= `false; 237 | state <= S_UC_READ_PREPARE; 238 | end 239 | end 240 | end 241 | 242 | // Cache Fill 243 | S_FILLCACHE_PREPARE: 244 | if(arvalid && arready) state <= 2; 245 | else begin 246 | arid <= 4'b0011; 247 | araddr <= lk_addr; 248 | arlen <= 4'hF; 249 | arvalid <= `true; 250 | end 251 | 252 | S_FILLCACHE_TRANSFER: 253 | if(rvalid) begin 254 | ca_wen <= `true; 255 | ca_adw <= {lk_idx, cnt}; 256 | ca_din <= rdata; 257 | cnt <= cnt + 1; 258 | if(rlast) state <= S_FILLCACHE_END; 259 | end 260 | 261 | S_FILLCACHE_END: begin 262 | // ca_valid[lk_idx] <= `true; 263 | state <= S_IDLE; 264 | end 265 | 266 | // Uncached Read 267 | S_UC_READ_PREPARE: 268 | if(arvalid && arready) state <= S_UC_READ_TRANSFER; 269 | else begin 270 | arid <= 4'b0010; 271 | araddr <= lk_addr; 272 | arlen <= 4'h0; 273 | arvalid <= `true; 274 | end 275 | 276 | S_UC_READ_TRANSFER: 277 | if(rvalid) begin 278 | uc_data <= rdata; 279 | uc_addr <= lk_addr; 280 | if(rlast) begin 281 | uc_valid <= `true; 282 | state <= S_UC_READ_WAITEND; 283 | end 284 | end 285 | 286 | S_UC_READ_WAITEND: begin 287 | if((bus_stall ^ r_streq) == 0) begin 288 | state <= S_IDLE; 289 | uc_valid <= `false; 290 | end 291 | end 292 | endcase 293 | end 294 | end 295 | 296 | integer i; 297 | initial begin 298 | for(i = 0; i < `I_lineN; i = i + 1) begin 299 | ca_ptag [i] <= 0; 300 | ca_valid[i] <= `false; 301 | end 302 | end 303 | 304 | always @(posedge aclk) begin 305 | if(!ca_rstn) begin 306 | for(i = 0; i < `I_lineN; i = i + 1) begin 307 | ca_valid[i] <= `false; 308 | end 309 | end 310 | else begin 311 | case (state) 312 | S_IDLE: 313 | if(!cop_nop && cop_en) begin 314 | case (cacheop) 315 | `COP_III: ca_valid[cad_idx] <= `false; 316 | `COP_IIST: begin 317 | ca_ptag [cad_idx] <= cop_itag[`ITag_Tag]; 318 | ca_valid[cad_idx] <= cop_itag[`ITag_Vld]; 319 | end 320 | `COP_IHI: 321 | if(cln_hit) ca_valid[cad_idx] <= `false; 322 | endcase 323 | end 324 | else begin 325 | if(cached) begin 326 | if(bus_en && !ln_hit) begin 327 | ca_ptag [ad_idx] <= bus_addr[`I_addr_ptag]; 328 | ca_valid[ad_idx] <= `false; 329 | end 330 | end 331 | end 332 | 333 | S_FILLCACHE_END: ca_valid[lk_idx] <= `true; 334 | endcase 335 | end 336 | end 337 | 338 | assign bus_rdata = cached ? ca_dout : uc_data; 339 | 340 | endmodule -------------------------------------------------------------------------------- /Src/Core/ALU_EX.v: -------------------------------------------------------------------------------- 1 | /********************MangoMIPS32******************* 2 | Filename: ALU_EX.v 3 | Author: RickyTino 4 | Version: v1.1.3 5 | **************************************************/ 6 | `include "../Config.v" 7 | `include "../Defines.v" 8 | 9 | module ALU_EX 10 | ( 11 | input wire [`AddrBus] pc, 12 | input wire [`ALUOp ] aluop, 13 | input wire [`DataBus] opr1, 14 | input wire [`DataBus] opr2, 15 | input wire [`DataBus] offset, 16 | 17 | output reg div_start, 18 | output reg div_signed, 19 | input wire div_ready, 20 | 21 | output reg [`DataBus] alures, 22 | output reg resnrdy, 23 | output wire [`DWord ] mulhi, 24 | output wire [`DWord ] mullo, 25 | output reg mul_s, 26 | 27 | output reg m_en, 28 | output reg [`ByteWEn] m_wen, 29 | output reg [`AddrBus] m_vaddr, 30 | output reg [`DataBus] m_wdata, 31 | output reg [`AXISize] m_size, 32 | input wire wreg, 33 | output reg [`ByteWEn] wregsel, 34 | 35 | input wire llbit_i, 36 | output reg llb_wen, 37 | output reg llbit_o, 38 | 39 | input wire usermode, 40 | input wire [`ExcBus ] excp_i, 41 | output reg [`ExcBus ] excp_o, 42 | output reg [`TLBOp ] tlbop, 43 | 44 | output wire stallreq 45 | ); 46 | 47 | assign stallreq = div_start; 48 | 49 | // Signs 50 | wire opr1_s = opr1[31]; 51 | wire opr2_s = opr2[31]; 52 | wire res_s = alures[31]; 53 | 54 | wire [`Word] abs_opr1 = opr1_s ? ~opr1 + 32'd1 : opr1; 55 | wire [`Word] abs_opr2 = opr2_s ? ~opr2 + 32'd1 : opr2; 56 | wire opr_lt = $signed(opr1) < $signed(opr2); 57 | wire opr_ltu = opr1 < opr2; 58 | wire opr_eq = (opr1 ^ opr2) == `ZeroWord; 59 | 60 | // CLO/CLZ 61 | reg [`Word] clzopr; 62 | reg [`Word] clzres; 63 | 64 | always @(*) begin 65 | case (aluop) 66 | `ALU_CLO: clzopr <= ~opr1; 67 | `ALU_CLZ: clzopr <= opr1; 68 | default: clzopr <= `ZeroWord; 69 | endcase 70 | 71 | casez (clzopr) 72 | 32'b00000000000000000000000000000000: clzres <= 32; 73 | 32'b00000000000000000000000000000001: clzres <= 31; 74 | 32'b0000000000000000000000000000001?: clzres <= 30; 75 | 32'b000000000000000000000000000001??: clzres <= 29; 76 | 32'b00000000000000000000000000001???: clzres <= 28; 77 | 32'b0000000000000000000000000001????: clzres <= 27; 78 | 32'b000000000000000000000000001?????: clzres <= 26; 79 | 32'b00000000000000000000000001??????: clzres <= 25; 80 | 32'b0000000000000000000000001???????: clzres <= 24; 81 | 32'b000000000000000000000001????????: clzres <= 23; 82 | 32'b00000000000000000000001?????????: clzres <= 22; 83 | 32'b0000000000000000000001??????????: clzres <= 21; 84 | 32'b000000000000000000001???????????: clzres <= 20; 85 | 32'b00000000000000000001????????????: clzres <= 19; 86 | 32'b0000000000000000001?????????????: clzres <= 18; 87 | 32'b000000000000000001??????????????: clzres <= 17; 88 | 32'b00000000000000001???????????????: clzres <= 16; 89 | 32'b0000000000000001????????????????: clzres <= 15; 90 | 32'b000000000000001?????????????????: clzres <= 14; 91 | 32'b00000000000001??????????????????: clzres <= 13; 92 | 32'b0000000000001???????????????????: clzres <= 12; 93 | 32'b000000000001????????????????????: clzres <= 11; 94 | 32'b00000000001?????????????????????: clzres <= 10; 95 | 32'b0000000001??????????????????????: clzres <= 9; 96 | 32'b000000001???????????????????????: clzres <= 8; 97 | 32'b00000001????????????????????????: clzres <= 7; 98 | 32'b0000001?????????????????????????: clzres <= 6; 99 | 32'b000001??????????????????????????: clzres <= 5; 100 | 32'b00001???????????????????????????: clzres <= 4; 101 | 32'b0001????????????????????????????: clzres <= 3; 102 | 32'b001?????????????????????????????: clzres <= 2; 103 | 32'b01??????????????????????????????: clzres <= 1; 104 | 32'b1???????????????????????????????: clzres <= 0; 105 | endcase 106 | end 107 | 108 | // Multiply first stage 109 | reg [`Word] mopr1, mopr2; 110 | 111 | always @(*) begin 112 | case (aluop) 113 | `ALU_MUL, 114 | `ALU_MULT, 115 | `ALU_MADD, 116 | `ALU_MSUB: begin 117 | mopr1 <= abs_opr1; 118 | mopr2 <= abs_opr2; 119 | mul_s <= opr1_s ^ opr2_s; 120 | end 121 | 122 | `ALU_MULTU, 123 | `ALU_MADDU, 124 | `ALU_MSUBU: begin 125 | mopr1 <= opr1; 126 | mopr2 <= opr2; 127 | mul_s <= `Zero; 128 | end 129 | 130 | default: begin 131 | mopr1 <= `ZeroWord; 132 | mopr2 <= `ZeroWord; 133 | mul_s <= `Zero; 134 | end 135 | endcase 136 | end 137 | 138 | assign mullo[31: 0] = mopr1[15: 0] * mopr2[15: 0]; 139 | assign mullo[63:32] = mopr1[31:16] * mopr2[15: 0]; 140 | assign mulhi[31: 0] = mopr1[15: 0] * mopr2[31:16]; 141 | assign mulhi[63:32] = mopr1[31:16] * mopr2[31:16]; 142 | 143 | // Divider 144 | always @(*) begin 145 | case (aluop) 146 | `ALU_DIV: begin 147 | div_signed <= `true; 148 | div_start <= !div_ready; 149 | end 150 | 151 | `ALU_DIVU: begin 152 | div_signed <= `false; 153 | div_start <= !div_ready; 154 | end 155 | 156 | default: begin 157 | div_signed <= `false; 158 | div_start <= `false; 159 | end 160 | endcase 161 | end 162 | 163 | // Memory Data Prepare 164 | wire [`AddrBus] sl_addr = opr1 + offset; 165 | reg [`ByteWEn] sel_l, sel_r; 166 | reg exc_ade; 167 | wire exc_user = usermode & sl_addr[31]; 168 | 169 | always @(*) begin 170 | m_en <= `false; 171 | m_wen <= `WrDisable; 172 | m_vaddr <= `ZeroWord; 173 | m_wdata <= `ZeroWord; 174 | m_size <= `ASize_Word; 175 | wregsel <= {4{wreg}}; 176 | llb_wen <= `false; 177 | llbit_o <= llbit_i; 178 | exc_ade <= `false; 179 | 180 | case (aluop) 181 | `ALU_CACHE:begin 182 | m_en <= `true; 183 | m_vaddr <= sl_addr; 184 | exc_ade <= exc_user; 185 | end 186 | 187 | `ALU_LB, 188 | `ALU_LBU:begin 189 | m_en <= `true; 190 | m_vaddr <= sl_addr; 191 | m_size <= `ASize_Byte; 192 | exc_ade <= exc_user; 193 | end 194 | 195 | `ALU_LH, 196 | `ALU_LHU: begin 197 | m_en <= `true; 198 | m_vaddr <= sl_addr; 199 | m_size <= `ASize_Half; 200 | exc_ade <= exc_user || sl_addr[0]; 201 | end 202 | 203 | `ALU_LW: begin 204 | m_en <= `true; 205 | m_vaddr <= sl_addr; 206 | exc_ade <= exc_user || (sl_addr[1:0] != 2'b00); 207 | end 208 | 209 | `ALU_LWL: begin 210 | m_en <= `true; 211 | m_vaddr <= sl_addr; 212 | wregsel <= sel_l; 213 | exc_ade <= exc_user; 214 | end 215 | 216 | `ALU_LWR: begin 217 | m_en <= `true; 218 | m_vaddr <= sl_addr; 219 | wregsel <= sel_r; 220 | exc_ade <= exc_user; 221 | end 222 | 223 | `ALU_SB: begin 224 | m_en <= `true; 225 | m_vaddr <= sl_addr; 226 | m_wdata <= {4{opr2[7:0]}}; 227 | m_size <= `ASize_Byte; 228 | exc_ade <= exc_user; 229 | case (sl_addr[1:0]) 230 | 2'b00: m_wen <= 4'b0001; 231 | 2'b01: m_wen <= 4'b0010; 232 | 2'b10: m_wen <= 4'b0100; 233 | 2'b11: m_wen <= 4'b1000; 234 | endcase 235 | end 236 | 237 | `ALU_SH: begin 238 | m_en <= `true; 239 | m_vaddr <= sl_addr; 240 | m_wdata <= {2{opr2[15:0]}}; 241 | m_size <= `ASize_Half; 242 | exc_ade <= exc_user || sl_addr[0]; 243 | m_wen <= sl_addr[1] ? 4'b1100 : 4'b0011; 244 | end 245 | 246 | `ALU_SW: begin 247 | m_en <= `true; 248 | m_vaddr <= sl_addr; 249 | m_wdata <= opr2; 250 | m_wen <= 4'b1111; 251 | exc_ade <= exc_user || (sl_addr[1:0] != 2'b00); 252 | end 253 | 254 | `ALU_SWL: begin 255 | m_en <= `true; 256 | m_vaddr <= {sl_addr[31:2], 2'b00}; 257 | exc_ade <= exc_user; 258 | case (sl_addr[1:0]) 259 | 2'b00: begin 260 | m_wen <= 4'b0001; 261 | m_wdata <= {24'b0, opr2[31:24]}; 262 | end 263 | 2'b01: begin 264 | m_wen <= 4'b0011; 265 | m_wdata <= {16'b0, opr2[31:16]}; 266 | end 267 | 2'b10: begin 268 | m_wen <= 4'b0111; 269 | m_wdata <= { 8'b0, opr2[31: 8]}; 270 | end 271 | 2'b11: begin 272 | m_wen <= 4'b1111; 273 | m_wdata <= opr2; 274 | end 275 | endcase 276 | end 277 | 278 | `ALU_SWR: begin 279 | m_en <= `true; 280 | m_vaddr <= {sl_addr[31:2], 2'b00}; 281 | exc_ade <= exc_user; 282 | case (sl_addr[1:0]) 283 | 2'b00: begin 284 | m_wen <= 4'b1111; 285 | m_wdata <= opr2; 286 | end 287 | 2'b01: begin 288 | m_wen <= 4'b1110; 289 | m_wdata <= {opr2[23:0], 8'b0}; 290 | end 291 | 2'b10: begin 292 | m_wen <= 4'b1100; 293 | m_wdata <= {opr2[15:0], 16'b0}; 294 | end 295 | 2'b11: begin 296 | m_wen <= 4'b1000; 297 | m_wdata <= {opr2[ 7:0], 24'b0}; 298 | end 299 | endcase 300 | end 301 | 302 | `ALU_LL: begin 303 | m_en <= `true; 304 | m_vaddr <= sl_addr; 305 | llb_wen <= `true; 306 | llbit_o <= `One; 307 | exc_ade <= exc_user || (sl_addr[1:0] != 2'b00); 308 | end 309 | 310 | `ALU_SC: if(llbit_i) begin 311 | m_en <= `true; 312 | m_vaddr <= sl_addr; 313 | m_wdata <= opr2; 314 | m_wen <= 4'b1111; 315 | exc_ade <= exc_user || (sl_addr[1:0] != 2'b00); 316 | end 317 | endcase 318 | 319 | case (sl_addr[1:0]) 320 | 2'b00: begin sel_l <= 4'b1000; sel_r <= 4'b1111; end 321 | 2'b01: begin sel_l <= 4'b1100; sel_r <= 4'b0111; end 322 | 2'b10: begin sel_l <= 4'b1110; sel_r <= 4'b0011; end 323 | 2'b11: begin sel_l <= 4'b1111; sel_r <= 4'b0001; end 324 | endcase 325 | end 326 | 327 | // Exception 328 | reg exc_ov, exc_tr; 329 | 330 | always @(*) begin 331 | case (aluop) 332 | `ALU_ADD: exc_ov <= (opr1_s & opr2_s & ~res_s) | (~opr1_s & ~opr2_s & res_s); 333 | `ALU_SUB: exc_ov <= (opr1_s & ~opr2_s & ~res_s) | (~opr1_s & opr2_s & res_s); 334 | default: exc_ov <= `false; 335 | endcase 336 | 337 | case (aluop) 338 | `ALU_TGE: exc_tr <= ~opr_lt; 339 | `ALU_TGEU: exc_tr <= ~opr_ltu; 340 | `ALU_TLT: exc_tr <= opr_lt; 341 | `ALU_TLTU: exc_tr <= opr_ltu; 342 | `ALU_TEQ: exc_tr <= opr_eq; 343 | `ALU_TNE: exc_tr <= ~opr_eq; 344 | default: exc_tr <= `false; 345 | endcase 346 | 347 | case (aluop) 348 | `ALU_TLBR: tlbop <= `TOP_TLBR; 349 | `ALU_TLBWI: tlbop <= `TOP_TLBWI; 350 | `ALU_TLBWR: tlbop <= `TOP_TLBWR; 351 | `ALU_TLBP: tlbop <= `TOP_TLBP; 352 | default: tlbop <= `TOP_NOP; 353 | endcase 354 | end 355 | 356 | always @(*) begin 357 | excp_o <= excp_i; 358 | excp_o[`Exc_Ov ] <= exc_ov; 359 | excp_o[`Exc_Trap ] <= exc_tr; 360 | excp_o[`Exc_D_AdE] <= exc_ade; 361 | end 362 | 363 | // General 364 | always @(*) begin 365 | case (aluop) 366 | `ALU_SLL: alures <= opr2 << opr1[4:0]; 367 | `ALU_SRL: alures <= opr2 >> opr1[4:0]; 368 | `ALU_SRA: alures <= ($signed(opr2)) >>> opr1[4:0]; 369 | `ALU_ADD, 370 | `ALU_ADDU: alures <= opr1 + opr2; 371 | `ALU_SUB, 372 | `ALU_SUBU: alures <= opr1 - opr2; 373 | `ALU_AND: alures <= opr1 & opr2; 374 | `ALU_OR: alures <= opr1 | opr2; 375 | `ALU_XOR: alures <= opr1 ^ opr2; 376 | `ALU_NOR: alures <= ~(opr1 | opr2); 377 | `ALU_SLT: alures <= opr_lt; 378 | `ALU_SLTU: alures <= opr_ltu; 379 | `ALU_MOV, 380 | `ALU_MTHI, 381 | `ALU_MTLO: alures <= opr1; 382 | `ALU_CLO, 383 | `ALU_CLZ: alures <= clzres; 384 | `ALU_BAL: alures <= pc + 32'd8; 385 | `ALU_SC: alures <= {31'b0, llbit_i}; 386 | `ALU_MTC0: alures <= opr2; 387 | default: alures <= `ZeroWord; 388 | endcase 389 | 390 | case (aluop) 391 | `ALU_LB, 392 | `ALU_LBU, 393 | `ALU_LH, 394 | `ALU_LHU, 395 | `ALU_LW, 396 | `ALU_LWL, 397 | `ALU_LWR, 398 | `ALU_LL, 399 | `ALU_MFHI, 400 | `ALU_MFLO, 401 | `ALU_MFC0, 402 | `ALU_MUL: resnrdy <= `true; 403 | default: resnrdy <= `false; 404 | endcase 405 | end 406 | 407 | endmodule -------------------------------------------------------------------------------- /Src/MangoMIPS_Top.v: -------------------------------------------------------------------------------- 1 | /********************MangoMIPS32******************* 2 | Filename: MangoMIPS_Top.v 3 | Author: RickyTino 4 | Version: v1.1.3 5 | **************************************************/ 6 | `include "Defines.v" 7 | `include "Config.v" 8 | 9 | module MangoMIPS_Top 10 | ( 11 | input wire cpu_clk, 12 | input wire cpu_rstn, 13 | input wire [ 5: 0] intr, 14 | 15 | output wire [ 3: 0] m_axi_arid, 16 | output wire [31: 0] m_axi_araddr, 17 | output wire [ 3: 0] m_axi_arlen, 18 | output wire [ 2: 0] m_axi_arsize, 19 | output wire [ 1: 0] m_axi_arburst, 20 | output wire [ 1: 0] m_axi_arlock, 21 | output wire [ 3: 0] m_axi_arcache, 22 | output wire [ 2: 0] m_axi_arprot, 23 | output wire m_axi_arvalid, 24 | input wire m_axi_arready, 25 | input wire [ 3: 0] m_axi_rid, 26 | input wire [31: 0] m_axi_rdata, 27 | input wire [ 1: 0] m_axi_rresp, 28 | input wire m_axi_rlast, 29 | input wire m_axi_rvalid, 30 | output wire m_axi_rready, 31 | output wire [ 3: 0] m_axi_awid, 32 | output wire [31: 0] m_axi_awaddr, 33 | output wire [ 3: 0] m_axi_awlen, 34 | output wire [ 2: 0] m_axi_awsize, 35 | output wire [ 1: 0] m_axi_awburst, 36 | output wire [ 1: 0] m_axi_awlock, 37 | output wire [ 3: 0] m_axi_awcache, 38 | output wire [ 2: 0] m_axi_awprot, 39 | output wire m_axi_awvalid, 40 | input wire m_axi_awready, 41 | output wire [ 3: 0] m_axi_wid, 42 | output wire [31: 0] m_axi_wdata, 43 | output wire [ 3: 0] m_axi_wstrb, 44 | output wire m_axi_wlast, 45 | output wire m_axi_wvalid, 46 | input wire m_axi_wready, 47 | input wire [ 3: 0] m_axi_bid, 48 | input wire [ 1: 0] m_axi_bresp, 49 | input wire m_axi_bvalid, 50 | output wire m_axi_bready 51 | ); 52 | 53 | reg rstn; 54 | always @(posedge cpu_clk) 55 | rstn <= cpu_rstn; 56 | 57 | wire inst_en; 58 | wire [`AddrBus] inst_addr; 59 | wire [`DataBus] inst_rdata; 60 | wire inst_streq; 61 | wire inst_stall; 62 | wire inst_cached; 63 | 64 | wire data_en; 65 | wire [`AddrBus] data_addr; 66 | wire [`DataBus] data_rdata; 67 | wire [`ByteWEn] data_wen; 68 | wire [`DataBus] data_wdata; 69 | wire [`AXISize] data_size; 70 | wire data_streq; 71 | wire data_stall; 72 | wire data_cached; 73 | 74 | wire [`CacheOp] cacheop; 75 | wire [`DataBus] cop_tag; 76 | 77 | wire [ 3: 0] ibus_arid; 78 | wire [31: 0] ibus_araddr; 79 | wire [ 3: 0] ibus_arlen; 80 | wire [ 2: 0] ibus_arsize; 81 | wire [ 1: 0] ibus_arburst; 82 | wire [ 1: 0] ibus_arlock; 83 | wire [ 3: 0] ibus_arcache; 84 | wire [ 2: 0] ibus_arprot; 85 | wire ibus_arvalid; 86 | wire ibus_arready; 87 | wire [ 3: 0] ibus_rid; 88 | wire [31: 0] ibus_rdata; 89 | wire [ 1: 0] ibus_rresp; 90 | wire ibus_rlast; 91 | wire ibus_rvalid; 92 | wire ibus_rready; 93 | wire [ 3: 0] ibus_awid; 94 | wire [31: 0] ibus_awaddr; 95 | wire [ 3: 0] ibus_awlen; 96 | wire [ 2: 0] ibus_awsize; 97 | wire [ 1: 0] ibus_awburst; 98 | wire [ 1: 0] ibus_awlock; 99 | wire [ 3: 0] ibus_awcache; 100 | wire [ 2: 0] ibus_awprot; 101 | wire ibus_awvalid; 102 | wire ibus_awready; 103 | wire [ 3: 0] ibus_wid; 104 | wire [31: 0] ibus_wdata; 105 | wire [ 3: 0] ibus_wstrb; 106 | wire ibus_wlast; 107 | wire ibus_wvalid; 108 | wire ibus_wready; 109 | wire [ 3: 0] ibus_bid; 110 | wire [ 1: 0] ibus_bresp; 111 | wire ibus_bvalid; 112 | wire ibus_bready; 113 | 114 | wire [ 3: 0] dbus_arid; 115 | wire [31: 0] dbus_araddr; 116 | wire [ 3: 0] dbus_arlen; 117 | wire [ 2: 0] dbus_arsize; 118 | wire [ 1: 0] dbus_arburst; 119 | wire [ 1: 0] dbus_arlock; 120 | wire [ 3: 0] dbus_arcache; 121 | wire [ 2: 0] dbus_arprot; 122 | wire dbus_arvalid; 123 | wire dbus_arready; 124 | wire [ 3: 0] dbus_rid; 125 | wire [31: 0] dbus_rdata; 126 | wire [ 1: 0] dbus_rresp; 127 | wire dbus_rlast; 128 | wire dbus_rvalid; 129 | wire dbus_rready; 130 | wire [ 3: 0] dbus_awid; 131 | wire [31: 0] dbus_awaddr; 132 | wire [ 3: 0] dbus_awlen; 133 | wire [ 2: 0] dbus_awsize; 134 | wire [ 1: 0] dbus_awburst; 135 | wire [ 1: 0] dbus_awlock; 136 | wire [ 3: 0] dbus_awcache; 137 | wire [ 2: 0] dbus_awprot; 138 | wire dbus_awvalid; 139 | wire dbus_awready; 140 | wire [ 3: 0] dbus_wid; 141 | wire [31: 0] dbus_wdata; 142 | wire [ 3: 0] dbus_wstrb; 143 | wire dbus_wlast; 144 | wire dbus_wvalid; 145 | wire dbus_wready; 146 | wire [ 3: 0] dbus_bid; 147 | wire [ 1: 0] dbus_bresp; 148 | wire dbus_bvalid; 149 | wire dbus_bready; 150 | 151 | MangoMIPS_Core_Top mips_core ( 152 | .clk ( cpu_clk ), 153 | .rst ( ~rstn ), 154 | .intr ( intr ), 155 | 156 | .ibus_en ( inst_en ), 157 | .ibus_addr ( inst_addr ), 158 | .ibus_rdata ( inst_rdata ), 159 | .ibus_streq ( inst_streq ), 160 | .ibus_stall ( inst_stall ), 161 | .ibus_cached ( inst_cached ), 162 | 163 | .dbus_en ( data_en ), 164 | .dbus_wen ( data_wen ), 165 | .dbus_addr ( data_addr ), 166 | .dbus_wdata ( data_wdata ), 167 | .dbus_rdata ( data_rdata ), 168 | .dbus_size ( data_size ), 169 | .dbus_streq ( data_streq ), 170 | .dbus_stall ( data_stall ), 171 | .dbus_cached ( data_cached ), 172 | 173 | .cacheop ( cacheop ), 174 | .cop_tag ( cop_tag ) 175 | ); 176 | 177 | ICache_Controller icache_ctrl ( 178 | .aclk ( cpu_clk ), 179 | .aresetn ( rstn ), 180 | .arid ( ibus_arid ), 181 | .araddr ( ibus_araddr ), 182 | .arlen ( ibus_arlen ), 183 | .arsize ( ibus_arsize ), 184 | .arburst ( ibus_arburst ), 185 | .arlock ( ibus_arlock ), 186 | .arcache ( ibus_arcache ), 187 | .arprot ( ibus_arprot ), 188 | .arvalid ( ibus_arvalid ), 189 | .arready ( ibus_arready ), 190 | .rid ( ibus_rid ), 191 | .rdata ( ibus_rdata ), 192 | .rresp ( ibus_rresp ), 193 | .rlast ( ibus_rlast ), 194 | .rvalid ( ibus_rvalid ), 195 | .rready ( ibus_rready ), 196 | .awid ( ibus_awid ), 197 | .awaddr ( ibus_awaddr ), 198 | .awlen ( ibus_awlen ), 199 | .awsize ( ibus_awsize ), 200 | .awburst ( ibus_awburst ), 201 | .awlock ( ibus_awlock ), 202 | .awcache ( ibus_awcache ), 203 | .awprot ( ibus_awprot ), 204 | .awvalid ( ibus_awvalid ), 205 | .awready ( ibus_awready ), 206 | .wid ( ibus_wid ), 207 | .wdata ( ibus_wdata ), 208 | .wstrb ( ibus_wstrb ), 209 | .wlast ( ibus_wlast ), 210 | .wvalid ( ibus_wvalid ), 211 | .wready ( ibus_wready ), 212 | .bid ( ibus_bid ), 213 | .bresp ( ibus_bresp ), 214 | .bvalid ( ibus_bvalid ), 215 | .bready ( ibus_bready ), 216 | 217 | .bus_en ( inst_en ), 218 | .bus_wen ( `WrDisable ), 219 | .bus_addr ( inst_addr ), 220 | .bus_rdata ( inst_rdata ), 221 | .bus_wdata ( `ZeroWord ), 222 | .bus_size ( `ASize_Word ), 223 | .bus_streq ( inst_streq ), 224 | .bus_stall ( inst_stall ), 225 | .bus_cached ( inst_cached ), 226 | 227 | .cacheop ( cacheop ), 228 | .cop_en ( data_en ), 229 | .cop_addr ( data_addr ), 230 | .cop_itag ( cop_tag ) 231 | ); 232 | 233 | DCache_Controller dcache_ctrl ( 234 | .aclk ( cpu_clk ), 235 | .aresetn ( rstn ), 236 | .arid ( dbus_arid ), 237 | .araddr ( dbus_araddr ), 238 | .arlen ( dbus_arlen ), 239 | .arsize ( dbus_arsize ), 240 | .arburst ( dbus_arburst ), 241 | .arlock ( dbus_arlock ), 242 | .arcache ( dbus_arcache ), 243 | .arprot ( dbus_arprot ), 244 | .arvalid ( dbus_arvalid ), 245 | .arready ( dbus_arready ), 246 | .rid ( dbus_rid ), 247 | .rdata ( dbus_rdata ), 248 | .rresp ( dbus_rresp ), 249 | .rlast ( dbus_rlast ), 250 | .rvalid ( dbus_rvalid ), 251 | .rready ( dbus_rready ), 252 | .awid ( dbus_awid ), 253 | .awaddr ( dbus_awaddr ), 254 | .awlen ( dbus_awlen ), 255 | .awsize ( dbus_awsize ), 256 | .awburst ( dbus_awburst ), 257 | .awlock ( dbus_awlock ), 258 | .awcache ( dbus_awcache ), 259 | .awprot ( dbus_awprot ), 260 | .awvalid ( dbus_awvalid ), 261 | .awready ( dbus_awready ), 262 | .wid ( dbus_wid ), 263 | .wdata ( dbus_wdata ), 264 | .wstrb ( dbus_wstrb ), 265 | .wlast ( dbus_wlast ), 266 | .wvalid ( dbus_wvalid ), 267 | .wready ( dbus_wready ), 268 | .bid ( dbus_bid ), 269 | .bresp ( dbus_bresp ), 270 | .bvalid ( dbus_bvalid ), 271 | .bready ( dbus_bready ), 272 | 273 | .bus_en ( data_en ), 274 | .bus_wen ( data_wen ), 275 | .bus_addr ( data_addr ), 276 | .bus_rdata ( data_rdata ), 277 | .bus_wdata ( data_wdata ), 278 | .bus_size ( data_size ), 279 | .bus_streq ( data_streq ), 280 | .bus_stall ( data_stall ), 281 | .bus_cached ( data_cached ), 282 | 283 | .cacheop ( cacheop ), 284 | .cop_dtag ( cop_tag ) 285 | ); 286 | 287 | Bus_Interface biu ( 288 | .aclk ( cpu_clk ), 289 | .aresetn ( rstn ), 290 | 291 | .s_axi_arid ( {ibus_arid ,dbus_arid } ), 292 | .s_axi_araddr ( {ibus_araddr ,dbus_araddr } ), 293 | .s_axi_arlen ( {ibus_arlen ,dbus_arlen } ), 294 | .s_axi_arsize ( {ibus_arsize ,dbus_arsize } ), 295 | .s_axi_arburst ( {ibus_arburst,dbus_arburst} ), 296 | .s_axi_arlock ( {ibus_arlock ,dbus_arlock } ), 297 | .s_axi_arcache ( {ibus_arcache,dbus_arcache} ), 298 | .s_axi_arprot ( {ibus_arprot ,dbus_arprot } ), 299 | .s_axi_arqos ( 0 ), 300 | .s_axi_arvalid ( {ibus_arvalid,dbus_arvalid} ), 301 | .s_axi_arready ( {ibus_arready,dbus_arready} ), 302 | .s_axi_rid ( {ibus_rid ,dbus_rid } ), 303 | .s_axi_rdata ( {ibus_rdata ,dbus_rdata } ), 304 | .s_axi_rresp ( {ibus_rresp ,dbus_rresp } ), 305 | .s_axi_rlast ( {ibus_rlast ,dbus_rlast } ), 306 | .s_axi_rvalid ( {ibus_rvalid ,dbus_rvalid } ), 307 | .s_axi_rready ( {ibus_rready ,dbus_rready } ), 308 | .s_axi_awid ( {ibus_awid ,dbus_awid } ), 309 | .s_axi_awaddr ( {ibus_awaddr ,dbus_awaddr } ), 310 | .s_axi_awlen ( {ibus_awlen ,dbus_awlen } ), 311 | .s_axi_awsize ( {ibus_awsize ,dbus_awsize } ), 312 | .s_axi_awburst ( {ibus_awburst,dbus_awburst} ), 313 | .s_axi_awlock ( {ibus_awlock ,dbus_awlock } ), 314 | .s_axi_awcache ( {ibus_awcache,dbus_awcache} ), 315 | .s_axi_awprot ( {ibus_awprot ,dbus_awprot } ), 316 | .s_axi_awqos ( 0 ), 317 | .s_axi_awvalid ( {ibus_awvalid,dbus_awvalid} ), 318 | .s_axi_awready ( {ibus_awready,dbus_awready} ), 319 | .s_axi_wid ( {ibus_wid ,dbus_wid } ), 320 | .s_axi_wdata ( {ibus_wdata ,dbus_wdata } ), 321 | .s_axi_wstrb ( {ibus_wstrb ,dbus_wstrb } ), 322 | .s_axi_wlast ( {ibus_wlast ,dbus_wlast } ), 323 | .s_axi_wvalid ( {ibus_wvalid ,dbus_wvalid } ), 324 | .s_axi_wready ( {ibus_wready ,dbus_wready } ), 325 | .s_axi_bid ( {ibus_bid ,dbus_bid } ), 326 | .s_axi_bresp ( {ibus_bresp ,dbus_bresp } ), 327 | .s_axi_bvalid ( {ibus_bvalid ,dbus_bvalid } ), 328 | .s_axi_bready ( {ibus_bready ,dbus_bready } ), 329 | 330 | .m_axi_arid ( m_axi_arid ), 331 | .m_axi_araddr ( m_axi_araddr ), 332 | .m_axi_arlen ( m_axi_arlen[3:0] ), 333 | .m_axi_arsize ( m_axi_arsize ), 334 | .m_axi_arburst ( m_axi_arburst ), 335 | .m_axi_arlock ( m_axi_arlock ), 336 | .m_axi_arcache ( m_axi_arcache ), 337 | .m_axi_arprot ( m_axi_arprot ), 338 | .m_axi_arqos ( ), 339 | .m_axi_arvalid ( m_axi_arvalid ), 340 | .m_axi_arready ( m_axi_arready ), 341 | .m_axi_rid ( m_axi_rid ), 342 | .m_axi_rdata ( m_axi_rdata ), 343 | .m_axi_rresp ( m_axi_rresp ), 344 | .m_axi_rlast ( m_axi_rlast ), 345 | .m_axi_rvalid ( m_axi_rvalid ), 346 | .m_axi_rready ( m_axi_rready ), 347 | .m_axi_awid ( m_axi_awid ), 348 | .m_axi_awaddr ( m_axi_awaddr ), 349 | .m_axi_awlen ( m_axi_awlen[3:0] ), 350 | .m_axi_awsize ( m_axi_awsize ), 351 | .m_axi_awburst ( m_axi_awburst ), 352 | .m_axi_awlock ( m_axi_awlock ), 353 | .m_axi_awcache ( m_axi_awcache ), 354 | .m_axi_awprot ( m_axi_awprot ), 355 | .m_axi_awqos ( ), 356 | .m_axi_awvalid ( m_axi_awvalid ), 357 | .m_axi_awready ( m_axi_awready ), 358 | .m_axi_wid ( m_axi_wid ), 359 | .m_axi_wdata ( m_axi_wdata ), 360 | .m_axi_wstrb ( m_axi_wstrb ), 361 | .m_axi_wlast ( m_axi_wlast ), 362 | .m_axi_wvalid ( m_axi_wvalid ), 363 | .m_axi_wready ( m_axi_wready ), 364 | .m_axi_bid ( m_axi_bid ), 365 | .m_axi_bresp ( m_axi_bresp ), 366 | .m_axi_bvalid ( m_axi_bvalid ), 367 | .m_axi_bready ( m_axi_bready ) 368 | ); 369 | 370 | endmodule -------------------------------------------------------------------------------- /Src/Cache/DCache_Controller.v: -------------------------------------------------------------------------------- 1 | /********************MangoMIPS32******************* 2 | Filename: DCache_Controller.v 3 | Author: RickyTino 4 | Version: v1.1.3 5 | **************************************************/ 6 | `include "../Config.v" 7 | `include "../Defines.v" 8 | 9 | module DCache_Controller 10 | ( 11 | input wire aclk, 12 | input wire aresetn, 13 | output reg [ 3 : 0 ] arid, 14 | output reg [ 31 : 0 ] araddr, 15 | output reg [ 3 : 0 ] arlen, 16 | output reg [ 2 : 0 ] arsize, 17 | output wire [ 1 : 0 ] arburst, 18 | output wire [ 1 : 0 ] arlock, 19 | output wire [ 3 : 0 ] arcache, 20 | output wire [ 2 : 0 ] arprot, 21 | output reg arvalid, 22 | input wire arready, 23 | input wire [ 3 : 0 ] rid, 24 | input wire [ 31 : 0 ] rdata, 25 | input wire [ 1 : 0 ] rresp, 26 | input wire rlast, 27 | input wire rvalid, 28 | output wire rready, 29 | output wire [ 3 : 0 ] awid, 30 | output reg [ 31 : 0 ] awaddr, 31 | output reg [ 3 : 0 ] awlen, 32 | output reg [ 2 : 0 ] awsize, 33 | output wire [ 1 : 0 ] awburst, 34 | output wire [ 1 : 0 ] awlock, 35 | output wire [ 3 : 0 ] awcache, 36 | output wire [ 2 : 0 ] awprot, 37 | output reg awvalid, 38 | input wire awready, 39 | output wire [ 3 : 0 ] wid, 40 | output wire [ 31 : 0 ] wdata, 41 | output reg [ 3 : 0 ] wstrb, 42 | output reg wlast, 43 | output reg wvalid, 44 | input wire wready, 45 | input wire [ 3 : 0 ] bid, 46 | input wire [ 1 : 0 ] bresp, 47 | input wire bvalid, 48 | output wire bready, 49 | 50 | input wire bus_en, 51 | input wire [`ByteWEn] bus_wen, 52 | input wire [`AddrBus] bus_addr, 53 | output wire [`DataBus] bus_rdata, 54 | input wire [`DataBus] bus_wdata, 55 | input wire [`AXISize] bus_size, 56 | output wire bus_streq, 57 | input wire bus_stall, 58 | input wire bus_cached, 59 | 60 | input wire [`CacheOp] cacheop, 61 | input wire [`DataBus] cop_dtag 62 | ); 63 | 64 | assign arburst = 2'b01; 65 | assign arlock = 2'b0; 66 | assign arcache = 4'b0; 67 | assign arprot = 3'b0; 68 | assign rready = 1'b1; 69 | assign awid = 4'b0; 70 | assign awburst = 2'b01; 71 | assign awlock = 2'b0; 72 | assign awcache = 4'b0; 73 | assign awprot = 3'b0; 74 | assign wid = 4'b0; 75 | assign bready = 1'b1; 76 | 77 | wire refs = bus_wen != `WrDisable; 78 | wire cop_nop = cacheop[0] || cacheop == `COP_NOP; // See Cache Op definition 79 | wire rreq = bus_en & !refs; 80 | wire wreq = bus_en & refs; 81 | 82 | // Sync Reset 83 | reg ca_rstn; 84 | always @(posedge aclk) ca_rstn <= aresetn; 85 | 86 | // Cached Channel 87 | reg ca_enb; 88 | reg [`ByteWEn] ca_wea, ca_web; 89 | reg [`D_ramad] ca_ada, ca_adb; 90 | reg [`DataBus] ca_dina, ca_dinb; 91 | wire [`DataBus] ca_dout; 92 | 93 | DCache_Ram dcache_ram ( 94 | .clk (aclk ), 95 | .enb (ca_enb ), 96 | .wea (ca_wea ), 97 | .web (ca_web ), 98 | .ada (ca_ada ), 99 | .adb (ca_adb ), 100 | .dina (ca_dina ), 101 | .dinb (ca_dinb ), 102 | .dout (ca_dout ) 103 | ); 104 | 105 | reg [`D_ptag] ca_ptag [`D_lnNum]; 106 | reg ca_valid [`D_lnNum]; 107 | reg ca_dirty [`D_lnNum]; 108 | 109 | wire [`D_idx ] ad_idx = bus_addr[`D_addr_idx ]; 110 | wire [`D_ptag] ad_ptag = bus_addr[`D_addr_ptag]; 111 | wire [`D_ptag] ln_ptag = ca_ptag [ad_idx]; 112 | wire ln_valid = ca_valid[ad_idx]; 113 | wire ln_dirty = ca_dirty[ad_idx]; 114 | wire ln_hit = (ln_ptag ^ ad_ptag) == 0 && ln_valid; 115 | wire ln_wb = !ln_hit && ln_valid && ln_dirty; 116 | 117 | // Uncached Channel 118 | reg [`Word] uc_data; 119 | reg [`Word] uc_addr; 120 | reg uc_valid; 121 | wire uc_hit = (uc_addr ^ bus_addr) == 0 && uc_valid; 122 | reg uc_wrdy; 123 | 124 | reg rw_streq; 125 | 126 | assign bus_streq = rw_streq || ca_enb; 127 | 128 | 129 | always @(*) begin 130 | rw_streq <= `false; 131 | ca_ada <= bus_addr[`D_addr_ramad]; 132 | ca_dina <= bus_wdata; 133 | ca_wea <= `WrDisable; 134 | 135 | if(bus_en) begin 136 | if(!cop_nop) begin 137 | case (cacheop) 138 | `COP_DIWI: rw_streq <= ln_dirty && ln_valid; 139 | `COP_DHWI: rw_streq <= ln_dirty && ln_hit; 140 | endcase 141 | end 142 | else begin 143 | if(bus_cached) begin 144 | ca_wea <= ln_hit ? bus_wen : `WrDisable; 145 | rw_streq <= !ln_hit; 146 | end 147 | else begin 148 | if(refs) rw_streq <= !uc_wrdy; 149 | else rw_streq <= !uc_hit; 150 | end 151 | end 152 | end 153 | end 154 | 155 | reg [`Word] lk_addr; 156 | reg [`Word] lk_data; 157 | reg [ 3: 0] lk_strb; 158 | reg [ 1: 0] lk_size; 159 | reg lk_cached; 160 | reg [ 3: 0] cnt; 161 | reg [ 3: 0] state; 162 | 163 | wire [`D_idx] lk_idx = lk_addr[`D_addr_idx]; 164 | 165 | parameter S_IDLE = 4'h0; 166 | parameter S_FILLCACHE_PREPARE = 4'h1; 167 | parameter S_FILLCACHE_TRANSFER = 4'h2; 168 | parameter S_FILLCACHE_END = 4'h3; 169 | parameter S_WRITEBACK_PREPARE = 4'h4; 170 | parameter S_WRITEBACK_TRANSFER = 4'h5; 171 | parameter S_WRITEBACK_END = 4'h6; 172 | parameter S_UC_READ_PREPARE = 4'h7; 173 | parameter S_UC_READ_TRANSFER = 4'h8; 174 | parameter S_UC_READ_WAITEND = 4'h9; 175 | parameter S_UC_WRITE_PREPARE = 4'hA; 176 | parameter S_UC_WRITE_TRANSFER = 4'hB; 177 | parameter S_UC_WRITE_RESPONSE = 4'hC; 178 | parameter S_UC_WRITE_WAITEND = 4'hD; 179 | 180 | always @(posedge aclk, negedge ca_rstn) begin 181 | if(!ca_rstn) begin 182 | state <= 0; 183 | cnt <= 0; 184 | 185 | lk_addr <= `ZeroWord; 186 | lk_cached <= `false; 187 | lk_size <= `ASize_Word; 188 | lk_data <= `ZeroWord; 189 | lk_strb <= `WrDisable; 190 | 191 | arid <= 0; 192 | araddr <= 0; 193 | arlen <= 0; 194 | arsize <= 0; 195 | arvalid <= 0; 196 | awaddr <= 0; 197 | awlen <= 0; 198 | awsize <= 0; 199 | awvalid <= 0; 200 | wstrb <= 0; 201 | wlast <= 0; 202 | wvalid <= 0; 203 | 204 | ca_web <= `WrDisable; 205 | ca_adb <= `ZeroWord; 206 | ca_dinb <= `ZeroWord; 207 | ca_enb <= `false; 208 | 209 | uc_data <= `ZeroWord; 210 | uc_addr <= `ZeroWord; 211 | uc_valid <= `false; 212 | uc_wrdy <= `false; 213 | end 214 | else begin 215 | arvalid <= 0; 216 | awvalid <= 0; 217 | wvalid <= 0; 218 | 219 | ca_web <= `WrDisable; 220 | ca_adb <= `ZeroWord; 221 | ca_dinb <= `ZeroWord; 222 | 223 | uc_valid <= `false; 224 | uc_wrdy <= `false; 225 | 226 | case (state) 227 | S_IDLE: 228 | if(bus_en) begin 229 | if(!cop_nop) begin 230 | case (cacheop) 231 | `COP_DIWI: begin 232 | // ca_valid[ad_idx] <= `false; 233 | if(ln_valid && ln_dirty) begin 234 | lk_addr <= {ln_ptag, ad_idx, 6'b0}; 235 | lk_cached <= `true; 236 | cnt <= 0; 237 | state <= S_WRITEBACK_PREPARE; 238 | ca_enb <= `true; 239 | end 240 | end 241 | 242 | // `COP_DIST: begin 243 | // ca_ptag [ad_idx] <= cop_dtag[`DTag_Tag]; 244 | // ca_valid[ad_idx] <= cop_dtag[`DTag_Vld]; 245 | // ca_dirty[ad_idx] <= cop_dtag[`DTag_Drt]; 246 | // end 247 | 248 | // `COP_DHI: begin 249 | // if(ln_hit) ca_valid[ad_idx] <= `false; 250 | // end 251 | 252 | `COP_DHWI: begin 253 | // if(ln_hit) ca_valid[ad_idx] <= `false; 254 | if(ln_hit && ln_dirty) begin 255 | lk_addr <= {ln_ptag, ad_idx, 6'b0}; 256 | lk_cached <= `true; 257 | cnt <= 0; 258 | state <= S_WRITEBACK_PREPARE; 259 | ca_enb <= `true; 260 | end 261 | end 262 | endcase 263 | end 264 | else begin 265 | if(bus_cached) begin 266 | // if(wreq && ln_hit) ca_dirty[ad_idx] <= `true; 267 | if(ln_wb) begin 268 | lk_addr <= {ln_ptag, ad_idx, 6'b0}; 269 | lk_cached <= `true; 270 | cnt <= 0; 271 | state <= S_WRITEBACK_PREPARE; 272 | ca_enb <= `true; 273 | end 274 | else if(!ln_hit) begin 275 | lk_addr <= {ad_ptag, ad_idx, 6'b0}; 276 | lk_cached <= `true; 277 | cnt <= 0; 278 | state <= S_FILLCACHE_PREPARE; 279 | // ca_ptag [ad_idx] <= bus_addr[`D_addr_ptag]; 280 | // ca_valid[ad_idx] <= `false; 281 | ca_enb <= `true; 282 | end 283 | end 284 | else begin //if uncached 285 | if(!refs && !uc_hit) begin 286 | lk_addr <= bus_addr; 287 | lk_size <= bus_size; 288 | lk_cached <= `false; 289 | state <= S_UC_READ_PREPARE; 290 | end 291 | else if(refs && !uc_wrdy) begin 292 | lk_addr <= bus_addr; 293 | lk_data <= bus_wdata; 294 | lk_strb <= bus_wen; 295 | lk_size <= bus_size; 296 | lk_cached <= `false; 297 | state <= S_UC_WRITE_PREPARE; 298 | end 299 | end 300 | end 301 | end 302 | 303 | //Cache Fill States 304 | S_FILLCACHE_PREPARE: 305 | if(arvalid && arready) state <= S_FILLCACHE_TRANSFER; 306 | else begin 307 | arid <= 4'b0101; 308 | araddr <= lk_addr; 309 | arlen <= 4'hF; 310 | arsize <= 3'b010; 311 | arvalid <= `true; 312 | end 313 | 314 | S_FILLCACHE_TRANSFER: 315 | if(rvalid) begin 316 | ca_web <= 4'hF; 317 | ca_adb <= {lk_idx, cnt}; 318 | ca_dinb <= rdata; 319 | cnt <= cnt + 1; 320 | if(rlast) state <= S_FILLCACHE_END; 321 | end 322 | 323 | S_FILLCACHE_END: begin 324 | // ca_valid[lk_idx] <= `true; 325 | ca_enb <= `false; 326 | state <= S_IDLE; 327 | end 328 | 329 | //Cache Writeback States 330 | S_WRITEBACK_PREPARE: 331 | if(awvalid && awready) state <= S_WRITEBACK_TRANSFER; 332 | else begin 333 | awaddr <= lk_addr; 334 | awlen <= 4'hF; 335 | awsize <= 3'b010; 336 | awvalid <= `true; 337 | end 338 | 339 | S_WRITEBACK_TRANSFER: 340 | if(wvalid && wready) begin 341 | if(cnt == 4'hF) state <= S_WRITEBACK_END; 342 | else cnt <= cnt + 1; 343 | end 344 | else begin 345 | ca_adb <= {lk_idx, cnt}; 346 | wstrb <= 4'hF; 347 | wvalid <= `true; 348 | wlast <= cnt == 4'hF; 349 | end 350 | 351 | S_WRITEBACK_END: 352 | if(bvalid) begin 353 | state <= S_IDLE; 354 | // ca_dirty[lk_idx] <= `false; 355 | ca_enb <= `false; 356 | end 357 | 358 | //Uncached Read States 359 | S_UC_READ_PREPARE: 360 | if(arvalid && arready) state <= S_UC_READ_TRANSFER; 361 | else begin 362 | arid <= 4'b0100; 363 | araddr <= lk_addr; 364 | arlen <= 4'h0; 365 | arsize <= {1'b0, lk_size}; 366 | arvalid <= `true; 367 | end 368 | 369 | S_UC_READ_TRANSFER: 370 | if(rvalid) begin 371 | uc_data <= rdata; 372 | uc_addr <= lk_addr; 373 | if(rlast) begin 374 | uc_valid <= `true; 375 | state <= S_UC_READ_WAITEND; 376 | end 377 | end 378 | 379 | S_UC_READ_WAITEND: 380 | if((bus_stall ^ rw_streq) == 0) begin 381 | state <= S_IDLE; 382 | uc_valid <= `false; 383 | end 384 | 385 | //Uncached Write States 386 | S_UC_WRITE_PREPARE: 387 | if(awvalid && awready) state <= S_UC_WRITE_TRANSFER; 388 | else begin 389 | awaddr <= lk_addr; 390 | awlen <= 4'h0; 391 | awsize <= {1'b0, lk_size}; 392 | awvalid <= `true; 393 | end 394 | 395 | S_UC_WRITE_TRANSFER: 396 | if(wvalid && wready) state <= S_UC_WRITE_RESPONSE; 397 | else begin 398 | wstrb <= lk_strb; 399 | wvalid <= `true; 400 | wlast <= `true; 401 | end 402 | 403 | S_UC_WRITE_RESPONSE: 404 | if(bvalid) begin 405 | state <= S_UC_WRITE_WAITEND; 406 | uc_wrdy <= `true; 407 | end 408 | 409 | S_UC_WRITE_WAITEND: 410 | if((bus_stall ^ rw_streq) == 0) begin 411 | state <= S_IDLE; 412 | uc_wrdy <= `false; 413 | end 414 | endcase 415 | end 416 | end 417 | 418 | 419 | integer i; 420 | initial begin 421 | for(i = 0; i < `D_lineN; i = i + 1) begin 422 | ca_ptag [i] <= 0; 423 | ca_valid[i] <= `false; 424 | ca_dirty[i] <= `false; 425 | end 426 | end 427 | 428 | always @(posedge aclk) begin 429 | if(!ca_rstn) begin 430 | for(i = 0; i < `D_lineN; i = i + 1) begin 431 | ca_valid[i] <= `false; 432 | ca_dirty[i] <= `false; 433 | end 434 | end 435 | else begin 436 | case (state) 437 | S_IDLE: 438 | if(bus_en) begin 439 | if(!cop_nop) begin 440 | case (cacheop) 441 | `COP_DIWI: ca_valid[ad_idx] <= `false; 442 | 443 | `COP_DIST: begin 444 | ca_ptag [ad_idx] <= cop_dtag[`DTag_Tag]; 445 | ca_valid[ad_idx] <= cop_dtag[`DTag_Vld]; 446 | ca_dirty[ad_idx] <= cop_dtag[`DTag_Drt]; 447 | end 448 | 449 | `COP_DHI, 450 | `COP_DHWI: if(ln_hit) ca_valid[ad_idx] <= `false; 451 | endcase 452 | end 453 | else if(bus_cached) begin 454 | if(wreq && ln_hit) ca_dirty[ad_idx] <= `true; 455 | if(!ln_wb && !ln_hit) begin 456 | ca_ptag [ad_idx] <= bus_addr[`D_addr_ptag]; 457 | ca_valid[ad_idx] <= `false; 458 | end 459 | end 460 | end 461 | 462 | S_FILLCACHE_END: ca_valid[lk_idx] <= `true; 463 | 464 | S_WRITEBACK_END: 465 | if(bvalid) ca_dirty[lk_idx] <= `false; 466 | endcase 467 | end 468 | end 469 | 470 | assign bus_rdata = bus_cached ? ca_dout : uc_data; 471 | assign wdata = lk_cached ? ca_dout : lk_data; 472 | 473 | endmodule -------------------------------------------------------------------------------- /Src/Core/CP0.v: -------------------------------------------------------------------------------- 1 | /********************MangoMIPS32******************* 2 | Filename: CP0.v 3 | Author: RickyTino 4 | Version: v1.1.3 5 | **************************************************/ 6 | `include "../Config.v" 7 | `include "../Defines.v" 8 | 9 | module CP0 10 | ( 11 | input wire clk, 12 | input wire rst, 13 | input wire [`HardInt] intr, 14 | 15 | input wire [`CP0Addr] addr, 16 | input wire wen, 17 | output reg [`DataBus] rdata, 18 | input wire [`DataBus] wdata, 19 | 20 | input wire exc_flag, 21 | input wire [`ExcType] exc_type, 22 | input wire [`AddrBus] pc, 23 | input wire [`AddrBus] exc_baddr, 24 | input wire [`CPNum ] exc_cpnum, 25 | input wire exc_save, 26 | input wire inslot, 27 | 28 | input wire tlb_idxwen, 29 | input wire tlb_itmwen, 30 | input wire [`DataBus] tlb_index, 31 | input wire [`TLB_Itm] tlb_item, 32 | 33 | output wire [`DataBus] Index_o, 34 | output wire [`DataBus] Random_o, 35 | output wire [`DataBus] EntryLo0_o, 36 | output wire [`DataBus] EntryLo1_o, 37 | output wire [`DataBus] PageMask_o, 38 | output wire [`DataBus] EntryHi_o, 39 | output wire [`DataBus] Status_o, 40 | output wire [`DataBus] Cause_o, 41 | output wire [`DataBus] EPC_o, 42 | output wire [`DataBus] Config_o, 43 | output wire [`DataBus] TagLo_o, 44 | output wire [`DataBus] ErrorEPC_o, 45 | 46 | output wire usermode, 47 | output wire exc_intr 48 | ); 49 | 50 | reg [`Word] BadVAddr; 51 | 52 | reg [`Word] EPC; 53 | // reg [`Word] ITagHi; 54 | // reg [`Word] DTagHi; 55 | reg [`Word] TagLo; 56 | reg [`Word] TagHi; 57 | reg [`Word] ErrorEPC; 58 | 59 | // Count & Compare 60 | reg [33: 0] Count__; 61 | reg [`Word] Compare; 62 | wire [`Word] Count = Count__[32:1]; 63 | 64 | reg timer_intr; 65 | wire timer_eq = (Count ^ Compare) == `ZeroWord; 66 | wire timer_on = Compare != `ZeroWord && timer_eq; 67 | 68 | // Status 69 | reg Status_CU0; 70 | reg Status_BEV; 71 | reg [ 7: 0] Status_IM; 72 | reg Status_UM; 73 | reg Status_ERL; 74 | reg Status_EXL; 75 | reg Status_IE; 76 | wire [`Word] Status = { 77 | 3'b0, 78 | Status_CU0, // 28 79 | 5'b0, 80 | Status_BEV, // 22 81 | 6'b0, 82 | Status_IM, // 15:8 83 | 3'b0, 84 | Status_UM, // 4 85 | 1'b0, 86 | Status_ERL, // 2 87 | Status_EXL, // 1 88 | Status_IE // 0 89 | }; 90 | 91 | // Cause 92 | reg Cause_BD; 93 | reg [ 1: 0] Cause_CE; 94 | reg Cause_IV; 95 | reg [ 7: 0] Cause_IP; 96 | reg [ 4: 0] Cause_ExcCode; 97 | wire [`Word] Cause = { 98 | Cause_BD, // 31 R 99 | 1'b0, 100 | Cause_CE, // 29:28 R 101 | 4'b0, 102 | `ifdef Disable_Cause_IV 103 | 1'b0, 104 | `else 105 | Cause_IV, // 23 RW 106 | `endif 107 | 7'b0, 108 | Cause_IP, // 15:8 R[15:10] RW[9:8] 109 | 1'b0, 110 | Cause_ExcCode, // 6:2 R 111 | 2'b0 112 | }; 113 | 114 | // PrId 115 | wire [`Word] PrId = 116 | { 117 | 8'h00, // Company Options 118 | 8'h01, // Company ID 119 | 8'h80, // Processor ID 120 | 8'h00 // Revision 121 | }; 122 | // 32'h00004220; //LS232 123 | 124 | // Config 125 | reg [ 2: 0] Config_K23; 126 | reg [ 2: 0] Config_KU; 127 | reg [ 2: 0] Config_K0; 128 | wire [`Word] Config = { 129 | 1'b1, // 31 Config1 130 | `ifdef Fixed_Mapping_MMU 131 | Config_K23, // 30:28 132 | Config_KU, // 27:25 133 | `else 134 | 3'b0, // 30:28 135 | 3'b0, // 27:25 136 | `endif 137 | 9'b0, 138 | 1'b0, // 15 BE:Little Endian 139 | 2'b0, // 14:13 AT:MIPS32 140 | 3'b0, // 12:10 AR:Release 1 141 | `ifdef Fixed_Mapping_MMU 142 | 3'b011, // 9: 7 MT:Fixed Mapping 143 | `else 144 | 3'b001, // 9: 7 MT:Standart TLB 145 | `endif 146 | 3'b0, 147 | 1'b0, // 3 VI:0 148 | Config_K0 // 2: 0 149 | }; 150 | 151 | // Config1 152 | `define IS 3'd`ICache_N - 3'd1 153 | `define DS 3'd`DCache_N - 3'd1 154 | wire [`Word] Config1 = { 155 | 1'b0, // 31 Config2 156 | `ifdef Fixed_Mapping_MMU 157 | 6'b0, // 30:25 MMU Size-1 158 | `else 159 | 6'd31, // 30:25 MMU Size-1 160 | `endif 161 | `IS, // 24:22 IS 162 | 3'd5, // 21:19 IL = 5 64B 163 | 3'b0, // 18:16 IA 164 | `DS, // 15:13 DS 165 | 3'd5, // 12:10 DL = 5 64B 166 | 3'b0, // 9: 7 DA 167 | 1'b0, // 6 C2 168 | 1'b0, // 5 MD 169 | 1'b0, // 4 PC 170 | 1'b0, // 3 WR 171 | 1'b0, // 2 CA 172 | 1'b0, // 1 EP 173 | 1'b0 // 0 FP 174 | }; 175 | 176 | // Index 177 | reg Index_P; 178 | reg [`TLB_Idx] Index__; 179 | wire [`Word ] Index; 180 | 181 | assign Index [ 31 ] = Index_P; 182 | assign Index [`Index_0] = 0; 183 | assign Index [`TLB_Idx] = Index__; 184 | 185 | // Random 186 | reg [`TLB_Idx] Random__; 187 | wire [`Word ] Random; 188 | 189 | assign Random [`Random_0] = 0; 190 | assign Random [`TLB_Idx ] = Random__; 191 | 192 | // EntryLo 193 | reg [19: 0] EntryLo0_PFN, EntryLo1_PFN; 194 | reg [ 2: 0] EntryLo0_C, EntryLo1_C; 195 | reg EntryLo0_D, EntryLo1_D; 196 | reg EntryLo0_V, EntryLo1_V; 197 | reg EntryLo0_G, EntryLo1_G; 198 | 199 | wire [`Word ] EntryLo0 = { 200 | 6'b0, 201 | EntryLo0_PFN, // 25: 6 202 | EntryLo0_C, // 5: 3 203 | EntryLo0_D, // 2 204 | EntryLo0_V, // 1 205 | EntryLo0_G // 0 206 | }; 207 | wire [`Word ] EntryLo1 = { 208 | 6'b0, 209 | EntryLo1_PFN, 210 | EntryLo1_C, 211 | EntryLo1_D, 212 | EntryLo1_V, 213 | EntryLo1_G 214 | }; 215 | 216 | // EntryHi 217 | reg [18: 0] EntryHi_VPN2; 218 | reg [ 7: 0] EntryHi_ASID; 219 | wire [`Word] EntryHi = {EntryHi_VPN2, 5'b0, EntryHi_ASID}; 220 | 221 | // Context 222 | reg [ 8: 0] Context_PTEBase; 223 | reg [18: 0] Context_BadVPN2; 224 | wire [`Word] Context = { 225 | Context_PTEBase, 226 | Context_BadVPN2, 227 | 4'b0 228 | }; 229 | 230 | // PageMask 231 | reg [15: 0] PageMask__; 232 | wire [`Word] PageMask = {3'b0, PageMask__, 13'b0}; 233 | 234 | // Wired 235 | reg [`TLB_Idx] Wired__; 236 | wire [`Word ] Wired; 237 | assign Wired [`Wired_0] = 0; 238 | assign Wired [`TLB_Idx] = Wired__; 239 | 240 | // CP0 Operations 241 | wire [`Word] pcm4 = pc - 32'h4; 242 | 243 | 244 | //PageMask write 245 | wire [15: 0] w_mask; 246 | genvar i; 247 | generate 248 | for(i = 0; i < 16; i = i + 2) begin 249 | assign w_mask[i ] = wdata[i + 13]; 250 | assign w_mask[i + 1] = wdata[i + 13]; 251 | end 252 | endgenerate 253 | 254 | always @(posedge clk, posedge rst) begin 255 | if(rst) begin 256 | 257 | Index_P <= 0; 258 | Index__ <= 0; 259 | Random__ <= `Random_Rst; 260 | EntryLo0_PFN <= 0; 261 | EntryLo0_C <= 0; 262 | EntryLo0_D <= 0; 263 | EntryLo0_V <= 0; 264 | EntryLo0_G <= 0; 265 | EntryLo1_PFN <= 0; 266 | EntryLo1_C <= 0; 267 | EntryLo1_D <= 0; 268 | EntryLo1_V <= 0; 269 | EntryLo1_G <= 0; 270 | Context_BadVPN2 <= 0; 271 | Context_PTEBase <= 0; 272 | PageMask__ <= 0; 273 | Wired__ <= 0; 274 | BadVAddr <= 0; 275 | Count__ <= 0; 276 | timer_intr <= 0; 277 | EntryHi_VPN2 <= 0; 278 | EntryHi_ASID <= 0; 279 | Compare <= 0; 280 | Status_CU0 <= 0; 281 | Status_BEV <= 1; 282 | Status_IM <= 0; 283 | Status_UM <= 0; 284 | Status_ERL <= 1; 285 | Status_EXL <= 0; 286 | Status_IE <= 0; 287 | Cause_BD <= 0; 288 | Cause_CE <= 0; 289 | Cause_IV <= 0; 290 | Cause_IP <= 0; 291 | Cause_ExcCode <= 0; 292 | EPC <= 0; 293 | `ifdef Reset_Cacheable 294 | Config_K23 <= 3'd3; 295 | Config_KU <= 3'd3; 296 | Config_K0 <= 3'd3; 297 | `else 298 | Config_K23 <= 3'd2; 299 | Config_KU <= 3'd2; 300 | Config_K0 <= 3'd2; 301 | `endif 302 | TagLo <= 0; 303 | TagHi <= 0; 304 | ErrorEPC <= 32'hBFC00000; 305 | end 306 | else begin 307 | // Count & Compare 308 | Count__ <= Count__ + 33'd1; 309 | if(timer_on) timer_intr <= `true; 310 | 311 | // Random 312 | Random__ <= (Random__ ^ Wired__) == 0 ? `Random_Rst : Random__ - 1; 313 | 314 | // Interrupts 315 | Cause_IP[7:2] <= {intr[5] | timer_intr, intr[4:0]}; 316 | 317 | // Exceptions 318 | if(exc_flag) begin 319 | case (exc_type) 320 | `ExcT_Intr, 321 | `ExcT_CpU, 322 | `ExcT_RI, 323 | `ExcT_Ov, 324 | `ExcT_Trap, 325 | `ExcT_SysC, 326 | `ExcT_Bp, 327 | `ExcT_AdE, 328 | // `ExcT_IBE, 329 | // `ExcT_DBE, 330 | `ExcT_TLBR, 331 | `ExcT_TLBI, 332 | `ExcT_TLBM: begin 333 | if(!Status_EXL) begin 334 | EPC <= inslot ? pcm4 : pc; 335 | Cause_BD <= inslot; 336 | end 337 | Status_EXL <= `One; 338 | end 339 | 340 | `ExcT_ERET: begin 341 | Status_EXL <= `Zero; 342 | end 343 | endcase 344 | 345 | case (exc_type) 346 | `ExcT_AdE: BadVAddr <= exc_baddr; 347 | 348 | `ExcT_TLBR, 349 | `ExcT_TLBI, 350 | `ExcT_TLBM: begin 351 | BadVAddr <= exc_baddr; 352 | Context_BadVPN2 <= exc_baddr[`VPN2]; 353 | EntryHi_VPN2 <= exc_baddr[`VPN2]; 354 | end 355 | 356 | `ExcT_CpU: Cause_CE <= exc_cpnum; 357 | endcase 358 | 359 | // ExcCode 360 | case (exc_type) 361 | `ExcT_Intr: Cause_ExcCode <= `ExcC_Intr; 362 | `ExcT_CpU: Cause_ExcCode <= `ExcC_CpU; 363 | `ExcT_RI: Cause_ExcCode <= `ExcC_RI; 364 | `ExcT_Ov: Cause_ExcCode <= `ExcC_Ov; 365 | `ExcT_Trap: Cause_ExcCode <= `ExcC_Tr; 366 | `ExcT_SysC: Cause_ExcCode <= `ExcC_SysC; 367 | `ExcT_Bp: Cause_ExcCode <= `ExcC_Bp; 368 | `ExcT_AdE: Cause_ExcCode <= exc_save ? `ExcC_AdES : `ExcC_AdEL; 369 | `ExcT_TLBR: Cause_ExcCode <= exc_save ? `ExcC_TLBS : `ExcC_TLBL; 370 | `ExcT_TLBI: Cause_ExcCode <= exc_save ? `ExcC_TLBS : `ExcC_TLBL; 371 | `ExcT_TLBM: Cause_ExcCode <= `ExcC_Mod; 372 | // `ExcT_IBE: Cause_ExcCode <= `ExcC_IBE 373 | // `ExcT_DBE: Cause_ExcCode <= `ExcC_DBE 374 | endcase 375 | 376 | // Displaying 377 | `ifdef Output_Exception_Info 378 | case (exc_type) 379 | `ExcT_Intr: $display("Interrupt Exception"); 380 | `ExcT_CpU: $display("Coprocessor Unusable Exception"); 381 | `ExcT_RI: $display("Reserved Instruction Exception"); 382 | `ExcT_Ov: $display("Integer Overflow Exception"); 383 | `ExcT_Trap: $display("Trap Exception"); 384 | `ExcT_SysC: $display("System Call Exception"); 385 | `ExcT_Bp: $display("Breakpoint Exception"); 386 | `ExcT_AdE: $display("Address Error Exception"); 387 | `ExcT_TLBR: $display("TLB Refill Exception"); 388 | `ExcT_TLBI: $display("TLB Invalid Exception"); 389 | `ExcT_TLBM: $display("TLB Modified Exception"); 390 | // `ExcT_IBE: $display("Bus Error Exception - Inst"); 391 | // `ExcT_DBE: $display("Bus Error Exception - Data"); 392 | endcase 393 | `endif 394 | end 395 | else if(tlb_idxwen) begin 396 | Index_P <= tlb_index[31]; 397 | Index__ <= tlb_index[`TLB_Idx]; 398 | end 399 | else if(tlb_itmwen) begin 400 | PageMask__ <= tlb_item[`TLB_Mask]; 401 | EntryHi_VPN2 <= tlb_item[`TLB_VPN2]; 402 | EntryHi_ASID <= tlb_item[`TLB_ASID]; 403 | EntryLo0_G <= tlb_item[`TLB_G]; 404 | EntryLo0_PFN <= tlb_item[`TLB_PFN0]; 405 | EntryLo0_V <= tlb_item[`TLB_V0]; 406 | EntryLo0_D <= tlb_item[`TLB_D0]; 407 | EntryLo0_C <= tlb_item[`TLB_C0]; 408 | EntryLo1_G <= tlb_item[`TLB_G]; 409 | EntryLo1_PFN <= tlb_item[`TLB_PFN1]; 410 | EntryLo1_V <= tlb_item[`TLB_V1]; 411 | EntryLo1_D <= tlb_item[`TLB_D1]; 412 | EntryLo1_C <= tlb_item[`TLB_C1]; 413 | end 414 | else if(wen) begin 415 | case (addr) 416 | `CP0_Index: begin 417 | Index__ <= wdata[`TLB_Idx]; 418 | end 419 | 420 | `CP0_EntryLo0: begin 421 | EntryLo0_PFN <= wdata[`PFN]; 422 | EntryLo0_C <= wdata[`CAt]; 423 | EntryLo0_D <= wdata[`Drt]; 424 | EntryLo0_V <= wdata[`Vld]; 425 | EntryLo0_G <= wdata[`Glb]; 426 | end 427 | 428 | `CP0_EntryLo1: begin 429 | EntryLo1_PFN <= wdata[`PFN]; 430 | EntryLo1_C <= wdata[`CAt]; 431 | EntryLo1_D <= wdata[`Drt]; 432 | EntryLo1_V <= wdata[`Vld]; 433 | EntryLo1_G <= wdata[`Glb]; 434 | end 435 | 436 | `CP0_Context: begin 437 | Context_PTEBase <= wdata[`PTEBase]; 438 | end 439 | 440 | `CP0_PageMask: begin 441 | PageMask__ <= w_mask; 442 | end 443 | 444 | `CP0_Wired: begin 445 | Wired__ <= wdata[`TLB_Idx]; 446 | Random__ <= `Random_Rst; 447 | end 448 | 449 | `CP0_BadVAddr: begin 450 | BadVAddr <= wdata; 451 | end 452 | 453 | `CP0_Count: begin 454 | Count__ <= {wdata, 1'b0}; 455 | end 456 | 457 | `CP0_EntryHi: begin 458 | EntryHi_VPN2 <= wdata[`VPN2]; 459 | EntryHi_ASID <= wdata[`ASID]; 460 | end 461 | 462 | `CP0_Compare: begin 463 | Compare <= wdata; 464 | timer_intr <= `false; 465 | end 466 | 467 | `CP0_Status: begin 468 | Status_CU0 <= wdata[`CU0]; 469 | Status_BEV <= wdata[`BEV]; 470 | Status_IM <= wdata[`IM ]; 471 | Status_UM <= wdata[`UM ]; 472 | Status_ERL <= wdata[`ERL]; 473 | Status_EXL <= wdata[`EXL]; 474 | Status_IE <= wdata[`IE ]; 475 | end 476 | 477 | `CP0_Cause: begin 478 | Cause_IV <= wdata[`IV ]; 479 | Cause_IP[1:0] <= wdata[`IPS]; 480 | end 481 | 482 | `CP0_EPC: begin 483 | EPC <= wdata; 484 | end 485 | 486 | `CP0_Config: begin 487 | Config_K23 <= wdata[`K23]; 488 | Config_KU <= wdata[`KU ]; 489 | Config_K0 <= wdata[`K0 ]; 490 | end 491 | 492 | `CP0_TagLo: begin 493 | TagLo <= wdata; 494 | end 495 | 496 | `CP0_TagHi: begin 497 | TagHi <= wdata; 498 | end 499 | 500 | `CP0_ErrorEPC: begin 501 | ErrorEPC <= wdata; 502 | end 503 | endcase 504 | end 505 | end 506 | end 507 | 508 | always @(*) begin 509 | case (addr) 510 | `CP0_Index: rdata <= Index; 511 | `CP0_Random: rdata <= Random; 512 | `CP0_EntryLo0: rdata <= EntryLo0; 513 | `CP0_EntryLo1: rdata <= EntryLo1; 514 | `CP0_Context: rdata <= Context; 515 | `CP0_PageMask: rdata <= PageMask; 516 | `CP0_Wired: rdata <= Wired; 517 | `CP0_BadVAddr: rdata <= BadVAddr; 518 | `CP0_Count: rdata <= Count; 519 | `CP0_EntryHi: rdata <= EntryHi; 520 | `CP0_Compare: rdata <= Compare; 521 | `CP0_Status: rdata <= Status; 522 | `CP0_Cause: rdata <= Cause; 523 | `CP0_EPC: rdata <= EPC; 524 | `CP0_PrId: rdata <= PrId; 525 | `CP0_Config: rdata <= Config; 526 | `CP0_Config1: rdata <= Config1; 527 | `CP0_TagLo: rdata <= TagLo; 528 | `CP0_TagHi: rdata <= TagHi; 529 | `CP0_ErrorEPC: rdata <= ErrorEPC; 530 | default: rdata <= `ZeroWord; 531 | endcase 532 | end 533 | 534 | wire no_ex_er = ~Status[`ERL] & ~Status[`EXL]; 535 | assign exc_intr = (Cause[`IP] & Status[`IM]) != 0 && Status[`IE] && no_ex_er; 536 | 537 | `ifdef Disable_User_Mode 538 | assign usermode = `false; 539 | `else 540 | assign usermode = Status[`UM] & no_ex_er; 541 | `endif 542 | 543 | // Output 544 | assign Index_o = Index; 545 | assign Random_o = Random; 546 | assign EntryLo0_o = EntryLo0; 547 | assign EntryLo1_o = EntryLo1; 548 | assign PageMask_o = PageMask; 549 | assign EntryHi_o = EntryHi; 550 | assign Status_o = Status; 551 | assign Cause_o = Cause; 552 | assign EPC_o = EPC; 553 | assign Config_o = Config; 554 | assign TagLo_o = TagLo; 555 | assign ErrorEPC_o = ErrorEPC; 556 | 557 | endmodule -------------------------------------------------------------------------------- /Src/Core/TLBU.v: -------------------------------------------------------------------------------- 1 | /********************MangoMIPS32******************* 2 | Filename: TLBU.v 3 | Author: RickyTino 4 | Version: v1.1.3 5 | **************************************************/ 6 | `include "../Config.v" 7 | `include "../Defines.v" 8 | 9 | `define TLB_Idle 2'd0 10 | `define TLB_Translate 2'd1 11 | `define TLB_Ready 2'd2 12 | 13 | module TLBU 14 | ( 15 | input wire clk, 16 | input wire rst, 17 | 18 | input wire [`TLBOp ] tlb_op, 19 | input wire [`DataBus] Index, 20 | input wire [`DataBus] Random, 21 | input wire [`DataBus] EntryLo0, 22 | input wire [`DataBus] EntryLo1, 23 | input wire [`DataBus] PageMask, 24 | input wire [`DataBus] EntryHi, 25 | 26 | input wire immu_en, 27 | input wire [`AddrBus] immu_vaddr, 28 | output wire immu_rdy, 29 | output reg [`AddrBus] immu_paddr, 30 | output reg immu_cat, 31 | input wire immu_stall, 32 | 33 | input wire dmmu_en, 34 | input wire [`AddrBus] dmmu_vaddr, 35 | input wire dmmu_refs, 36 | output wire dmmu_rdy, 37 | output reg [`AddrBus] dmmu_paddr, 38 | output reg dmmu_cat, 39 | input wire dmmu_stall, 40 | 41 | output reg cp0_idxwen, 42 | output reg [`DataBus] cp0_wIndex, 43 | output reg cp0_tlbwen, 44 | output reg [`TLB_Itm] cp0_tlbitm, 45 | 46 | output reg i_tlbr, 47 | output reg i_tlbi, 48 | output reg d_tlbr, 49 | output reg d_tlbi, 50 | output reg d_tlbm 51 | ); 52 | 53 | `ifdef Fixed_Mapping_MMU 54 | 55 | always @(*) begin 56 | cp0_idxwen <= `false; 57 | cp0_wIndex <= `ZeroWord; 58 | cp0_tlbwen <= `false; 59 | cp0_tlbitm <= 0; 60 | i_tlbi <= `false; 61 | i_tlbr <= `false; 62 | d_tlbi <= `false; 63 | d_tlbr <= `false; 64 | d_tlbm <= `false; 65 | end 66 | 67 | `else 68 | 69 | reg [`TLB_Itm] TLB [`TLB_Sel]; 70 | 71 | reg [ 7: 0] ilk_asid, dlk_asid; 72 | reg ilk_valid, dlk_valid; 73 | 74 | // TLB translation : stage1 75 | reg [`AddrBus] i_vaddr, d_vaddr; 76 | wire [`TLB_Sel] i_hit, d_hit, p_hit; 77 | wire [`TLB_Sel] i_match, d_match, p_match; 78 | wire [`TLB_Sel] i_avlb, d_avlb, p_avlb; 79 | 80 | genvar i; 81 | generate 82 | for (i = 0; i < `TLB_N; i = i + 1) begin 83 | assign i_match[i] = ((TLB[i][`TLB_VPN2] & ~TLB[i][`TLB_VMask]) 84 | ^ (i_vaddr[`VPN2] & ~TLB[i][`TLB_VMask])) == 0; 85 | assign d_match[i] = ((TLB[i][`TLB_VPN2] & ~TLB[i][`TLB_VMask]) 86 | ^ (d_vaddr[`VPN2] & ~TLB[i][`TLB_VMask])) == 0; 87 | assign p_match[i] = ((TLB[i][`TLB_VPN2] & ~TLB[i][`TLB_VMask]) 88 | ^ (EntryHi[`VPN2] & ~TLB[i][`TLB_VMask])) == 0; 89 | assign i_avlb[i] = TLB[i][`TLB_G] || (TLB[i][`TLB_ASID] ^ ilk_asid) == 0; 90 | assign d_avlb[i] = TLB[i][`TLB_G] || (TLB[i][`TLB_ASID] ^ dlk_asid) == 0; 91 | assign p_avlb[i] = TLB[i][`TLB_G] || (TLB[i][`TLB_ASID] ^ EntryHi[`ASID]) == 0; 92 | assign i_hit[i] = i_match[i] && i_avlb[i]; 93 | assign d_hit[i] = d_match[i] && d_avlb[i]; 94 | assign p_hit[i] = p_match[i] && p_avlb[i]; 95 | end 96 | endgenerate 97 | 98 | reg [`TLB_Idx] i_hitidx, d_hitidx, p_hitidx; 99 | wire i_miss, d_miss, p_miss; 100 | 101 | assign i_miss = i_hit == 0; 102 | assign d_miss = d_hit == 0; 103 | assign p_miss = p_hit == 0; 104 | 105 | always @(*) begin 106 | casez (i_hit) 107 | 32'b00000000000000000000000000000001: i_hitidx <= 0; 108 | 32'b0000000000000000000000000000001?: i_hitidx <= 1; 109 | 32'b000000000000000000000000000001??: i_hitidx <= 2; 110 | 32'b00000000000000000000000000001???: i_hitidx <= 3; 111 | 32'b0000000000000000000000000001????: i_hitidx <= 4; 112 | 32'b000000000000000000000000001?????: i_hitidx <= 5; 113 | 32'b00000000000000000000000001??????: i_hitidx <= 6; 114 | 32'b0000000000000000000000001???????: i_hitidx <= 7; 115 | 32'b000000000000000000000001????????: i_hitidx <= 8; 116 | 32'b00000000000000000000001?????????: i_hitidx <= 9; 117 | 32'b0000000000000000000001??????????: i_hitidx <= 10; 118 | 32'b000000000000000000001???????????: i_hitidx <= 11; 119 | 32'b00000000000000000001????????????: i_hitidx <= 12; 120 | 32'b0000000000000000001?????????????: i_hitidx <= 13; 121 | 32'b000000000000000001??????????????: i_hitidx <= 14; 122 | 32'b00000000000000001???????????????: i_hitidx <= 15; 123 | 32'b0000000000000001????????????????: i_hitidx <= 16; 124 | 32'b000000000000001?????????????????: i_hitidx <= 17; 125 | 32'b00000000000001??????????????????: i_hitidx <= 18; 126 | 32'b0000000000001???????????????????: i_hitidx <= 19; 127 | 32'b000000000001????????????????????: i_hitidx <= 20; 128 | 32'b00000000001?????????????????????: i_hitidx <= 21; 129 | 32'b0000000001??????????????????????: i_hitidx <= 22; 130 | 32'b000000001???????????????????????: i_hitidx <= 23; 131 | 32'b00000001????????????????????????: i_hitidx <= 24; 132 | 32'b0000001?????????????????????????: i_hitidx <= 25; 133 | 32'b000001??????????????????????????: i_hitidx <= 26; 134 | 32'b00001???????????????????????????: i_hitidx <= 27; 135 | 32'b0001????????????????????????????: i_hitidx <= 28; 136 | 32'b001?????????????????????????????: i_hitidx <= 29; 137 | 32'b01??????????????????????????????: i_hitidx <= 30; 138 | 32'b1???????????????????????????????: i_hitidx <= 31; 139 | default: i_hitidx <= 0; 140 | endcase 141 | 142 | casez (d_hit) 143 | 32'b00000000000000000000000000000001: d_hitidx <= 0; 144 | 32'b0000000000000000000000000000001?: d_hitidx <= 1; 145 | 32'b000000000000000000000000000001??: d_hitidx <= 2; 146 | 32'b00000000000000000000000000001???: d_hitidx <= 3; 147 | 32'b0000000000000000000000000001????: d_hitidx <= 4; 148 | 32'b000000000000000000000000001?????: d_hitidx <= 5; 149 | 32'b00000000000000000000000001??????: d_hitidx <= 6; 150 | 32'b0000000000000000000000001???????: d_hitidx <= 7; 151 | 32'b000000000000000000000001????????: d_hitidx <= 8; 152 | 32'b00000000000000000000001?????????: d_hitidx <= 9; 153 | 32'b0000000000000000000001??????????: d_hitidx <= 10; 154 | 32'b000000000000000000001???????????: d_hitidx <= 11; 155 | 32'b00000000000000000001????????????: d_hitidx <= 12; 156 | 32'b0000000000000000001?????????????: d_hitidx <= 13; 157 | 32'b000000000000000001??????????????: d_hitidx <= 14; 158 | 32'b00000000000000001???????????????: d_hitidx <= 15; 159 | 32'b0000000000000001????????????????: d_hitidx <= 16; 160 | 32'b000000000000001?????????????????: d_hitidx <= 17; 161 | 32'b00000000000001??????????????????: d_hitidx <= 18; 162 | 32'b0000000000001???????????????????: d_hitidx <= 19; 163 | 32'b000000000001????????????????????: d_hitidx <= 20; 164 | 32'b00000000001?????????????????????: d_hitidx <= 21; 165 | 32'b0000000001??????????????????????: d_hitidx <= 22; 166 | 32'b000000001???????????????????????: d_hitidx <= 23; 167 | 32'b00000001????????????????????????: d_hitidx <= 24; 168 | 32'b0000001?????????????????????????: d_hitidx <= 25; 169 | 32'b000001??????????????????????????: d_hitidx <= 26; 170 | 32'b00001???????????????????????????: d_hitidx <= 27; 171 | 32'b0001????????????????????????????: d_hitidx <= 28; 172 | 32'b001?????????????????????????????: d_hitidx <= 29; 173 | 32'b01??????????????????????????????: d_hitidx <= 30; 174 | 32'b1???????????????????????????????: d_hitidx <= 31; 175 | default: d_hitidx <= 0; 176 | endcase 177 | 178 | casez (p_hit) 179 | 32'b00000000000000000000000000000001: p_hitidx <= 0; 180 | 32'b0000000000000000000000000000001?: p_hitidx <= 1; 181 | 32'b000000000000000000000000000001??: p_hitidx <= 2; 182 | 32'b00000000000000000000000000001???: p_hitidx <= 3; 183 | 32'b0000000000000000000000000001????: p_hitidx <= 4; 184 | 32'b000000000000000000000000001?????: p_hitidx <= 5; 185 | 32'b00000000000000000000000001??????: p_hitidx <= 6; 186 | 32'b0000000000000000000000001???????: p_hitidx <= 7; 187 | 32'b000000000000000000000001????????: p_hitidx <= 8; 188 | 32'b00000000000000000000001?????????: p_hitidx <= 9; 189 | 32'b0000000000000000000001??????????: p_hitidx <= 10; 190 | 32'b000000000000000000001???????????: p_hitidx <= 11; 191 | 32'b00000000000000000001????????????: p_hitidx <= 12; 192 | 32'b0000000000000000001?????????????: p_hitidx <= 13; 193 | 32'b000000000000000001??????????????: p_hitidx <= 14; 194 | 32'b00000000000000001???????????????: p_hitidx <= 15; 195 | 32'b0000000000000001????????????????: p_hitidx <= 16; 196 | 32'b000000000000001?????????????????: p_hitidx <= 17; 197 | 32'b00000000000001??????????????????: p_hitidx <= 18; 198 | 32'b0000000000001???????????????????: p_hitidx <= 19; 199 | 32'b000000000001????????????????????: p_hitidx <= 20; 200 | 32'b00000000001?????????????????????: p_hitidx <= 21; 201 | 32'b0000000001??????????????????????: p_hitidx <= 22; 202 | 32'b000000001???????????????????????: p_hitidx <= 23; 203 | 32'b00000001????????????????????????: p_hitidx <= 24; 204 | 32'b0000001?????????????????????????: p_hitidx <= 25; 205 | 32'b000001??????????????????????????: p_hitidx <= 26; 206 | 32'b00001???????????????????????????: p_hitidx <= 27; 207 | 32'b0001????????????????????????????: p_hitidx <= 28; 208 | 32'b001?????????????????????????????: p_hitidx <= 29; 209 | 32'b01??????????????????????????????: p_hitidx <= 30; 210 | 32'b1???????????????????????????????: p_hitidx <= 31; 211 | default: p_hitidx <= 0; 212 | endcase 213 | end 214 | 215 | // TLB translation : stage2 216 | reg [`TLB_Idx] i_idx, d_idx; 217 | reg [`TLB_Idx] i_eob, d_eob; // EvenOddBit 218 | reg [`PageNum] i_pfn, d_pfn; 219 | reg [`CacheAt] i_cat, d_cat; 220 | reg i_vld, d_vld; 221 | reg i_drt, d_drt; 222 | 223 | reg [`AddrBus] i_paddr, d_paddr; 224 | 225 | wire [`TLB_Itm] i_itm = TLB[i_idx]; 226 | wire [`TLB_Itm] d_itm = TLB[d_idx]; 227 | 228 | always @(*) begin 229 | casez (i_itm[`TLB_Mask]) 230 | 16'b0000000000000000: i_eob <= 12; 231 | 16'b0000000000000011: i_eob <= 14; 232 | 16'b00000000000011??: i_eob <= 16; 233 | 16'b000000000011????: i_eob <= 18; 234 | 16'b0000000011??????: i_eob <= 20; 235 | 16'b00000011????????: i_eob <= 22; 236 | 16'b000011??????????: i_eob <= 24; 237 | 16'b0011????????????: i_eob <= 26; 238 | 16'b11??????????????: i_eob <= 28; 239 | default: i_eob <= 12; // UNDEFINED 240 | endcase 241 | 242 | casez (d_itm[`TLB_Mask]) 243 | 16'b0000000000000000: d_eob <= 12; 244 | 16'b0000000000000011: d_eob <= 14; 245 | 16'b00000000000011??: d_eob <= 16; 246 | 16'b000000000011????: d_eob <= 18; 247 | 16'b0000000011??????: d_eob <= 20; 248 | 16'b00000011????????: d_eob <= 22; 249 | 16'b000011??????????: d_eob <= 24; 250 | 16'b0011????????????: d_eob <= 26; 251 | 16'b11??????????????: d_eob <= 28; 252 | default: d_eob <= 12; // UNDEFINED 253 | endcase 254 | 255 | if(i_vaddr[i_eob]) begin 256 | i_pfn <= i_itm[`TLB_PFN1]; 257 | i_vld <= i_itm[`TLB_V1 ]; 258 | i_cat <= i_itm[`TLB_C1 ]; 259 | i_drt <= i_itm[`TLB_D1 ]; 260 | end 261 | else begin 262 | i_pfn <= i_itm[`TLB_PFN0]; 263 | i_vld <= i_itm[`TLB_V0 ]; 264 | i_cat <= i_itm[`TLB_C0 ]; 265 | i_drt <= i_itm[`TLB_D0 ]; 266 | end 267 | 268 | if(d_vaddr[d_eob]) begin 269 | d_pfn <= d_itm[`TLB_PFN1]; 270 | d_vld <= d_itm[`TLB_V1 ]; 271 | d_cat <= d_itm[`TLB_C1 ]; 272 | d_drt <= d_itm[`TLB_D1 ]; 273 | end 274 | else begin 275 | d_pfn <= d_itm[`TLB_PFN0]; 276 | d_vld <= d_itm[`TLB_V0 ]; 277 | d_cat <= d_itm[`TLB_C0 ]; 278 | d_drt <= d_itm[`TLB_D0 ]; 279 | end 280 | 281 | case (i_eob) 282 | 12: i_paddr <= {i_pfn[19: 0], i_vaddr[11:0]}; 283 | 14: i_paddr <= {i_pfn[19: 2], i_vaddr[13:0]}; 284 | 16: i_paddr <= {i_pfn[19: 4], i_vaddr[15:0]}; 285 | 18: i_paddr <= {i_pfn[19: 6], i_vaddr[17:0]}; 286 | 20: i_paddr <= {i_pfn[19: 8], i_vaddr[19:0]}; 287 | 22: i_paddr <= {i_pfn[19:10], i_vaddr[21:0]}; 288 | 24: i_paddr <= {i_pfn[19:12], i_vaddr[23:0]}; 289 | 26: i_paddr <= {i_pfn[19:14], i_vaddr[25:0]}; 290 | 28: i_paddr <= {i_pfn[19:16], i_vaddr[27:0]}; 291 | default: i_paddr <= {i_pfn[19: 0], i_vaddr[11:0]}; 292 | endcase 293 | 294 | case (d_eob) 295 | 12: d_paddr <= {d_pfn[19: 0], d_vaddr[11:0]}; 296 | 14: d_paddr <= {d_pfn[19: 2], d_vaddr[13:0]}; 297 | 16: d_paddr <= {d_pfn[19: 4], d_vaddr[15:0]}; 298 | 18: d_paddr <= {d_pfn[19: 6], d_vaddr[17:0]}; 299 | 20: d_paddr <= {d_pfn[19: 8], d_vaddr[19:0]}; 300 | 22: d_paddr <= {d_pfn[19:10], d_vaddr[21:0]}; 301 | 24: d_paddr <= {d_pfn[19:12], d_vaddr[23:0]}; 302 | 26: d_paddr <= {d_pfn[19:14], d_vaddr[25:0]}; 303 | 28: d_paddr <= {d_pfn[19:16], d_vaddr[27:0]}; 304 | default: d_paddr <= {d_pfn[19: 0], d_vaddr[11:0]}; 305 | endcase 306 | end 307 | 308 | // TLB control & I/O 309 | reg [ 1: 0] i_state, d_state; 310 | 311 | assign immu_rdy = immu_en && ilk_valid; 312 | assign dmmu_rdy = dmmu_en && dlk_valid; 313 | 314 | 315 | wire tlb_nop = tlb_op == `TOP_NOP; 316 | 317 | wire [`TLB_Idx] idx_index = Index [`TLB_Idx]; 318 | wire [`TLB_Idx] idx_rand = Random[`TLB_Idx]; 319 | 320 | always @(posedge clk, posedge rst) begin 321 | if(rst) begin 322 | i_state <= `TLB_Idle; 323 | i_vaddr <= `ZeroWord; 324 | i_idx <= 0; 325 | immu_paddr <= `ZeroWord; 326 | immu_cat <= `false; 327 | ilk_asid <= 0; 328 | ilk_valid <= `false; 329 | i_tlbi <= `false; 330 | i_tlbr <= `false; 331 | 332 | d_state <= `TLB_Idle; 333 | d_vaddr <= `ZeroWord; 334 | d_idx <= 0; 335 | dmmu_paddr <= `ZeroWord; 336 | dmmu_cat <= `false; 337 | dlk_asid <= 0; 338 | dlk_valid <= `false; 339 | d_tlbi <= `false; 340 | d_tlbr <= `false; 341 | d_tlbm <= `false; 342 | 343 | cp0_idxwen <= `false; 344 | cp0_wIndex <= `ZeroWord; 345 | cp0_tlbwen <= `false; 346 | cp0_tlbitm <= 0; 347 | end 348 | else begin 349 | cp0_idxwen <= `false; 350 | cp0_tlbwen <= `false; 351 | 352 | case (i_state) 353 | `TLB_Idle: begin 354 | if(immu_en && !immu_rdy && tlb_nop) begin 355 | i_state <= `TLB_Translate; 356 | i_vaddr <= immu_vaddr; 357 | ilk_asid <= EntryHi[`ASID]; 358 | end 359 | end 360 | 361 | `TLB_Translate: begin 362 | if(i_miss) // TLBRefill 363 | i_tlbr <= `true; 364 | i_state <= `TLB_Ready; 365 | i_idx <= i_hitidx; 366 | end 367 | 368 | `TLB_Ready: begin 369 | if(!i_vld) // TLBInvalid 370 | i_tlbi <= `true; 371 | ilk_valid <= `true; 372 | immu_paddr <= i_paddr; 373 | case (i_cat) 374 | 3'd3: immu_cat <= `true; 375 | default: immu_cat <= `false; 376 | endcase 377 | 378 | if(!immu_stall) begin 379 | i_state <= `TLB_Idle; 380 | ilk_valid <= `false; 381 | i_tlbi <= `false; 382 | i_tlbr <= `false; 383 | end 384 | end 385 | endcase 386 | 387 | case (d_state) 388 | `TLB_Idle: begin 389 | if(dmmu_en && !dmmu_rdy && tlb_nop) begin 390 | d_state <= `TLB_Translate; 391 | d_vaddr <= dmmu_vaddr; 392 | dlk_asid <= EntryHi[`ASID]; 393 | end 394 | end 395 | 396 | `TLB_Translate: begin 397 | if(d_miss) // TLBRefill 398 | d_tlbr <= `true; 399 | d_state <= `TLB_Ready; 400 | d_idx <= d_hitidx; 401 | end 402 | 403 | `TLB_Ready: begin 404 | if(!d_vld) // TLBInvalid 405 | d_tlbi <= `true; 406 | if(!d_drt && dmmu_refs) // TLBModified 407 | d_tlbm <= `true; 408 | dlk_valid <= `true; 409 | dmmu_paddr <= d_paddr; 410 | case (d_cat) 411 | 3'd3: dmmu_cat <= `true; 412 | default: dmmu_cat <= `false; 413 | endcase 414 | 415 | if(!dmmu_stall) begin 416 | dlk_valid <= `false; 417 | d_tlbi <= `false; 418 | d_tlbr <= `false; 419 | d_tlbm <= `false; 420 | d_state <= `TLB_Idle; 421 | end 422 | end 423 | endcase 424 | 425 | case (tlb_op) 426 | `TOP_TLBR: begin 427 | cp0_tlbwen <= `true; 428 | cp0_tlbitm <= TLB[idx_index]; 429 | end 430 | 431 | `TOP_TLBP: begin 432 | cp0_idxwen <= `true; 433 | if(p_miss) cp0_wIndex <= 32'h80000000; 434 | else cp0_wIndex <= {32'b0, p_hitidx}; 435 | end 436 | endcase 437 | end 438 | end 439 | 440 | integer j; 441 | initial begin 442 | for(j = 0; j < `TLB_N; j = j + 1) 443 | TLB[j] <= 0; 444 | end 445 | 446 | always @(posedge clk) begin 447 | case (tlb_op) 448 | `TOP_TLBWI: begin 449 | TLB[idx_index][`TLB_Mask] <= PageMask[`Mask]; 450 | TLB[idx_index][`TLB_VPN2] <= EntryHi [`VPN2] & ~PageMask[`VMask]; 451 | TLB[idx_index][`TLB_ASID] <= EntryHi [`ASID]; 452 | TLB[idx_index][`TLB_G ] <= EntryLo0[`Glb ] & EntryLo1[`Glb]; 453 | TLB[idx_index][`TLB_PFN0] <= EntryLo0[`PFN ] & ~PageMask[`PMask]; 454 | TLB[idx_index][`TLB_V0 ] <= EntryLo0[`Vld ]; 455 | TLB[idx_index][`TLB_D0 ] <= EntryLo0[`Drt ]; 456 | TLB[idx_index][`TLB_C0 ] <= EntryLo0[`CAt ]; 457 | TLB[idx_index][`TLB_PFN1] <= EntryLo1[`PFN ] & ~PageMask[`PMask]; 458 | TLB[idx_index][`TLB_V1 ] <= EntryLo1[`Vld ]; 459 | TLB[idx_index][`TLB_D1 ] <= EntryLo1[`Drt ]; 460 | TLB[idx_index][`TLB_C1 ] <= EntryLo1[`CAt ]; 461 | end 462 | 463 | `TOP_TLBWR: begin 464 | TLB[idx_rand][`TLB_Mask] <= PageMask[`Mask]; 465 | TLB[idx_rand][`TLB_VPN2] <= EntryHi [`VPN2] & ~PageMask[`VMask]; 466 | TLB[idx_rand][`TLB_ASID] <= EntryHi [`ASID]; 467 | TLB[idx_rand][`TLB_G ] <= EntryLo0[`Glb ] & EntryLo1[`Glb]; 468 | TLB[idx_rand][`TLB_PFN0] <= EntryLo0[`PFN ] & ~PageMask[`PMask]; 469 | TLB[idx_rand][`TLB_V0 ] <= EntryLo0[`Vld ]; 470 | TLB[idx_rand][`TLB_D0 ] <= EntryLo0[`Drt ]; 471 | TLB[idx_rand][`TLB_C0 ] <= EntryLo0[`CAt ]; 472 | TLB[idx_rand][`TLB_PFN1] <= EntryLo1[`PFN ] & ~PageMask[`PMask]; 473 | TLB[idx_rand][`TLB_V1 ] <= EntryLo1[`Vld ]; 474 | TLB[idx_rand][`TLB_D1 ] <= EntryLo1[`Drt ]; 475 | TLB[idx_rand][`TLB_C1 ] <= EntryLo1[`CAt ]; 476 | end 477 | endcase 478 | end 479 | 480 | `endif 481 | 482 | endmodule --------------------------------------------------------------------------------