├── src ├── memory │ ├── comport.h │ ├── comm.h │ ├── comport.cpp │ ├── main.cpp │ └── comm.cpp └── cpu │ ├── common.h │ ├── opcode.h │ ├── alu.v │ ├── fifo.v │ ├── mfifo.v │ ├── pipeline_insnfetch.v │ ├── alu_multiplier.v │ ├── cpu.v │ ├── alu_divider.v │ ├── uart_comm.v │ ├── cpu_core.v │ ├── pipeline_mem.v │ ├── memory_controller.v │ ├── multchan_comm.v │ ├── cache.v │ ├── pipeline_exec.v │ └── pipeline_decode.v ├── README.md ├── sim ├── sim_cpu.v └── sim_memory.v └── LICENSE /src/memory/comport.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | class COMPort 8 | { 9 | public: 10 | COMPort(); 11 | ~COMPort(); 12 | 13 | bool open(const std::string &name); 14 | void write(const unsigned char *buf, size_t length); 15 | size_t read(unsigned char *buf, size_t length); 16 | 17 | protected: 18 | HANDLE hComm; 19 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mips-cpu 2 | A MIPS CPU implemented in Verilog 3 | 4 | This is a course project of ACM Honored Class @ SJTU ([wiki](https://acm.sjtu.edu.cn/wiki/System_2017)) 5 | 6 | ## Features 7 | - 32-bit MIPS instruction 8 | - 5-stage pipeline 9 | - set-associative cache 10 | - runnable on FPGA (tested on XC7A35T) 11 | - memory simulated by C++ program (use UART) 12 | -------------------------------------------------------------------------------- /src/memory/comm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "comport.h" 4 | #include 5 | #include 6 | 7 | class Comm 8 | { 9 | public: 10 | Comm(COMPort &com) : com(com), sendPacketID(0), recvPacketID(0) {} 11 | 12 | void always_read(std::function &)> callback); 13 | void write(const std::vector &data); 14 | 15 | protected: 16 | COMPort &com; 17 | size_t recvPacketID; 18 | size_t sendPacketID; 19 | }; -------------------------------------------------------------------------------- /sim/sim_cpu.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2017/06/22 21:36:19 7 | // Design Name: 8 | // Module Name: sim_cpu 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | 23 | module sim_cpu(); 24 | reg CLK; 25 | reg RST; 26 | wire Rx, Tx; 27 | 28 | cpu CPU(CLK, RST, Tx, Rx); 29 | sim_memory sm(CLK, RST, Rx, Tx); 30 | 31 | initial begin 32 | CLK = 0; 33 | RST = 0; 34 | RST = #1 1; 35 | repeat(1000) #1 CLK = !CLK; 36 | RST = 0; 37 | forever #1 CLK = !CLK; 38 | end 39 | endmodule 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 张哲恺 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/cpu/common.h: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2017/06/17 18:56:28 7 | // Design Name: 8 | // Module Name: common 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | `define CLOG2(x) \ 23 | ((x <= 0) ? -1 : \ 24 | (x == 1) ? 0 : \ 25 | (x <= 2) ? 1 : \ 26 | (x <= 4) ? 2 : \ 27 | (x <= 8) ? 3 : \ 28 | (x <= 16) ? 4 : \ 29 | (x <= 32) ? 5 : \ 30 | (x <= 64) ? 6 : \ 31 | (x <= 128) ? 7 : \ 32 | (x <= 256) ? 8 : \ 33 | (x <= 512) ? 9 : \ 34 | (x <= 1024) ? 10 : \ 35 | (x <= 2048) ? 11 : \ 36 | (x <= 4096) ? 12 : \ 37 | (x <= 8192) ? 13 : \ 38 | (x <= 16384) ? 14 : \ 39 | (x <= 32768) ? 15 : \ 40 | (x <= 65536) ? 16 : \ 41 | (x <= 131072) ? 17 : \ 42 | (x <= 262144) ? 18 : \ 43 | (x <= 524288) ? 19 : \ 44 | (x <= 1048576) ? 20 : -1) 45 | -------------------------------------------------------------------------------- /src/cpu/opcode.h: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2017/06/18 20:51:37 7 | // Design Name: 8 | // Module Name: opcode 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | `define ALU_OPCODE_WIDTH 5 23 | 24 | `define ALU_NOP 0 25 | `define ALU_ADD 1 26 | `define ALU_ADDU 2 27 | `define ALU_SUB 3 28 | `define ALU_SUBU 4 29 | `define ALU_MULTL 5 30 | `define ALU_MULTH 6 31 | `define ALU_MULTLU 7 32 | `define ALU_MULTHU 8 33 | `define ALU_DIV 9 34 | `define ALU_MOD 10 35 | `define ALU_DIVU 11 36 | `define ALU_MODU 12 37 | `define ALU_AND 13 38 | `define ALU_OR 14 39 | `define ALU_NOR 15 40 | `define ALU_XOR 16 41 | `define ALU_SLL 17 42 | `define ALU_SRL 18 43 | `define ALU_SRA 19 44 | `define ALU_ROR 20 45 | `define ALU_SEQ 21 46 | `define ALU_SLT 22 47 | `define ALU_SLTU 23 48 | 49 | `define MEM_OPCODE_WIDTH 4 50 | 51 | `define MEM_NOP 0 52 | `define MEM_LB 1 53 | `define MEM_LBU 2 54 | `define MEM_LH 3 55 | `define MEM_LHU 4 56 | `define MEM_LW 5 57 | `define MEM_SB 6 58 | `define MEM_SH 7 59 | `define MEM_SW 8 60 | 61 | -------------------------------------------------------------------------------- /src/memory/comport.cpp: -------------------------------------------------------------------------------- 1 | #include "comport.h" 2 | 3 | COMPort::COMPort() : hComm(INVALID_HANDLE_VALUE) {} 4 | COMPort::~COMPort() 5 | { 6 | if (hComm != INVALID_HANDLE_VALUE) 7 | CloseHandle(hComm); 8 | } 9 | 10 | bool COMPort::open(const std::string &name) 11 | { 12 | hComm = CreateFileA(name.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 13 | if (hComm == INVALID_HANDLE_VALUE) 14 | return false; 15 | DCB dcb; 16 | //dcb.DCBlength = sizeof(dcb); 17 | if (!GetCommState(hComm, &dcb)) 18 | return false; 19 | BuildCommDCBA("baud=230400 parity=E data=8 stop=1", &dcb); 20 | /*dcb.BaudRate = 9600; 21 | dcb.fBinary = TRUE; 22 | dcb.ByteSize = 8; 23 | dcb.StopBits = ONESTOPBIT; 24 | dcb.fParity = TRUE; 25 | dcb.Parity = PARITY_ODD; 26 | dcb.fDtrControl = DTR_CONTROL_DISABLE; 27 | dcb.fRtsControl = RTS_CONTROL_DISABLE;*/ 28 | if (!SetCommState(hComm, &dcb)) 29 | return false; 30 | //SetCommMask(hComm, EV_RXCHAR); 31 | COMMTIMEOUTS CommTimeOuts; 32 | GetCommTimeouts(hComm, &CommTimeOuts); 33 | CommTimeOuts.ReadIntervalTimeout = 0; 34 | CommTimeOuts.ReadTotalTimeoutConstant = 0; 35 | CommTimeOuts.ReadTotalTimeoutMultiplier = 0; 36 | CommTimeOuts.WriteTotalTimeoutConstant = 1000; 37 | CommTimeOuts.WriteTotalTimeoutMultiplier = 10; 38 | SetCommTimeouts(hComm, &CommTimeOuts); 39 | return true; 40 | } 41 | 42 | void COMPort::write(const unsigned char *buf, size_t length) 43 | { 44 | DWORD dwWrite; 45 | WriteFile(hComm, buf, length, &dwWrite, NULL); 46 | } 47 | 48 | size_t COMPort::read(unsigned char *buf, size_t length) 49 | { 50 | DWORD dwRead; 51 | if (!ReadFile(hComm, buf, length, &dwRead, NULL)) 52 | return 0; 53 | return dwRead; 54 | } -------------------------------------------------------------------------------- /src/cpu/alu.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2017/06/22 16:16:07 7 | // Design Name: 8 | // Module Name: alu 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | `include "opcode.h" 23 | 24 | module alu( 25 | input CLK, 26 | input RST, 27 | 28 | input [`ALU_OPCODE_WIDTH-1:0] opcode, 29 | input [31:0] src1, 30 | input [31:0] src2, 31 | output reg [31:0] result, 32 | 33 | output reg busy, 34 | output reg done 35 | ); 36 | 37 | always @(posedge CLK or posedge RST) begin 38 | if(RST) begin 39 | result <= 0; 40 | busy <= 0; 41 | done <= 0; 42 | end else begin 43 | done <= 1; 44 | busy <= 0; 45 | case(opcode) 46 | `ALU_ADD: result <= src1 + src2; 47 | `ALU_ADDU: result <= src1 + src2; 48 | `ALU_SUB: result <= src1 - src2; 49 | `ALU_SUBU: result <= src1 - src2; 50 | `ALU_AND: result <= src1 & src2; 51 | `ALU_OR: result <= src1 | src2; 52 | `ALU_NOR: result <= ~(src1 | src2); 53 | `ALU_XOR: result <= src1 ^ src2; 54 | `ALU_SLL: result <= src2 << src1[4:0]; 55 | `ALU_SRL: result <= src2 >> src1[4:0]; 56 | `ALU_SRA: result <= $signed(src2) >>> src1[4:0]; 57 | `ALU_ROR: result <= (src2 >> src1[4:0]) | (src2 << (32-src1[4:0])); 58 | `ALU_SEQ: result <= src1 == src2 ? 32'b1 : 32'b0; 59 | `ALU_SLT: result <= $signed(src1) < $signed(src2) ? 32'b1 : 32'b0; 60 | `ALU_SLTU: result <= src1 < src2 ? 32'b1 : 32'b0; 61 | default: done <= 0; 62 | endcase 63 | end 64 | end 65 | endmodule 66 | -------------------------------------------------------------------------------- /src/cpu/fifo.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2017/06/15 07:35:24 7 | // Design Name: 8 | // Module Name: fifo 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | 23 | module fifo 24 | #( 25 | parameter SIZE_BIT = 3, 26 | parameter WIDTH = 8 27 | ) 28 | ( 29 | input CLK, 30 | input RST, 31 | input read_flag, 32 | output [WIDTH-1:0] read_data, 33 | input write_flag, 34 | input [WIDTH-1:0] write_data, 35 | output empty, 36 | output full 37 | ); 38 | 39 | localparam SIZE = 1 << SIZE_BIT; 40 | reg [WIDTH-1:0] buffer[SIZE-1:0]; 41 | reg [SIZE_BIT-1:0] read_ptr; 42 | reg [SIZE_BIT-1:0] write_ptr; 43 | reg [SIZE_BIT:0] buffer_size; 44 | 45 | assign empty = buffer_size == 0; 46 | assign full = buffer_size == SIZE; 47 | 48 | wire read, write; 49 | assign read = read_flag && !empty; 50 | assign write = write_flag && !full; 51 | 52 | assign read_data = buffer[read_ptr]; 53 | 54 | integer i; 55 | always @(negedge CLK or posedge RST) begin 56 | if(RST) begin 57 | read_ptr <= 0; 58 | write_ptr <= 0; 59 | buffer_size <= 0; 60 | for(i=0; i 3 | 4 | int main() 5 | { 6 | COMPort com; 7 | if (!com.open("com4")) 8 | { 9 | fprintf(stderr, "Failed to open serial port\n"); 10 | return 1; 11 | } 12 | Comm comm(com); 13 | 14 | const unsigned int MEMORY_SIZE = 8192; 15 | unsigned char *memory = new unsigned char[MEMORY_SIZE]; 16 | memset(memory, 0, MEMORY_SIZE); 17 | 18 | FILE *fram = fopen(R"(D:\Project\Vivado\mips_cpu\testcase\mips.bin)", "rb"); 19 | fread(memory, sizeof(unsigned char), MEMORY_SIZE, fram); 20 | //for(int i=0; i<1000; i++) 21 | // comm.write({ 2, 3, 3, 3 }); 22 | /*comm.always_read([&](const std::vector &data) 23 | { 24 | unsigned int num = data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24; 25 | num++; 26 | comm.write({ unsigned char(num), unsigned char(num >> 8), 27 | unsigned char(num >> 16), unsigned char(num >> 24) }); 28 | });*/ 29 | comm.always_read([&](const std::vector &data) 30 | { 31 | if (data.size() == 5 && data[4] == 0) 32 | { 33 | unsigned int addr = data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24; 34 | if (addr >= MEMORY_SIZE) 35 | printf("Read Addr 0x%08x out of range!\n", addr); 36 | else 37 | { 38 | printf("Read Addr 0x%08x: %02x%02x%02x%02x\n", addr, (int)memory[addr + 3], (int)memory[addr + 2], (int)memory[addr + 1], memory[addr]); 39 | comm.write({ memory[addr], memory[addr + 1], memory[addr + 2], memory[addr + 3] }); 40 | } 41 | } 42 | else if (data.size() == 9) 43 | { 44 | unsigned int addr = data[4] | data[5] << 8 | data[6] << 16 | data[7] << 24; 45 | unsigned int wdata = data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24; 46 | printf("Write to Addr 0x%08x: %08x, Mask = %d\n", addr, wdata, data[8] & 0b1111); 47 | if (addr >= MEMORY_SIZE) 48 | { 49 | printf("Write addr out of range!"); 50 | } 51 | else 52 | { 53 | if (data[8] & 0b0001) 54 | memory[addr] = data[0]; 55 | if (data[8] & 0b0010) 56 | memory[addr + 1] = data[1]; 57 | if (data[8] & 0b0100) 58 | memory[addr + 2] = data[2]; 59 | if (data[8] & 0b1000) 60 | memory[addr + 3] = data[3]; 61 | } 62 | } 63 | }); 64 | return 0; 65 | } -------------------------------------------------------------------------------- /src/cpu/mfifo.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2017/06/15 16:01:34 7 | // Design Name: 8 | // Module Name: mfifo 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | //Multiple FIFO with single input port and multiple output port 23 | module simo_fifo 24 | #( 25 | parameter CHANNEL_BIT = 1, 26 | parameter SIZE_BIT = 3, 27 | parameter WIDTH = 8 28 | ) 29 | ( 30 | input CLK, 31 | input RST, 32 | 33 | input [(1< 3 | #include 4 | #include 5 | 6 | void Comm::write(const std::vector &data) 7 | { 8 | assert(data.size() <= 9); 9 | sendPacketID++; 10 | unsigned char buf[50]; 11 | buf[0] = (0b100 << 5) | (sendPacketID & 0b11111); 12 | buf[1] = 0b10100000; 13 | buf[2] = (0b110 << 5) | (data.size() & 0b11111); 14 | 15 | std::bitset<72> bits = 0; 16 | for (size_t i = 0; i < data.size(); i++) 17 | for (size_t j = 0; j < 8; j++) 18 | bits[i * 8 + j] = data[i] & (1 << j) ? 1 : 0; 19 | 20 | size_t i = 3; 21 | for (size_t sent = 0; sent < data.size() * 8; sent += 7, i++) 22 | { 23 | buf[i] = 0; 24 | for (size_t j = 0; j < 7; j++) 25 | buf[i] |= bits[sent + j] << j; 26 | } 27 | buf[i] = (0b111 << 5) | (sendPacketID & 0b11111); 28 | 29 | com.write(buf, i+1); 30 | } 31 | 32 | void Comm::always_read(std::function &)> callback) 33 | { 34 | enum states { IDLE, CHANNEL, LENGTH, DATA, END }; 35 | states state = IDLE; 36 | 37 | size_t length_bit; 38 | size_t packet_id; 39 | size_t recv_bit; 40 | std::bitset<72> bits; 41 | 42 | auto read_packet = [&](unsigned char packet) 43 | { 44 | switch (state) 45 | { 46 | case IDLE: 47 | if (packet >> 5 == 0b100) 48 | { 49 | packet_id = packet & 0b11111; 50 | if (packet_id != ((recvPacketID + 1) & 0b11111)) 51 | std::cerr << "Lose Packet!" << std::endl; 52 | recv_bit = 0; 53 | state = CHANNEL; 54 | } 55 | else 56 | std::cerr << "Corrupted Packet @IDLE" << std::endl; 57 | break; 58 | 59 | case CHANNEL: 60 | if (packet >> 5 == 0b101) 61 | state = LENGTH; 62 | else 63 | { 64 | state = IDLE; 65 | std::cerr << "Corrupted Packet @Channel" << std::endl; 66 | } 67 | break; 68 | 69 | case LENGTH: 70 | if (packet >> 5 == 0b110) 71 | { 72 | length_bit = (packet & 0b11111) * 8; 73 | state = DATA; 74 | bits.reset(); 75 | } 76 | else 77 | { 78 | state = IDLE; 79 | std::cerr << "Corrupted Packet @Length" << std::endl; 80 | } 81 | break; 82 | 83 | case DATA: 84 | if (packet >> 7 == 0b0) 85 | { 86 | for (size_t i = 0; i < 7 && recv_bit < length_bit; i++, recv_bit++) 87 | bits[recv_bit] = packet & (1 << i) ? 1 : 0; 88 | if (recv_bit == length_bit) 89 | state = END; 90 | } 91 | else 92 | { 93 | state = IDLE; 94 | std::cerr << "Corrupted Packet @Data." << recv_bit / 7 << std::endl; 95 | } 96 | break; 97 | 98 | case END: 99 | if (packet >> 5 == 0b111) 100 | { 101 | if (packet_id == (packet & 0b11111)) 102 | { 103 | recvPacketID = packet_id; 104 | std::vector result; 105 | size_t write_bit = 0; 106 | for (size_t write_bit = 0; write_bit < recv_bit; write_bit += 8) 107 | { 108 | char tmp = 0; 109 | for (size_t j = 0; j < 8; j++) 110 | tmp |= bits[write_bit + j] << j; 111 | result.push_back(tmp); 112 | } 113 | callback(result); 114 | } 115 | } 116 | else 117 | { 118 | std::cerr << "Corrupted Packet @End" << std::endl; 119 | } 120 | state = IDLE; 121 | } 122 | }; 123 | 124 | while (true) 125 | { 126 | unsigned char tmp; 127 | size_t len = com.read(&tmp, 1); 128 | if (len == 0) 129 | break; 130 | //std::cerr << "Read " << std::hex << (int)tmp << std::endl; 131 | //for (size_t i = 0; i < len; i++) 132 | //read_packet(tmp[i]); 133 | read_packet(tmp); 134 | } 135 | } -------------------------------------------------------------------------------- /src/cpu/cpu.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2017/06/21 13:08:03 7 | // Design Name: 8 | // Module Name: cpu 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | 23 | module cpu( 24 | input EXCLK, 25 | input button, 26 | output Tx, 27 | input Rx 28 | ); 29 | 30 | //reg CLK = 0; 31 | // reg RST_Powerup; 32 | // reg reseted = 0; 33 | // always @(posedge EXCLK) begin 34 | // RST_Powerup <= 0; 35 | // if(!reseted) begin 36 | // RST_Powerup <= 1; 37 | // reseted <= 1; 38 | // end 39 | // //CLK <= !CLK; 40 | // end 41 | 42 | reg RST; 43 | reg RST_delay; 44 | 45 | wire CLK; 46 | clk_wiz_0 clk(CLK, 1'b0, EXCLK); 47 | 48 | always @(posedge CLK or posedge button) begin 49 | if(button) begin 50 | RST <= 1; 51 | RST_delay <= 1; 52 | end else begin 53 | RST_delay <= 0; 54 | RST <= RST_delay; 55 | end 56 | end 57 | 58 | wire UART_send_flag; 59 | wire [7:0] UART_send_data; 60 | wire UART_recv_flag; 61 | wire [7:0] UART_recv_data; 62 | wire UART_sendable; 63 | wire UART_receivable; 64 | 65 | uart_comm #(.BAUDRATE(5000000/*115200*/), .CLOCKRATE(66667000)) UART( 66 | CLK, RST, 67 | UART_send_flag, UART_send_data, 68 | UART_recv_flag, UART_recv_data, 69 | UART_sendable, UART_receivable, 70 | Tx, Rx); 71 | 72 | localparam CHANNEL_BIT = 1; 73 | localparam MESSAGE_BIT = 72; 74 | localparam CHANNEL = 1 << CHANNEL_BIT; 75 | 76 | wire COMM_read_flag[CHANNEL-1:0]; 77 | wire [MESSAGE_BIT-1:0] COMM_read_data[CHANNEL-1:0]; 78 | wire [4:0] COMM_read_length[CHANNEL-1:0]; 79 | wire COMM_write_flag[CHANNEL-1:0]; 80 | wire [MESSAGE_BIT-1:0] COMM_write_data[CHANNEL-1:0]; 81 | wire [4:0] COMM_write_length[CHANNEL-1:0]; 82 | wire COMM_readable[CHANNEL-1:0]; 83 | wire COMM_writable[CHANNEL-1:0]; 84 | 85 | multchan_comm #(.MESSAGE_BIT(MESSAGE_BIT), .CHANNEL_BIT(CHANNEL_BIT)) COMM( 86 | CLK, RST, 87 | UART_send_flag, UART_send_data, 88 | UART_recv_flag, UART_recv_data, 89 | UART_sendable, UART_receivable, 90 | {COMM_read_flag[1], COMM_read_flag[0]}, 91 | {COMM_read_length[1], COMM_read_data[1], COMM_read_length[0], COMM_read_data[0]}, 92 | {COMM_write_flag[1], COMM_write_flag[0]}, 93 | {COMM_write_length[1], COMM_write_data[1], COMM_write_length[0], COMM_write_data[0]}, 94 | {COMM_readable[1], COMM_readable[0]}, 95 | {COMM_writable[1], COMM_writable[0]}); 96 | 97 | wire [2*2-1:0] MEM_rw_flag; 98 | wire [2*32-1:0] MEM_addr; 99 | wire [2*32-1:0] MEM_read_data; 100 | wire [2*32-1:0] MEM_write_data; 101 | wire [2*4-1:0] MEM_write_mask; 102 | wire [1:0] MEM_busy; 103 | wire [1:0] MEM_done; 104 | 105 | memory_controller MEM_CTRL( 106 | CLK, RST, 107 | COMM_write_flag[0], COMM_write_data[0], COMM_write_length[0], 108 | COMM_read_flag[0], COMM_read_data[0], COMM_read_length[0], 109 | COMM_writable[0], COMM_readable[0], 110 | MEM_rw_flag, MEM_addr, 111 | MEM_read_data, MEM_write_data, MEM_write_mask, 112 | MEM_busy, MEM_done); 113 | 114 | cpu_core CORE( 115 | CLK, RST, 116 | MEM_rw_flag, MEM_addr, 117 | MEM_read_data, MEM_write_data, MEM_write_mask, 118 | MEM_busy, MEM_done); 119 | endmodule 120 | -------------------------------------------------------------------------------- /src/cpu/alu_divider.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2017/06/22 16:45:58 7 | // Design Name: 8 | // Module Name: alu_divider 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | `include "opcode.h" 23 | 24 | module alu_divider( 25 | input CLK, 26 | input RST, 27 | 28 | input [`ALU_OPCODE_WIDTH-1:0] opcode, 29 | input [31:0] src1, 30 | input [31:0] src2, 31 | output reg [31:0] result, 32 | 33 | output reg busy, 34 | output reg done 35 | ); 36 | 37 | reg [31:0] dividend, divisor; 38 | reg sign, remainder_flag; 39 | reg [31:0] quotient, remainder, work_divisor; 40 | reg [4:0] current_bit; 41 | 42 | //wire [31:0] sign_remainder = $signed(dividend) < 0 ? -remainder : remainder; 43 | //wire [31:0] sign_quotient = ($signed(dividend) < 0) ^ ($signed(divisor) < 0) ? -quotient : quotient; 44 | 45 | function [31:0] sign_remainder; 46 | input [31:0] in_dividend; 47 | input [31:0] in_remainder; 48 | 49 | if($signed(in_dividend) < 0) 50 | sign_remainder = -in_remainder; 51 | else 52 | sign_remainder = in_remainder; 53 | endfunction 54 | 55 | function [31:0] sign_quotient; 56 | input [31:0] in_dividend; 57 | input [31:0] in_divisor; 58 | input [31:0] in_quotient; 59 | 60 | if(($signed(dividend) < 0) ^ ($signed(divisor) < 0)) 61 | sign_quotient = -quotient; 62 | else 63 | sign_quotient = quotient; 64 | endfunction 65 | 66 | task divide_bit; 67 | reg [63:0] tmp; 68 | 69 | begin 70 | tmp = {{32{1'b0}}, work_divisor} << current_bit; 71 | if(tmp <= remainder) begin 72 | quotient[current_bit] = 1; 73 | remainder = remainder - tmp; 74 | end else 75 | quotient[current_bit] = 0; 76 | current_bit = current_bit - 1; 77 | end 78 | endtask 79 | 80 | always @(posedge CLK or posedge RST) begin 81 | if(RST) begin 82 | dividend <= 0; 83 | divisor <= 0; 84 | sign <= 0; 85 | remainder_flag <= 0; 86 | quotient <= 0; 87 | remainder <= 0; 88 | current_bit <= 0; 89 | result <= 0; 90 | busy <= 0; 91 | done <= 0; 92 | end else begin 93 | done <= 0; 94 | if(!busy) begin 95 | if(opcode == `ALU_MOD || opcode == `ALU_MODU) 96 | remainder_flag = 1; 97 | else 98 | remainder_flag = 0; 99 | 100 | case(opcode) 101 | `ALU_DIV, `ALU_MOD: begin 102 | if(dividend == src1 && divisor == src2 && sign) begin 103 | result <= remainder_flag ? sign_remainder(dividend, remainder) : sign_quotient(dividend, divisor, quotient); 104 | busy <= 0; 105 | done <= 1; 106 | end else begin 107 | dividend <= src1; 108 | divisor <= src2; 109 | sign <= 1; 110 | if($signed(src1) < 0) 111 | remainder <= -src1; 112 | else 113 | remainder <= src1; 114 | if($signed(src2) < 0) 115 | work_divisor <= -src2; 116 | else 117 | work_divisor <= src2; 118 | current_bit <= 31; 119 | busy <= 1; 120 | done <= 0; 121 | end 122 | end 123 | 124 | `ALU_DIVU, `ALU_MODU: begin 125 | if(dividend == src1 && divisor == src2 && !sign) begin 126 | result <= remainder_flag ? remainder : quotient; 127 | busy <= 0; 128 | done <= 1; 129 | end else begin 130 | dividend <= src1; 131 | divisor <= src2; 132 | sign <= 0; 133 | remainder <= src1; 134 | work_divisor <= src2; 135 | current_bit <= 31; 136 | busy <= 1; 137 | done <= 0; 138 | end 139 | end 140 | 141 | default: begin 142 | busy <= 0; 143 | done <= 0; 144 | end 145 | endcase 146 | end else begin 147 | divide_bit(); 148 | if(current_bit == 31) begin 149 | if(sign) 150 | result <= remainder_flag ? sign_remainder(dividend, remainder) : sign_quotient(dividend, divisor, quotient); 151 | else 152 | result <= remainder_flag ? remainder : quotient; 153 | busy <= 0; 154 | done <= 1; 155 | end 156 | end 157 | end 158 | end 159 | endmodule 160 | -------------------------------------------------------------------------------- /src/cpu/uart_comm.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2017/06/15 07:07:54 7 | // Design Name: 8 | // Module Name: uart_comm 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | module uart_comm 23 | #( 24 | parameter BAUDRATE = 9600, 25 | parameter CLOCKRATE = 100000000 26 | )( 27 | input CLK, 28 | input RST, 29 | 30 | input send_flag, 31 | input [7:0] send_data, 32 | input recv_flag, 33 | output [7:0] recv_data, 34 | 35 | output sendable, 36 | output receivable, 37 | 38 | output reg Tx, 39 | input Rx 40 | ); 41 | 42 | reg recv_write_flag; 43 | reg [7:0] recv_write_data; 44 | wire recv_empty, recv_full; 45 | fifo #(.WIDTH(8)) recv_buffer(CLK, RST, recv_flag, recv_data, recv_write_flag, recv_write_data, recv_empty, recv_full); 46 | 47 | reg send_read_flag; 48 | wire [7:0] send_read_data; 49 | reg [7:0] send_read_data_buf; 50 | wire send_empty, send_full; 51 | fifo #(.WIDTH(8)) send_buffer(CLK, RST, send_read_flag, send_read_data, send_flag, send_data, send_empty, send_full); 52 | 53 | assign receivable = !recv_empty; 54 | assign sendable = !send_full; 55 | 56 | localparam SAMPLE_INTERVAL = CLOCKRATE / BAUDRATE; 57 | 58 | localparam STATUS_IDLE = 0; 59 | localparam STATUS_BEGIN = 1; 60 | localparam STATUS_DATA = 2; 61 | localparam STATUS_VALID = 4; 62 | localparam STATUS_END = 8; 63 | reg [3:0] recv_status; 64 | reg [2:0] recv_bit; 65 | reg recv_parity; 66 | 67 | integer recv_counter; 68 | reg recv_clock; 69 | 70 | wire sample = recv_counter == SAMPLE_INTERVAL / 2; 71 | 72 | always @(posedge CLK or posedge RST) begin 73 | if(RST) begin 74 | recv_write_flag <= 0; 75 | recv_write_data <= 0; 76 | recv_status <= STATUS_IDLE; 77 | recv_bit <= 0; 78 | recv_parity <= 0; 79 | recv_counter <= 0; 80 | recv_clock <= 0; 81 | end else begin 82 | recv_write_flag <= 0; 83 | if(recv_clock) begin 84 | if(recv_counter == SAMPLE_INTERVAL - 1) 85 | recv_counter <= 0; 86 | else 87 | recv_counter <= recv_counter + 1; 88 | end 89 | if(recv_status == STATUS_IDLE) begin 90 | if(!Rx) begin 91 | recv_status <= STATUS_BEGIN; 92 | recv_counter <= 0; 93 | recv_clock <= 1; 94 | end 95 | end else if(sample) begin 96 | case(recv_status) 97 | STATUS_BEGIN:begin 98 | if(!Rx) begin 99 | recv_status <= STATUS_DATA; 100 | recv_bit <= 0; 101 | recv_parity <= 0; 102 | end else begin 103 | recv_status <= STATUS_IDLE; 104 | recv_clock <= 0; 105 | end 106 | end 107 | 108 | STATUS_DATA:begin 109 | recv_parity <= recv_parity ^ Rx; 110 | recv_write_data[recv_bit] <= Rx; 111 | recv_bit <= recv_bit + 1; 112 | if(recv_bit == 7) 113 | recv_status <= STATUS_VALID; 114 | end 115 | 116 | STATUS_VALID:begin 117 | if(recv_parity == Rx && !recv_full) 118 | recv_write_flag <= 1; 119 | recv_status <= STATUS_END; 120 | end 121 | 122 | STATUS_END: begin 123 | recv_status <= STATUS_IDLE; 124 | recv_clock <= 0; 125 | end 126 | endcase 127 | end 128 | end 129 | end 130 | 131 | integer counter; 132 | always @(posedge CLK or posedge RST) begin 133 | if(RST) begin 134 | counter <= 0; 135 | end else begin 136 | counter <= counter + 1; 137 | if(counter == SAMPLE_INTERVAL - 1) 138 | counter <= 0; 139 | end 140 | end 141 | 142 | reg [3:0] send_status; 143 | reg [2:0] send_bit; 144 | reg send_parity; 145 | reg tosend; 146 | 147 | always @(posedge CLK or posedge RST) begin 148 | if(RST) begin 149 | send_read_flag <= 0; 150 | send_read_data_buf <= 0; 151 | send_status <= STATUS_IDLE; 152 | send_bit <= 0; 153 | send_parity <= 0; 154 | tosend <= 0; 155 | Tx <= 1; 156 | end else begin 157 | send_read_flag <= 0; 158 | 159 | if(counter == 0) begin 160 | case(send_status) 161 | STATUS_IDLE:begin 162 | if(!send_empty) begin 163 | send_read_data_buf <= send_read_data; 164 | send_read_flag <= 1; 165 | Tx <= 0; 166 | send_status <= STATUS_DATA; 167 | send_bit <= 0; 168 | send_parity <= 0; 169 | end 170 | end 171 | 172 | STATUS_DATA:begin 173 | Tx <= send_read_data_buf[send_bit]; 174 | send_parity <= send_parity ^ send_read_data_buf[send_bit]; 175 | send_bit <= send_bit + 1; 176 | if(send_bit == 7) 177 | send_status <= STATUS_VALID; 178 | end 179 | 180 | STATUS_VALID:begin 181 | Tx <= send_parity; 182 | send_status <= STATUS_END; 183 | end 184 | 185 | STATUS_END:begin 186 | Tx <= 1; 187 | send_status <= STATUS_IDLE; 188 | tosend = 0; 189 | end 190 | endcase 191 | end 192 | end 193 | end 194 | endmodule 195 | -------------------------------------------------------------------------------- /src/cpu/cpu_core.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2017/06/21 12:26:00 7 | // Design Name: 8 | // Module Name: cpu_core 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | `include "opcode.h" 23 | 24 | module cpu_core( 25 | input CLK, 26 | input RST, 27 | 28 | //To Memory Controller 29 | output [2*2-1:0] rw_flag, 30 | output [2*32-1:0] addr, 31 | input [2*32-1:0] read_data, 32 | output [2*32-1:0] write_data, 33 | output [2*4-1:0] write_mask, 34 | input [1:0] busy, 35 | input [1:0] done 36 | ); 37 | 38 | wire [2:0] writeback_insn_id; 39 | wire [31:0] writeback_data; 40 | wire [2:0] alu_forward_insn_id; 41 | wire [31:0] alu_forward_data; 42 | 43 | wire ID_IF_next_insn_enabled; 44 | wire [31:0] ID_IF_next_insn; 45 | wire ID_IF_busy; 46 | 47 | wire [31:0] IF_ID_insn; 48 | wire [31:0] IF_ID_insnPC; 49 | wire IF_ID_placeholder_insn; 50 | 51 | 52 | 53 | wire [1:0] ICACHE_rw_flag; 54 | wire [31:0] ICACHE_addr; 55 | wire [31:0] ICACHE_read_data; 56 | wire [31:0] ICACHE_write_data; 57 | wire [3:0] ICACHE_write_mask; 58 | wire ICACHE_busy; 59 | wire ICACHE_done; 60 | 61 | wire ICACHE_flush_flag; 62 | wire [31:0] ICACHE_flush_addr; 63 | 64 | assign ICACHE_write_data = 0; 65 | assign ICACHE_write_mask = 0; 66 | assign ICACHE_rw_flag[1] = 0; 67 | 68 | cache ICACHE( 69 | CLK, RST, 70 | ICACHE_rw_flag, 71 | ICACHE_addr, 72 | ICACHE_read_data, 73 | ICACHE_write_data, ICACHE_write_mask, 74 | ICACHE_busy, ICACHE_done, 75 | ICACHE_flush_flag, ICACHE_flush_addr, 76 | rw_flag[3:2], addr[63:32], read_data[63:32], write_data[63:32], write_mask[7:4], busy[1], done[1]); 77 | 78 | pipeline_insnfetch IF( 79 | CLK, RST, 80 | ICACHE_rw_flag[0], ICACHE_addr, ICACHE_read_data, ICACHE_busy, ICACHE_done, 81 | ID_IF_next_insn_enabled, ID_IF_next_insn, ID_IF_busy, 82 | IF_ID_insn, IF_ID_insnPC, IF_ID_placeholder_insn); 83 | 84 | wire EX_ID_busy; 85 | wire [31:0] ID_EX_insnPC; 86 | wire [2:0] ID_EX_insn_id; 87 | wire [`ALU_OPCODE_WIDTH-1:0] ID_EX_alu_opcode; 88 | wire [31:0] ID_EX_alu_src1; 89 | wire ID_EX_alu_src1_forward; 90 | wire [2:0] ID_EX_alu_src1_forward_from; 91 | wire [31:0] ID_EX_alu_src2; 92 | wire ID_EX_alu_src2_forward; 93 | wire [2:0] ID_EX_alu_src2_forward_from; 94 | wire [`MEM_OPCODE_WIDTH-1:0] ID_EX_mem_opcode; 95 | wire [31:0] ID_EX_mem_src2; 96 | wire ID_EX_mem_src2_forward; 97 | wire [2:0] ID_EX_mem_src2_forward_from; 98 | 99 | pipeline_decode ID( 100 | CLK, RST, 101 | IF_ID_insn, IF_ID_insnPC, IF_ID_placeholder_insn, 102 | ID_IF_next_insn_enabled, ID_IF_next_insn, ID_IF_busy, 103 | EX_ID_busy, 104 | ID_EX_insnPC, ID_EX_insn_id, 105 | ID_EX_alu_opcode, 106 | ID_EX_alu_src1, ID_EX_alu_src1_forward, ID_EX_alu_src1_forward_from, 107 | ID_EX_alu_src2, ID_EX_alu_src2_forward, ID_EX_alu_src2_forward_from, 108 | ID_EX_mem_opcode, 109 | ID_EX_mem_src2, ID_EX_mem_src2_forward, ID_EX_mem_src2_forward_from, 110 | writeback_insn_id, writeback_data, 111 | alu_forward_insn_id, alu_forward_data); 112 | 113 | wire MEM_EX_busy; 114 | wire [31:0] EX_MEM_insnPC; 115 | wire [2:0] EX_MEM_insn_id; 116 | wire [`MEM_OPCODE_WIDTH-1:0] EX_MEM_opcode; 117 | wire [31:0] EX_MEM_src1; 118 | wire [31:0] EX_MEM_src2; 119 | wire EX_MEM_src2_forward; 120 | wire [2:0] EX_MEM_src2_forward_from; 121 | 122 | pipeline_exec EX( 123 | CLK, RST, 124 | EX_ID_busy, 125 | ID_EX_insnPC, ID_EX_insn_id, 126 | ID_EX_alu_opcode, 127 | ID_EX_alu_src1, ID_EX_alu_src1_forward, ID_EX_alu_src1_forward_from, 128 | ID_EX_alu_src2, ID_EX_alu_src2_forward, ID_EX_alu_src2_forward_from, 129 | ID_EX_mem_opcode, 130 | ID_EX_mem_src2, ID_EX_mem_src2_forward, ID_EX_mem_src2_forward_from, 131 | MEM_EX_busy, 132 | EX_MEM_insnPC, EX_MEM_insn_id, 133 | EX_MEM_opcode, 134 | EX_MEM_src1, 135 | EX_MEM_src2, EX_MEM_src2_forward, EX_MEM_src2_forward_from, 136 | writeback_insn_id, writeback_data, 137 | alu_forward_insn_id, alu_forward_data); 138 | 139 | wire [31:0] MEM_WB_insnPC; 140 | wire [2:0] MEM_WB_insn_id; 141 | wire [31:0] MEM_WB_mem_output; 142 | 143 | wire [1:0] DCACHE_rw_flag; 144 | wire [31:0] DCACHE_addr; 145 | wire [31:0] DCACHE_read_data; 146 | wire [31:0] DCACHE_write_data; 147 | wire [4:0] DCACHE_write_mask; 148 | wire DCACHE_busy; 149 | wire DCACHE_done; 150 | 151 | assign ICACHE_flush_flag = DCACHE_rw_flag[1]; 152 | assign ICACHE_flush_addr = DCACHE_addr; 153 | 154 | cache DCACHE( 155 | CLK, RST, 156 | DCACHE_rw_flag, 157 | DCACHE_addr, 158 | DCACHE_read_data, 159 | DCACHE_write_data, DCACHE_write_mask, 160 | DCACHE_busy, DCACHE_done, 161 | 0, 32'b0, 162 | rw_flag[1:0], addr[31:0], read_data[31:0], write_data[31:0], write_mask[3:0], busy[0], done[0]); 163 | 164 | pipeline_mem MEM( 165 | CLK, RST, 166 | //rw_flag[1:0], addr[31:0], read_data[31:0], write_data[31:0], write_mask[3:0], busy[0], done[0], 167 | DCACHE_rw_flag, DCACHE_addr, DCACHE_read_data, DCACHE_write_data, DCACHE_write_mask, DCACHE_busy, DCACHE_done, 168 | MEM_EX_busy, 169 | EX_MEM_insnPC, EX_MEM_insn_id, 170 | EX_MEM_opcode, 171 | EX_MEM_src1, 172 | EX_MEM_src2, EX_MEM_src2_forward, EX_MEM_src2_forward_from, 173 | MEM_WB_insnPC, MEM_WB_insn_id, MEM_WB_mem_output, 174 | writeback_insn_id, writeback_data); 175 | 176 | assign alu_forward_insn_id = EX_MEM_opcode == `MEM_NOP ? EX_MEM_insn_id : 3'b111; 177 | assign alu_forward_data = EX_MEM_src1; 178 | assign writeback_insn_id = MEM_WB_insn_id; 179 | assign writeback_data = MEM_WB_mem_output; 180 | endmodule 181 | -------------------------------------------------------------------------------- /src/cpu/pipeline_mem.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2017/06/21 10:27:50 7 | // Design Name: 8 | // Module Name: pipeline_mem 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | `include "opcode.h" 23 | 24 | module pipeline_mem( 25 | input CLK, 26 | input RST, 27 | 28 | output reg [1:0] rw_flag, 29 | output [31:0] addr, 30 | input [31:0] read_data, 31 | output reg [31:0] write_data, 32 | output reg [3:0] write_mask, 33 | input mem_busy, 34 | input mem_done, 35 | 36 | output prev_busy, 37 | input [31:0] prev_insnPC, 38 | input [2:0] prev_insn_id, 39 | input [`MEM_OPCODE_WIDTH-1:0] mem_opcode, 40 | input [31:0] mem_src1, 41 | input [31:0] mem_src2, 42 | input mem_src2_forward, 43 | input [2:0] mem_src2_forward_from, 44 | 45 | output reg [31:0] next_insnPC, 46 | output reg [2:0] next_insn_id, 47 | output reg [31:0] mem_output, 48 | 49 | input [2:0] write_back_insn_id, 50 | input [31:0] write_back_data 51 | ); 52 | 53 | wire src2_ready; 54 | wire [31:0] src2; 55 | 56 | assign src2_ready = !mem_src2_forward || mem_src2_forward_from == write_back_insn_id; 57 | assign src2 = mem_src2_forward ? write_back_data : mem_src2; 58 | 59 | //reg busy; 60 | assign prev_busy = mem_busy || !src2_ready; 61 | 62 | assign addr = mem_src1 & ~(32'b11); 63 | //assign write_data = src2; 64 | 65 | reg unaligned_addr; 66 | always @(*) begin 67 | unaligned_addr = 0; 68 | write_mask = 0; 69 | write_data = 0; 70 | rw_flag = 0; 71 | if(!prev_busy) begin 72 | case(mem_opcode) 73 | `MEM_LB, `MEM_LBU, `MEM_LH, `MEM_LHU, `MEM_LW: begin 74 | if(((mem_opcode == `MEM_LH || mem_opcode == `MEM_LHU) && mem_src1[1:0] == 2'b11) 75 | || (mem_opcode == `MEM_LW && mem_src1[1:0] != 2'b00)) begin 76 | unaligned_addr = 1; 77 | rw_flag = 0; 78 | end else begin 79 | rw_flag = 1; 80 | write_mask = 0; 81 | write_data = 0; 82 | end 83 | end 84 | 85 | `MEM_SB: begin 86 | rw_flag = 2; 87 | if(mem_src1[1:0] == 2'b00) begin 88 | write_mask = 4'b0001; //Little Endian 89 | write_data = {24'b0, src2[7:0]}; 90 | end else if(mem_src1[1:0] == 2'b01) begin 91 | write_mask = 4'b0010; 92 | write_data = {16'b0, src2[7:0], 8'b0}; 93 | end else if(mem_src1[1:0] == 2'b10) begin 94 | write_mask = 4'b0100; 95 | write_data = {8'b0, src2[7:0], 16'b0}; 96 | end else begin 97 | write_mask = 4'b1000; 98 | write_data = {src2[7:0], 24'b0}; 99 | end 100 | end 101 | 102 | `MEM_SH: begin 103 | rw_flag = 2; 104 | if(mem_src1[1:0] == 2'b00) begin 105 | write_mask = 4'b0011; 106 | write_data = {16'b0, src2[15:0]}; 107 | end else if(mem_src1[1:0] == 2'b01) begin 108 | write_mask = 4'b0110; 109 | write_data = {8'b0, src2[15:0], 8'b0}; 110 | end else if(mem_src1[1:0] == 2'b10) begin 111 | write_mask = 4'b1100; 112 | write_data = {src2[15:0], 16'b0}; 113 | end else begin 114 | rw_flag = 0; 115 | unaligned_addr = 1; 116 | end 117 | end 118 | 119 | `MEM_SW: begin 120 | if(mem_src1[1:0] == 2'b00) begin 121 | rw_flag = 2; 122 | write_mask = 4'b1111; 123 | write_data = src2; 124 | end else begin 125 | rw_flag = 0; 126 | unaligned_addr = 1; 127 | end 128 | end 129 | endcase 130 | end 131 | end 132 | 133 | reg [31:0] buf_insnPC; 134 | reg [2:0] buf_insn_id; 135 | reg [31:0] buf_src1; 136 | reg [`MEM_OPCODE_WIDTH-1:0] buf_opcode; 137 | 138 | always @(posedge CLK or posedge RST) begin 139 | if(RST) begin 140 | buf_insnPC <= 0; 141 | buf_insn_id <= 3'b111; 142 | buf_src1 <= 0; 143 | buf_opcode <= 0; 144 | end else begin 145 | if(!prev_busy) begin 146 | buf_insnPC <= prev_insnPC; 147 | buf_insn_id <= prev_insn_id; 148 | buf_src1 <= mem_src1; 149 | buf_opcode <= mem_opcode; 150 | end 151 | end 152 | end 153 | 154 | function [7:0] get_byte; 155 | input [1:0] addr_suffix; 156 | input [31:0] data; 157 | 158 | case(addr_suffix) 159 | 2'b00: get_byte = data[7:0]; 160 | 2'b01: get_byte = data[15:8]; 161 | 2'b10: get_byte = data[23:16]; 162 | 2'b11: get_byte = data[31:24]; 163 | endcase 164 | endfunction 165 | 166 | function [15:0] get_half; 167 | input [1:0] addr_suffix; 168 | input [31:0] data; 169 | 170 | case(addr_suffix) 171 | 2'b00: get_half = data[15:0]; 172 | 2'b01: get_half = data[23:8]; 173 | 2'b10: get_half = data[31:16]; 174 | default: get_half = 16'b0; 175 | endcase 176 | endfunction 177 | 178 | function [31:0] sext_byte; 179 | input [7:0] in; 180 | sext_byte = {{24{in[7]}}, in}; 181 | endfunction 182 | 183 | function [31:0] sext_half; 184 | input [15:0] in; 185 | sext_half = {{16{in[15]}}, in}; 186 | endfunction 187 | 188 | always @(*) begin 189 | if(buf_opcode == `MEM_NOP) begin 190 | next_insnPC = buf_insnPC; 191 | next_insn_id = buf_insn_id; 192 | mem_output = buf_src1; 193 | end else if(mem_done) begin 194 | next_insnPC = buf_insnPC; 195 | next_insn_id = buf_insn_id; 196 | case(buf_opcode) 197 | `MEM_LB: mem_output = sext_byte(get_byte(buf_src1[1:0], read_data)); 198 | `MEM_LBU: mem_output = {24'b0, get_byte(buf_src1[1:0], read_data)}; 199 | `MEM_LH: mem_output = sext_half(get_half(buf_src1[1:0], read_data)); 200 | `MEM_LHU: mem_output = {16'b0, get_half(buf_src1[1:0], read_data)}; 201 | `MEM_LW: mem_output = read_data; 202 | default: mem_output = 0; 203 | endcase 204 | end else begin 205 | next_insnPC = 0; 206 | next_insn_id = 3'b111; 207 | mem_output = 0; 208 | end 209 | end 210 | 211 | /*always @(negedge CLK or posedge RST) begin 212 | if(RST) begin 213 | //busy <= 0; 214 | next_insnPC <= 0; 215 | next_insn_id <= 3'b111; 216 | mem_output <= 0; 217 | end else begin 218 | //busy <= 0; 219 | 220 | end 221 | end*/ 222 | endmodule 223 | -------------------------------------------------------------------------------- /src/cpu/memory_controller.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2017/06/17 16:55:33 7 | // Design Name: 8 | // Module Name: memory_controller 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | `include "common.h" 23 | 24 | module memory_controller 25 | #( 26 | parameter PORT_COUNT = 2, 27 | parameter DATA_WIDTH_BYTE = 4, 28 | parameter ADDR_WIDTH_BYTE = 4 29 | ) 30 | ( 31 | CLK, RST, 32 | 33 | send_flag, send_data, send_length, 34 | recv_flag, recv_data, recv_length, 35 | 36 | sendable, receivable, 37 | 38 | rw_flag_, //1 for read, 2 for write 39 | addr_, 40 | read_data_, write_data_, write_mask_, 41 | busy, done 42 | ); 43 | 44 | // read request packet format: (MSB -> LSB) (length = 4 byte) 45 | // 0 addr 46 | // write request packet format: 47 | // 1 length(in byte) addr data 48 | // read response packet format: 49 | // data 50 | 51 | localparam DATA_WIDTH = 8 * DATA_WIDTH_BYTE; 52 | localparam ADDR_WIDTH = 8 * ADDR_WIDTH_BYTE; 53 | localparam LENGTH_WIDTH = `CLOG2(DATA_WIDTH_BYTE) + 1; 54 | localparam PORT_COUNT_BIT = `CLOG2(PORT_COUNT); 55 | localparam SEND_BYTE = DATA_WIDTH_BYTE + ADDR_WIDTH_BYTE + DATA_WIDTH_BYTE / 8 + 1; 56 | 57 | input CLK, RST; 58 | 59 | output reg send_flag; 60 | output reg [SEND_BYTE*8-1:0] send_data; 61 | output reg [4:0] send_length; 62 | 63 | output reg recv_flag; 64 | input [SEND_BYTE*8-1:0] recv_data; 65 | input [4:0] recv_length; 66 | 67 | input sendable, receivable; 68 | 69 | input [PORT_COUNT*2-1:0] rw_flag_; 70 | input [PORT_COUNT * ADDR_WIDTH-1:0] addr_; 71 | //input [PORT_COUNT * LENGTH_WIDTH-1:0] length_; 72 | output [PORT_COUNT * DATA_WIDTH-1:0] read_data_; 73 | input [PORT_COUNT * DATA_WIDTH-1:0] write_data_; 74 | input [PORT_COUNT * DATA_WIDTH_BYTE-1:0] write_mask_; 75 | output reg [PORT_COUNT-1:0] busy; 76 | output reg [PORT_COUNT-1:0] done; 77 | 78 | wire [1:0] rw_flag[PORT_COUNT-1:0]; 79 | wire [ADDR_WIDTH-1:0] addr[PORT_COUNT-1:0]; 80 | //wire [LENGTH_WIDTH-1:0] length[PORT_COUNT-1:0]; 81 | reg [DATA_WIDTH-1:0] read_data[PORT_COUNT-1:0]; 82 | wire [DATA_WIDTH-1:0] write_data[PORT_COUNT-1:0]; 83 | wire [DATA_WIDTH_BYTE-1:0] write_mask[PORT_COUNT-1:0]; 84 | 85 | genvar j; 86 | generate 87 | for(j=0; j max_priority[i-1] ? priority[i] : max_priority[i-1]; 89 | // assign current_read[i] = !write_buffer_empty[i] && 90 | // (priority[i] > max_priority[i-1] || (priority[i] == max_priority[i-1] && skip_read[i] > skip_read[current_read[i-1]])) ? i : current_read[i-1]; 91 | // end 92 | // endgenerate 93 | 94 | reg [4:0] max_priority_array[CHANNEL-1:0]; 95 | reg [CHANNEL_BIT-1:0] current_read_array[CHANNEL-1:0]; 96 | //wire [CHANNEL_BIT-1:0] current_read; 97 | 98 | assign write_buffer_select = current_read_array[CHANNEL-1]; 99 | 100 | integer i; 101 | always @(negedge CLK or posedge RST) begin 102 | if(RST) begin 103 | for(i=0; i < CHANNEL; i=i+1) begin 104 | max_priority_array[i] <= 0; 105 | current_read_array[i] <= 0; 106 | end 107 | end else begin 108 | max_priority_array[0] <= write_buffer_empty[0] ? 0 : priority[0]; 109 | current_read_array[0] <= 0; 110 | for(i=1; i < CHANNEL; i=i+1) begin 111 | if(!write_buffer_empty[i] && 112 | (priority[i] > max_priority_array[i-1] || (priority[i] == max_priority_array[i-1] && skip_read[i] > skip_read[current_read_array[i-1]]))) begin 113 | max_priority_array[i] <= priority[i]; 114 | current_read_array[i] <= i; 115 | end else begin 116 | max_priority_array[i] <= max_priority_array[i-1]; 117 | current_read_array[i] <= current_read_array[i-1]; 118 | end 119 | end 120 | end 121 | end 122 | 123 | localparam STATUS_IDLE = 0; 124 | //localparam STATUS_HEAD = 1; 125 | localparam STATUS_CHANNEL = 1; 126 | localparam STATUS_LENGTH = 2; 127 | localparam STATUS_DATA = 4; 128 | localparam STATUS_END = 8; 129 | reg [3:0] send_status; 130 | reg [8:0] send_bit; 131 | reg [4:0] packet_id; 132 | 133 | reg [CHANNEL_BIT-1:0] send_channel; 134 | 135 | wire [4:0] length; 136 | assign length = write_buffer_read_data_buf[WIDTH-1:WIDTH-5]; 137 | 138 | wire [MESSAGE_BIT+6:0] data; 139 | assign data[MESSAGE_BIT-1:0] = write_buffer_read_data_buf[MESSAGE_BIT-1:0]; 140 | assign data[MESSAGE_BIT+6:MESSAGE_BIT] = 0; 141 | 142 | wire [4:0] next_packet_id; 143 | assign next_packet_id = packet_id + 1; 144 | 145 | integer j; 146 | always @(posedge CLK or posedge RST) begin 147 | send_flag <= 0; 148 | write_buffer_read_flag <= 0; 149 | if(RST) begin 150 | write_buffer_read_data_buf <= 0; 151 | send_channel <= 0; 152 | send_data <= 0; 153 | send_status <= STATUS_IDLE; 154 | send_bit <= 0; 155 | packet_id <= 0; 156 | for(j=0; j < CHANNEL; j=j+1) begin 157 | priority[j] <= CHANNEL_PRIORITY[j*5 +: 5]; 158 | skip_read[j] <= 0; 159 | end 160 | end else if(sendable) begin 161 | case(send_status) 162 | STATUS_IDLE: begin 163 | if(!write_buffer_empty[write_buffer_select]) begin 164 | write_buffer_read_data_buf <= write_buffer_read_data; 165 | write_buffer_read_flag <= 1; 166 | send_bit <= 0; 167 | send_channel <= write_buffer_select; 168 | 169 | skip_read[write_buffer_select] <= 0; 170 | priority[write_buffer_select] <= CHANNEL_PRIORITY[write_buffer_select*5 +: 5]; 171 | for(j=0; j < CHANNEL; j=j+1) 172 | if(j != write_buffer_select && !write_buffer_empty[j]) begin 173 | if(skip_read[j] == 7) begin 174 | skip_read[j] <= 0; 175 | if(priority[j][3:0] != 4'hf) 176 | priority[j] <= priority[j] + 1; 177 | end else 178 | skip_read[j] <= skip_read[j] + 1; 179 | end 180 | 181 | packet_id <= next_packet_id; 182 | 183 | if(PACKET_SIZE-3-5 > 0) 184 | send_data <= {3'b100, {(PACKET_SIZE-3-5){1'b0}}, next_packet_id}; 185 | else 186 | send_data <= {3'b100, next_packet_id}; 187 | send_flag <= 1; 188 | send_status <= STATUS_CHANNEL; 189 | end 190 | end 191 | 192 | STATUS_CHANNEL: begin 193 | if(PACKET_SIZE-3-CHANNEL_BIT > 0) 194 | send_data <= {3'b101, {(PACKET_SIZE-3-CHANNEL_BIT){1'b0}}, send_channel}; 195 | else 196 | send_data <= {3'b101, send_channel}; 197 | send_flag <= 1; 198 | send_status <= STATUS_LENGTH; 199 | end 200 | 201 | STATUS_LENGTH: begin 202 | if(PACKET_SIZE-3-5 > 0) 203 | send_data <= {3'b110, {(PACKET_SIZE-3-5){1'b0}}, length}; 204 | else 205 | send_data <= {3'b110, length}; 206 | send_flag <= 1; 207 | send_status <= STATUS_DATA; 208 | end 209 | 210 | STATUS_DATA: begin 211 | send_data <= {1'b0, data[send_bit +: PACKET_SIZE-1]}; 212 | send_flag <= 1; 213 | send_bit <= send_bit + PACKET_SIZE - 1; 214 | if(send_bit + PACKET_SIZE - 1 >= (length << 3)) 215 | send_status <= STATUS_END; 216 | end 217 | 218 | STATUS_END: begin 219 | if(PACKET_SIZE-3-5 > 0) 220 | send_data <= {3'b111, {(PACKET_SIZE-3-5){1'b0}}, packet_id}; 221 | else 222 | send_data <= {3'b111, packet_id}; 223 | send_flag <= 1; 224 | send_status <= STATUS_IDLE; 225 | end 226 | endcase 227 | end 228 | end 229 | 230 | reg [4:0] recv_status; 231 | reg [8:0] recv_bit; 232 | reg [4:0] recv_packet_id; 233 | reg [4:0] recv_length; 234 | 235 | always @(posedge CLK or posedge RST) begin 236 | read_buffer_write_flag <= 0; 237 | recv_flag <= 0; 238 | if(RST) begin 239 | recv_status <= STATUS_IDLE; 240 | recv_bit <= 0; 241 | recv_packet_id <= 0; 242 | recv_length <= 0; 243 | read_buffer_select <= 0; 244 | read_buffer_write_data <= 0; 245 | end else begin 246 | if(receivable) begin 247 | recv_flag <= 1; 248 | case(recv_status) 249 | STATUS_IDLE: begin 250 | if(recv_data[PACKET_SIZE-1:PACKET_SIZE-3] == 3'b100) begin 251 | recv_packet_id <= recv_data[4:0]; 252 | recv_bit <= 0; 253 | recv_length <= 0; 254 | recv_status <= STATUS_CHANNEL; 255 | end 256 | end 257 | 258 | STATUS_CHANNEL: begin 259 | if(recv_data[PACKET_SIZE-1:PACKET_SIZE-3] == 3'b101) begin 260 | read_buffer_select <= recv_data[CHANNEL_BIT-1:0]; 261 | recv_status <= STATUS_LENGTH; 262 | end else 263 | recv_status <= STATUS_IDLE; 264 | end 265 | 266 | STATUS_LENGTH: begin 267 | if(recv_data[PACKET_SIZE-1:PACKET_SIZE-3] == 3'b110) begin 268 | recv_length <= recv_data[4:0]; 269 | recv_status <= STATUS_DATA; 270 | end else 271 | recv_status <= STATUS_IDLE; 272 | end 273 | 274 | STATUS_DATA: begin 275 | if(recv_data[PACKET_SIZE-1] == 0) begin 276 | read_buffer_write_data[recv_bit +: PACKET_SIZE-1] <= recv_data[PACKET_SIZE-2:0]; 277 | recv_bit <= recv_bit + PACKET_SIZE - 1; 278 | if(recv_bit + PACKET_SIZE - 1 >= (recv_length << 3)) 279 | recv_status <= STATUS_END; 280 | end else 281 | recv_status <= STATUS_IDLE; 282 | end 283 | 284 | STATUS_END: begin 285 | if(recv_data[PACKET_SIZE-1:PACKET_SIZE-3] == 3'b111) 286 | if(recv_packet_id == recv_data[4:0] && !read_buffer_full) begin 287 | read_buffer_write_data[WIDTH-1:WIDTH-5] <= recv_length; 288 | read_buffer_write_flag <= 1; 289 | end 290 | recv_status <= STATUS_IDLE; 291 | end 292 | endcase 293 | end 294 | end 295 | end 296 | endmodule 297 | -------------------------------------------------------------------------------- /src/cpu/cache.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2017/06/24 14:11:45 7 | // Design Name: 8 | // Module Name: cache 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | `include "common.h" 23 | 24 | module cacheram 25 | #( 26 | parameter ADDR_WIDTH = 16, 27 | parameter DATA_BYTE_WIDTH = 4 28 | ) 29 | ( 30 | input CLK, 31 | input RST, 32 | 33 | output reg [8*DATA_BYTE_WIDTH-1:0] read_data, 34 | input [ADDR_WIDTH-1:0] read_addr, 35 | input read_flag, 36 | input [8*DATA_BYTE_WIDTH-1:0] write_data, 37 | input [ADDR_WIDTH-1:0] write_addr, 38 | input [DATA_BYTE_WIDTH-1:0] write_mask, 39 | input write_flag 40 | ); 41 | 42 | reg [8*DATA_BYTE_WIDTH-1:0] data[(1<= lru_tmp[i*2+1] ? lru_tmp[i*2] : lru_tmp[i*2+1]; 165 | assign mru_tmp[i] = mru_tmp[i*2] < mru_tmp[i*2+1] ? mru_tmp[i*2] : mru_tmp[i*2+1]; 166 | assign lru_id_tmp[i] = lru_tmp[i*2] >= lru_tmp[i*2+1] ? lru_id_tmp[i*2] : lru_id_tmp[i*2+1]; 167 | assign mru_id_tmp[i] = mru_tmp[i*2] < mru_tmp[i*2+1] ? mru_id_tmp[i*2] : mru_id_tmp[i*2+1]; 168 | end 169 | endgenerate 170 | 171 | wire [SET_SELECT_BIT-1:0] lru_id, mru_id; 172 | 173 | assign lru_id = lru_id_tmp[1]; 174 | assign mru_id = mru_id_tmp[1]; 175 | 176 | task use_cache; 177 | input [NASSOC-1:0] cache_id; 178 | 179 | if(cache_id != mru_id) begin 180 | recent_use_counter[addr_index] <= recent_use_counter[addr_index] + 1; 181 | recuse[cache_id][addr_index] <= recent_use_counter[addr_index] + 1; 182 | end else if(recuse[cache_id][addr_index] != recent_use_counter[addr_index]) 183 | $display("Assertion Failed: recuse[cache_id][addr_index] == recent_use_counter"); 184 | endtask 185 | 186 | localparam STATE_IDLE = 0; 187 | localparam STATE_WAIT_FOR_READ_PHASE_1 = 1; //Before Critical Word Reach 188 | localparam STATE_WAIT_FOR_READ_PHASE_2 = 2; //After Critical Word Reach 189 | localparam STATE_WAIT_FOR_WRITE = 4; 190 | 191 | reg [2:0] state; 192 | reg [2:0] next_state; 193 | 194 | reg [SET_SELECT_BIT-1:0] current_cache; 195 | reg [TAG_BIT-1:0] current_tag; 196 | reg [INDEX_BIT-1:0] current_block; 197 | reg [WORD_SELECT_BIT-1:0] current_word; 198 | reg [WORD_SELECT_BIT-1:0] critical_word; 199 | 200 | reg signed [SET_SELECT_BIT:0] write_cache; //set to -1 if not write 201 | reg [INDEX_BIT-1:0] write_block; 202 | reg [WORD_SELECT_BIT-1:0] write_word; 203 | reg [31:0] write_data; 204 | //reg write_flag; 205 | reg [3:0] write_mask; 206 | 207 | reg signed [SET_SELECT_BIT:0] read_cache; //set to -1 if not read 208 | reg [INDEX_BIT-1:0] read_block; 209 | reg [WORD_SELECT_BIT-1:0] read_word; 210 | //reg read_flag; 211 | 212 | reg [SET_SELECT_BIT-1:0] valid_cache; 213 | reg [INDEX_BIT-1:0] valid_block; 214 | reg valid_flag; 215 | reg [TAG_BIT-1:0] valid_tag; 216 | 217 | reg next_done; 218 | reg [NASSOC-1:0] next_current_cache; 219 | reg [TAG_BIT-1:0] next_current_tag; 220 | reg [INDEX_BIT-1:0] next_current_block; 221 | reg [WORD_SELECT_BIT-1:0] next_current_word; 222 | reg [WORD_SELECT_BIT-1:0] next_critical_word; 223 | 224 | wire [31:0] RAM_read_data[NASSOC-1:0]; 225 | reg [SET_SELECT_BIT-1:0] RAM_read_select; 226 | 227 | assign read_data = RAM_read_data[RAM_read_select]; 228 | 229 | generate 230 | for(i=0; i remainder) begin 216 | quotient[divide_currentbit] = 1; 217 | remainder = remainder - tmp; 218 | end else 219 | quotient[divide_currentbit] = 0; 220 | divide_currentbit = divide_currentbit - 1; 221 | end 222 | endtask 223 | 224 | task divide; 225 | input [31:0] dividend; 226 | input [31:0] divisor; 227 | input sign; 228 | 229 | if(dividend == last_dividend && divisor == last_divisor && sign == last_divide_sign) begin 230 | if(divide_currentbit != 31) 231 | divide_bit(); 232 | else if(!divide_finished) begin 233 | if(sign) begin 234 | if($signed(last_dividend) < 0) 235 | remainder = -remainder; 236 | if(($signed(last_dividend) < 0) ^ ($signed(last_divisor) < 0)) 237 | quotient = -quotient; 238 | end 239 | divide_finished = 1; 240 | end 241 | end else begin 242 | last_dividend = dividend; 243 | last_divisor = divisor; 244 | last_divide_sign = sign; 245 | 246 | if(sign) begin 247 | if($signed(dividend) < 0) 248 | remainder = -dividend; 249 | else 250 | remainder = dividend; 251 | if($signed(divisor) < 0) 252 | divisor_work = -divisor; 253 | else 254 | divisor_work = divisor; 255 | end else begin 256 | remainder = dividend; 257 | divisor_work = divisor; 258 | end 259 | 260 | divide_currentbit = 31; 261 | divide_bit(); 262 | end 263 | endtask 264 | 265 | function divide_done; 266 | input [31:0] dividend; 267 | input [31:0] divisor; 268 | input sign; 269 | divide_done = dividend == last_dividend && divisor == last_divisor && sign == last_divide_sign && divide_finished; 270 | endfunction 271 | 272 | reg [31:0] last_mult1, last_mult2, last_sign; 273 | reg [63:0] partial_result[4:0]; 274 | reg [63:0] multiply_result; 275 | reg mult_done; 276 | 277 | task multiply; 278 | input [31:0] mult1; 279 | input [31:0] mult2; 280 | input sign; 281 | if(mult1 == last_mult1 && mult2 == last_mult2 && sign == last_sign) begin 282 | if(!mult_done) begin 283 | multiply_result = 284 | partial_result[0] 285 | + partial_result[1] 286 | + partial_result[2] 287 | + partial_result[3] 288 | + partial_result[4]; 289 | mult_done = 1; 290 | end 291 | end else begin 292 | last_mult1 = mult1; 293 | last_mult2 = mult2; 294 | last_sign = sign; 295 | mult_done = 0; 296 | partial_result[0] = last_mult1[15:0] * last_mult2[15:0]; 297 | partial_result[1] = last_mult1[31:16] * last_mult2[15:0] << 16; 298 | partial_result[2] = last_mult1[15:0] * last_mult2[31:16] << 16; 299 | partial_result[3] = last_mult1[31:16] * last_mult2[31:16] << 32; 300 | if(sign) begin 301 | partial_result[4] = 302 | (last_mult1[31] ? ((-last_mult2[31:0]) << 32) : 0) 303 | + (last_mult2[31] ? ((-last_mult1[31:0]) << 32) : 0); 304 | end else 305 | partial_result[4] = 0; 306 | end 307 | endtask 308 | 309 | function multiply_done; 310 | input [31:0] mult1; 311 | input [31:0] mult2; 312 | input sign; 313 | multiply_done = (mult1 == last_mult1 & mult2 == last_mult2) & (sign == last_sign & mult_done); 314 | endfunction 315 | 316 | task set_busy; 317 | input [31:0] src1; 318 | input [31:0] src2; 319 | input [`ALU_OPCODE_WIDTH-1:0] opcode; 320 | begin 321 | case(alu_opcode) 322 | `ALU_MULTL, `ALU_MULTH: busy <= !multiply_done(src1, src2, 1); 323 | `ALU_MULTLU, `ALU_MULTHU: busy <= !multiply_done(src1, src2, 0); 324 | `ALU_DIV, `ALU_MOD: busy <= !divide_done(src1, src2, 1); 325 | `ALU_DIVU, `ALU_MODU: busy <= !divide_done(src1, src2, 0); 326 | endcase 327 | end 328 | endtask 329 | 330 | always @(posedge CLK or posedge RST) begin 331 | if(RST) begin 332 | busy <= 0; 333 | end else begin 334 | busy <= 0; 335 | if(!prev_busy) begin 336 | set_busy(alu_src1, alu_src2, alu_opcode); 337 | end else if(busy) begin 338 | set_busy(buf_src1, buf_src2, buf_opcode); 339 | end 340 | end 341 | end 342 | 343 | integer i; 344 | always @(negedge CLK or posedge RST) begin 345 | if(RST) begin 346 | //busy <= 0; 347 | next_insnPC <= 0; 348 | next_insn_id <= 3'b111; 349 | mem_opcode <= 0; 350 | mem_src1 <= 0; 351 | mem_src2 <= 0; 352 | mem_src2_forward <= 0; 353 | mem_src2_forward_from <= 0; 354 | last_dividend <= 0; 355 | last_divisor <= 0; 356 | last_divide_sign <= 0; 357 | divisor_work <= 0; 358 | quotient <= 0; 359 | remainder <= 0; 360 | divide_currentbit <= 0; 361 | divide_finished <= 0; 362 | last_mult1 <= 0; 363 | last_mult2 <= 0; 364 | last_sign <= 0; 365 | multiply_result <= 0; 366 | mult_done <= 0; 367 | for(i=0; i<5; i=i+1) 368 | partial_result[i] <= 0; 369 | end else begin 370 | //busy <= 0; 371 | 372 | next_insnPC <= buf_insnPC; 373 | next_insn_id <= buf_insn_id; 374 | mem_opcode <= buf_mem_opcode; 375 | mem_src2 <= buf_mem_src2; 376 | if(mem_src2_forward != 0 && mem_src2_forward_from != 1) 377 | $display("DEBUG! FORWARD=%d", mem_src2_forward); 378 | mem_src2_forward <= buf_mem_src2_forward[0]; 379 | mem_src2_forward_from <= buf_mem_src2_forward_from; 380 | 381 | case(buf_opcode) 382 | `ALU_NOP: mem_src1 <= buf_src1; 383 | `ALU_ADD: mem_src1 <= buf_src1 + buf_src2; 384 | `ALU_ADDU: mem_src1 <= buf_src1 + buf_src2; 385 | `ALU_SUB: mem_src1 <= buf_src1 - buf_src2; 386 | `ALU_SUBU: mem_src1 <= buf_src1 - buf_src2; 387 | `ALU_MULTL: begin 388 | if(multiply_done(buf_src1, buf_src2, 1)) 389 | mem_src1 <= multiply_result[31:0]; 390 | else begin 391 | multiply(buf_src1, buf_src2, 1); 392 | //set_busy(); 393 | end 394 | end 395 | `ALU_MULTH: begin 396 | if(multiply_done(buf_src1, buf_src2, 1)) 397 | mem_src1 <= multiply_result[63:32]; 398 | else begin 399 | multiply(buf_src1, buf_src2, 1); 400 | //set_busy(); 401 | end 402 | end 403 | `ALU_MULTLU: begin 404 | if(multiply_done(buf_src1, buf_src2, 0)) 405 | mem_src1 <= multiply_result[31:0]; 406 | else begin 407 | multiply(buf_src1, buf_src2, 0); 408 | //set_busy(); 409 | end 410 | end 411 | `ALU_MULTHU: begin 412 | if(multiply_done(buf_src1, buf_src2, 0)) 413 | mem_src1 <= multiply_result[63:32]; 414 | else begin 415 | multiply(buf_src1, buf_src2, 0); 416 | //set_busy(); 417 | end 418 | end 419 | `ALU_DIV, `ALU_MOD: begin 420 | if(divide_done(buf_src1, buf_src2, 1)) 421 | mem_src1 <= buf_opcode == `ALU_DIV ? quotient : remainder; 422 | else begin 423 | //set_busy(); 424 | divide(buf_src1, buf_src2, 1); 425 | end 426 | end 427 | `ALU_DIVU, `ALU_MODU: begin 428 | if(divide_done(buf_src1, buf_src2, 0)) 429 | mem_src1 <= buf_opcode == `ALU_DIVU ? quotient : remainder; 430 | else begin 431 | //set_busy(); 432 | divide(buf_src1, buf_src2, 0); 433 | end 434 | end 435 | `ALU_AND: mem_src1 <= buf_src1 & buf_src2; 436 | `ALU_OR: mem_src1 <= buf_src1 | buf_src2; 437 | `ALU_NOR: mem_src1 <= ~(buf_src1 | buf_src2); 438 | `ALU_XOR: mem_src1 <= buf_src1 ^ buf_src2; 439 | `ALU_SLL: mem_src1 <= buf_src1 << buf_src2[4:0]; 440 | `ALU_SRL: mem_src1 <= buf_src1 >> buf_src2[4:0]; 441 | `ALU_SRA: mem_src1 <= $signed(buf_src1) >>> buf_src2[4:0]; 442 | `ALU_ROR: mem_src1 <= (buf_src1 >> buf_src2[4:0]) | (buf_src1 << (32-buf_src2[4:0])); 443 | `ALU_SEQ: mem_src1 <= buf_src1 == buf_src2 ? 32'b1 : 32'b0; 444 | `ALU_SLT: mem_src1 <= $signed(buf_src1) < $signed(buf_src2) ? 32'b1 : 32'b0; 445 | `ALU_SLTU: mem_src1 <= buf_src1 < buf_src2 ? 32'b1 : 32'b0; 446 | default: mem_src1 <= 0; 447 | endcase 448 | end 449 | end 450 | */ 451 | endmodule 452 | -------------------------------------------------------------------------------- /src/cpu/pipeline_decode.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2017/06/18 20:31:47 7 | // Design Name: 8 | // Module Name: pipeline_decode 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | `include "opcode.h" 23 | 24 | module pipeline_decode( 25 | input CLK, 26 | input RST, 27 | 28 | input [31:0] prev_insn, 29 | input [31:0] prev_insnPC, 30 | input prev_placeholder_insn, //indicates that current instruction is a placeholder(NOP) and prev_next_insn should not be changed 31 | output reg prev_next_insn_enabled, 32 | output reg [31:0] prev_next_insn, 33 | output prev_busy, 34 | 35 | input next_busy, 36 | output reg [31:0] next_insnPC, //may be useful when handle exceptions 37 | output reg [2:0] next_insn_id, //may be useful when forward data 38 | output reg [`ALU_OPCODE_WIDTH-1:0] alu_opcode, 39 | output reg [31:0] alu_src1, 40 | output reg alu_src1_forward, //1 for forward from ALU, 2 for forward from MEM 41 | output reg [2:0] alu_src1_forward_from, 42 | output reg [31:0] alu_src2, 43 | output reg alu_src2_forward, 44 | output reg [2:0] alu_src2_forward_from, 45 | output reg [`MEM_OPCODE_WIDTH-1:0] mem_opcode, 46 | output reg [31:0] mem_src2, 47 | output reg mem_src2_forward, 48 | output reg [2:0] mem_src2_forward_from, 49 | 50 | input [2:0] writeback_insn_id, 51 | input [31:0] writeback_data, 52 | 53 | input [2:0] alu_forward_insn_id, 54 | input [31:0] alu_forward_data 55 | ); 56 | 57 | localparam OPCD_SPECIAL = 6'h00; 58 | localparam OPCD_REGIMM = 6'h01; 59 | localparam OPCD_BEQ = 6'h04; 60 | localparam OPCD_BNE = 6'h05; 61 | localparam OPCD_POP06 = 6'h06; 62 | localparam OPCD_POP07 = 6'h07; 63 | //localparam OPCD_ADDI = 6'h08; 64 | localparam OPCD_POP10 = 6'h08; 65 | localparam OPCD_ADDIU = 6'h09; 66 | localparam OPCD_SLTI = 6'h0A; 67 | localparam OPCD_SLTIU = 6'h0B; 68 | localparam OPCD_ANDI = 6'h0C; 69 | localparam OPCD_ORI = 6'h0D; 70 | localparam OPCD_XORI = 6'h0E; 71 | localparam OPCD_AUI = 6'h0F; 72 | localparam OPCD_POP26 = 6'h16; 73 | localparam OPCD_POP27 = 6'h17; 74 | localparam OPCD_POP30 = 6'h18; 75 | localparam OPCD_LB = 6'h20; 76 | localparam OPCD_LH = 6'h21; 77 | localparam OPCD_LW = 6'h23; 78 | localparam OPCD_LBU = 6'h24; 79 | localparam OPCD_LHU = 6'h25; 80 | localparam OPCD_SB = 6'h28; 81 | localparam OPCD_SH = 6'h29; 82 | localparam OPCD_SW = 6'h2B; 83 | localparam OPCD_LWC1 = 6'h31; 84 | localparam OPCD_SWC1 = 6'h39; 85 | localparam OPCD_J = 6'h02; 86 | localparam OPCD_JAL = 6'h03; 87 | localparam OPCD_BC = 6'h32; 88 | localparam OPCD_POP66 = 6'h36; 89 | localparam OPCD_BALC = 6'h3A; 90 | localparam OPCD_POP76 = 6'h3E; 91 | 92 | localparam OPFUNC_SLL = 6'h00; 93 | localparam OPFUNC_SRL = 6'h02; 94 | localparam OPFUNC_SRA = 6'h03; 95 | localparam OPFUNC_SLLV = 6'h04; 96 | localparam OPFUNC_SRLV = 6'h06; 97 | localparam OPFUNC_SRAV = 6'h07; 98 | localparam OPFUNC_JR = 6'h08; 99 | localparam OPFUNC_JALR = 6'h09; 100 | localparam OPFUNC_SYSCALL = 6'h0C; 101 | localparam OPFUNC_BREAK = 6'h0D; 102 | localparam OPFUNC_SOP30 = 6'h18; //mul muh 103 | localparam OPFUNC_SOP31 = 6'h19; //mulu mulu 104 | localparam OPFUNC_SOP32 = 6'h1A; //div mod 105 | localparam OPFUNC_SOP33 = 6'h1B; //divu modu 106 | localparam OPFUNC_ADD = 6'h20; 107 | localparam OPFUNC_ADDU = 6'h21; 108 | localparam OPFUNC_SUB = 6'h22; 109 | localparam OPFUNC_SUBU = 6'h23; 110 | localparam OPFUNC_AND = 6'h24; 111 | localparam OPFUNC_OR = 6'h25; 112 | localparam OPFUNC_XOR = 6'h26; 113 | localparam OPFUNC_NOR = 6'h27; 114 | localparam OPFUNC_SLT = 6'h2A; 115 | localparam OPFUNC_SLTU = 6'h2B; 116 | 117 | 118 | 119 | reg [31:0] insn; 120 | reg [31:0] insnPC; 121 | reg [2:0] insn_id; //insn_id[2] must be 0 122 | reg [4:0] insn_write_reg[7:0]; //register to which the instruction write back 123 | //reg [1:0] insn_data_stage[7:0]; 124 | reg insn_data_overrided[7:0]; 125 | 126 | reg [31:0] reg_file[31:1]; 127 | wire [31:0] GPR[31:0]; 128 | 129 | reg reg_lock[31:0]; 130 | reg [2:0] reg_lock_by[31:0]; //the id of last instruction that locks the register 131 | //reg [1:0] reg_data_stage[31:0]; //[0] for can be forwarded from MEMORY, [1] for can be forwardedd from ALU 132 | //reg reg_readable[31:0]; 133 | reg [4:0] next_insn_write_reg; 134 | //reg [1:0] next_insn_data_stage; 135 | 136 | reg [4:0] next_insn_write_reg_pending; 137 | //reg [1:0] next_insn_data_stage_pending; 138 | 139 | genvar j; 140 | generate 141 | for(j=1; j<32; j=j+1) 142 | assign GPR[j] = reg_file[j]; 143 | endgenerate 144 | assign GPR[0] = 0; 145 | 146 | 147 | 148 | reg busy; 149 | assign prev_busy = busy || next_busy; 150 | 151 | wire writeback_flag = /*insn_data_stage[writeback_insn_id][0] &*/ !insn_data_overrided[writeback_insn_id]; 152 | wire alu_forward_flag = /*insn_data_stage[alu_forward_insn_id][1] &*/ !insn_data_overrided[alu_forward_insn_id]; 153 | 154 | wire [4:0] writeback_reg = insn_write_reg[writeback_insn_id]; 155 | //writeback_flag ? : 0; 156 | wire [4:0] alu_forward_reg = insn_write_reg[alu_forward_insn_id]; 157 | //alu_forward_flag ? : 0; 158 | 159 | integer i; 160 | /*always @(posedge CLK or posedge RST) begin 161 | if(RST) begin 162 | 163 | end else begin 164 | 165 | end 166 | end*/ 167 | 168 | task write_register; 169 | input [4:0] regid; 170 | //input [1:0] stage; 171 | begin 172 | //if(regid != 0) begin 173 | //next_insn_data_stage_pending <= stage; 174 | next_insn_write_reg_pending <= regid; 175 | //end 176 | end 177 | endtask 178 | 179 | reg drop_next_insn; 180 | 181 | localparam NEVER = 0; 182 | localparam ALWAYS = 1; 183 | localparam RS_EQ_RT = 2; 184 | localparam RS_NE_RT = 3; 185 | localparam RS_GTU_RT = 4; 186 | localparam RS_LTU_RT = 5; 187 | localparam RS_GEU_RT = 6; 188 | localparam RS_LEU_RT = 7; 189 | localparam RS_GT_RT = 8; 190 | localparam RS_LT_RT = 9; 191 | localparam RS_GE_RT = 10; 192 | localparam RS_LE_RT = 11; 193 | localparam RS_EQ_ZERO = 12; 194 | localparam RS_NE_ZERO = 13; 195 | localparam RS_GT_ZERO = 14; 196 | localparam RS_LT_ZERO = 15; 197 | localparam RS_GE_ZERO = 16; 198 | localparam RS_LE_ZERO = 17; 199 | localparam RT_EQ_ZERO = 18; 200 | localparam RT_NE_ZERO = 19; 201 | localparam RT_GT_ZERO = 20; 202 | localparam RT_LT_ZERO = 21; 203 | localparam RT_GE_ZERO = 22; 204 | localparam RT_LE_ZERO = 23; 205 | 206 | reg [23:0] jump_cond; 207 | reg [6:0] jump_cond_basic; 208 | reg [4:0] jump_cond_id; 209 | 210 | localparam JUMP_J = 0; 211 | localparam JUMP_BC = 1; 212 | localparam JUMP_BALC = 2; 213 | localparam JUMP_BC_LONG = 4; 214 | localparam JUMP_J_LONG = 8; 215 | localparam JUMP_BC_VERY_LONG = 16; 216 | localparam JUMP_GPR_RS = 32; 217 | reg [5:0] jump_type; 218 | 219 | reg [3:0] POP_insn_type; //8 for register busy 220 | reg [31:0] Branch_target; 221 | reg [31:0] BC_target; 222 | reg [31:0] BC_long_target; //21 bit addr 223 | reg [31:0] J_target; //26 bit addr 224 | reg [31:0] BC_very_long_target; //26 bit addr 225 | 226 | //reg [5:0] tmp_opcode; 227 | //reg [4:0] tmp_rs, tmp_rt; 228 | //reg [15:0] tmp_imm; 229 | //reg [31:0] tmp_PC; 230 | reg [31:0] GPR_rs, GPR_rt; 231 | reg rs_lock, rt_lock; 232 | reg [2:0] rs_lock_by, rt_lock_by; 233 | //reg [1:0] rs_data_stage, rt_data_stage; 234 | 235 | /*always @(posedge CLK or posedge RST) begin 236 | if(RST) begin 237 | busy <= 0; 238 | end else begin 239 | if(!prev_busy) begin 240 | tmp_opcode = prev_insn[31:26]; 241 | tmp_rs = prev_insn[25:21]; 242 | tmp_rt = prev_insn[20:16]; 243 | tmp_imm = prev_insn[15:0]; 244 | tmp_PC = prev_insnPC; 245 | end else begin 246 | tmp_opcode = insn[31:26]; 247 | tmp_rs = insn[25:21]; 248 | tmp_rt = insn[20:16]; 249 | tmp_imm = insn[15:0]; 250 | tmp_PC = insnPC; 251 | end 252 | 253 | Branch_target = tmp_PC + {{14{tmp_imm[15]}}, tmp_imm, 2'b00}; 254 | BC_target = tmp_PC + 4 + {{14{tmp_imm[15]}}, tmp_imm, 2'b00}; 255 | BC_long_target = tmp_PC + 4 + {{9{tmp_rt[5]}}, tmp_rt, tmp_imm, 2'b00}; 256 | J_target = {tmp_PC[31:28], tmp_rs, tmp_rt, tmp_imm, 2'b00}; 257 | BC_very_long_target = tmp_PC + 4 + {{4{tmp_rs[4]}}, tmp_rs, tmp_rt, tmp_imm, 2'b00}; 258 | 259 | if(tmp_rs == 0) begin 260 | GPR_rs = 0; 261 | rs_lock = 0; 262 | end else if(tmp_rs == writeback_reg) begin 263 | GPR_rs = writeback_data; 264 | rs_lock = 0; 265 | end else if(tmp_rs == alu_forward_reg) begin 266 | GPR_rs = alu_forward_data; 267 | rs_lock = 0; 268 | end else begin 269 | GPR_rs = reg_file[tmp_rs]; 270 | rs_lock = reg_lock[tmp_rs]; 271 | end 272 | 273 | if(tmp_rt == 0) begin 274 | GPR_rt = 0; 275 | rt_lock = 0; 276 | end else if(tmp_rt == writeback_reg) begin 277 | GPR_rt = writeback_data; 278 | rt_lock = 0; 279 | end else if(tmp_rt == alu_forward_reg) begin 280 | GPR_rt = alu_forward_data; 281 | rt_lock = 0; 282 | end else begin 283 | GPR_rt = reg_file[tmp_rt]; 284 | rt_lock = reg_lock[tmp_rt]; 285 | end 286 | 287 | if(tmp_rt == 0) 288 | POP_insn_type = rs_lock ? 8 : 0; 289 | else if(tmp_rs == 0) 290 | POP_insn_type = rt_lock ? 8 : 1; 291 | else if(tmp_rs == tmp_rt) 292 | POP_insn_type = rt_lock ? 8 : 2; 293 | else 294 | POP_insn_type = rs_lock || rt_lock ? 8 : 4; 295 | 296 | jump_cond[0] = 0; 297 | jump_cond[1] = 1; 298 | jump_cond[2] = GPR_rs == GPR_rt; 299 | jump_cond[3] = GPR_rs != GPR_rt; 300 | jump_cond[4] = GPR_rs > GPR_rt; 301 | jump_cond[5] = GPR_rs < GPR_rt; 302 | jump_cond[6] = GPR_rs >= GPR_rt; 303 | jump_cond[7] = GPR_rs <= GPR_rt; 304 | jump_cond[8] = $signed(GPR_rs) > $signed(GPR_rt); 305 | jump_cond[9] = $signed(GPR_rs) < $signed(GPR_rt); 306 | jump_cond[10] = $signed(GPR_rs) >= $signed(GPR_rt); 307 | jump_cond[11] = $signed(GPR_rs) <= $signed(GPR_rt); 308 | jump_cond[12] = GPR_rs == 0; 309 | jump_cond[13] = GPR_rs != 0; 310 | jump_cond[14] = $signed(GPR_rs) > 0; 311 | jump_cond[15] = $signed(GPR_rs) < 0; 312 | jump_cond[16] = $signed(GPR_rs) >= 0; 313 | jump_cond[17] = $signed(GPR_rs) <= 0; 314 | jump_cond[18] = GPR_rt == 0; 315 | jump_cond[19] = GPR_rt != 0; 316 | jump_cond[20] = $signed(GPR_rt) > 0; 317 | jump_cond[21] = $signed(GPR_rt) < 0; 318 | jump_cond[22] = $signed(GPR_rt) >= 0; 319 | jump_cond[23] = $signed(GPR_rt) <= 0; 320 | 321 | busy <= 0; 322 | if(tmp_opcode == OPCD_SPECIAL) begin 323 | if(tmp_imm[5:0] == OPFUNC_JR || tmp_imm[5:0] == OPFUNC_JALR) 324 | if(rs_lock) 325 | busy <= 1; 326 | end else if(tmp_opcode == OPCD_REGIMM) begin 327 | if(rs_lock) 328 | busy <= 1; 329 | end else if(tmp_opcode == OPCD_BEQ || tmp_opcode == OPCD_BNE) begin 330 | if(rs_lock || rt_lock) 331 | busy <= 1; 332 | end else if(POP_insn_type[3]) begin//POP_insn_type == 8 333 | busy <= 1; 334 | end 335 | end 336 | end 337 | */ 338 | 339 | reg [5:0] opcode; 340 | reg [4:0] rs, rt, rd, sa; 341 | reg [5:0] opfunc; 342 | reg [15:0] imm; 343 | reg [25:0] j_addr; 344 | 345 | task fetch_rs; //rs -> src1 346 | begin 347 | alu_src1 <= GPR_rs; 348 | alu_src1_forward <= rs_lock; 349 | alu_src1_forward_from <= rs_lock_by; 350 | end 351 | endtask 352 | 353 | task fetch_rt; 354 | begin 355 | alu_src2 <= GPR_rt; 356 | alu_src2_forward <= rt_lock; 357 | alu_src2_forward_from <= rt_lock_by; 358 | end 359 | endtask 360 | 361 | task decode_rtype; //dst reg = src1 reg OP src2 reg 362 | input [4:0] dst; 363 | input use_src1; //src1 -- rs 364 | input use_src2; //src2 -- rt 365 | input [`ALU_OPCODE_WIDTH-1:0] alu_op; 366 | input [`MEM_OPCODE_WIDTH-1:0] mem_op; 367 | 368 | begin 369 | if(use_src1) begin 370 | fetch_rs(); 371 | end 372 | if(use_src2) begin 373 | fetch_rt(); 374 | end 375 | alu_opcode <= alu_op; 376 | mem_opcode <= mem_op; 377 | write_register(dst); 378 | end 379 | endtask 380 | 381 | task decode_itype; 382 | input [4:0] dst; 383 | input use_src1; 384 | input sign_extend; 385 | //input [15:0] imm2; 386 | input [`ALU_OPCODE_WIDTH-1:0] alu_op; 387 | input [`MEM_OPCODE_WIDTH-1:0] mem_op; 388 | 389 | begin 390 | if(use_src1) begin 391 | fetch_rs(); 392 | end 393 | //fetch_register(src1, alu_src1, alu_src1_forward, alu_src1_forward_from); 394 | if(sign_extend) 395 | alu_src2 <= {{16{imm[15]}}, imm}; //sign extended 396 | else 397 | alu_src2 <= {16'b0, imm}; //zero extended 398 | alu_opcode <= alu_op; 399 | mem_opcode <= mem_op; 400 | write_register(dst); 401 | end 402 | endtask 403 | 404 | reg tmp_busy; 405 | 406 | reg [31:0] tmp_GPR_rs, tmp_GPR_rt; 407 | reg clear_next_insn; 408 | 409 | reg [31:0] last_next_insn; 410 | reg last_next_insn_enabled; 411 | reg last_drop_next_insn; 412 | 413 | reg [31:0] insnPC_add_4; 414 | 415 | always @(posedge CLK or posedge RST) begin 416 | if(RST) begin 417 | insn <= 0; 418 | insnPC <= 0; 419 | reg_lock[0] <= 0; 420 | //reg_data_stage[0] <= 0; 421 | reg_lock_by[0] <= 0; 422 | for(i=1; i<32; i=i+1) begin 423 | reg_file[i] <= 0; 424 | reg_lock[i] <= 0; 425 | reg_lock_by[i] <= 0; 426 | //reg_data_stage[i] <= 0; 427 | end 428 | for(i=0; i<8; i=i+1) begin 429 | //insn_data_stage[i] <= 0; 430 | insn_data_overrided[i] <= 1; 431 | insn_write_reg[i] <= 0; 432 | end 433 | 434 | //prev_next_insn <= 0; 435 | //prev_next_insn_enabled <= 0; 436 | next_insnPC <= 0; 437 | alu_opcode <= 0; 438 | alu_src1 <= 0; 439 | alu_src2 <= 0; 440 | alu_src1_forward <= 0; 441 | alu_src1_forward_from <= 0; 442 | alu_src2_forward <= 0; 443 | alu_src2_forward_from <= 0; 444 | mem_opcode <= 0; 445 | mem_src2 <= 0; 446 | mem_src2_forward <= 0; 447 | mem_src2_forward_from <= 0; 448 | insn_id <= 0; 449 | next_insn_id <= 0; 450 | //next_insn_write_reg <= 0; 451 | //next_insn_data_stage <= 0; 452 | //drop_next_insn <= 0; 453 | //next_insn_data_stage_pending <= 0; 454 | next_insn_write_reg_pending <= 0; 455 | 456 | //tmp_GPR_rs <= 0; 457 | //tmp_GPR_rt <= 0; 458 | last_next_insn <= 0; 459 | last_next_insn_enabled <= 0; 460 | last_drop_next_insn <= 0; 461 | 462 | clear_next_insn <= 1; 463 | end else begin 464 | if(writeback_flag) begin 465 | if(writeback_reg == 0) 466 | $display("Assertion Failed: Writeback_reg == 0"); 467 | reg_file[writeback_reg] <= writeback_data; 468 | reg_lock[writeback_reg] <= 0; 469 | //reg_data_stage[writeback_reg] <= 0; 470 | //insn_data_stage[writeback_insn_id] <= 0; 471 | end 472 | if(alu_forward_flag) begin 473 | if(alu_forward_reg == 0) 474 | $display("Assertion Failed: ALU_forward_reg == 0"); 475 | 476 | reg_file[alu_forward_reg] <= alu_forward_data; 477 | reg_lock[alu_forward_reg] <= 0; 478 | //reg_data_stage[alu_forward_reg] <= 0; 479 | //insn_data_stage[alu_forward_insn_id] <= 0; 480 | end 481 | 482 | if(!prev_busy) begin 483 | insn = prev_insn; 484 | insnPC = prev_insnPC; 485 | 486 | if(next_insn_write_reg != 0) begin 487 | insn_write_reg[next_insn_id] <= next_insn_write_reg; 488 | //insn_data_stage[next_insn_id] <= next_insn_data_stage; 489 | insn_data_overrided[next_insn_id] <= 0; 490 | reg_lock[next_insn_write_reg] <= 1; 491 | //reg_data_stage[next_insn_write_reg] <= next_insn_data_stage; 492 | if(reg_lock[next_insn_write_reg]) 493 | insn_data_overrided[reg_lock_by[next_insn_write_reg]] <= 1; 494 | reg_lock_by[next_insn_write_reg] <= next_insn_id; 495 | end else begin 496 | insn_write_reg[next_insn_id] <= 0; 497 | insn_data_overrided[next_insn_id] <= 1; 498 | //insn_data_stage[next_insn_id] <= 0; 499 | end 500 | end 501 | 502 | opcode = insn[31:26]; 503 | rs = insn[25:21]; 504 | rt = insn[20:16]; 505 | rd = insn[15:11]; 506 | sa = insn[10:6]; 507 | opfunc = insn[5:0]; 508 | imm = insn[15:0]; 509 | j_addr = insn[25:0]; 510 | 511 | 512 | 513 | 514 | case(1'b1) 515 | writeback_flag && rs == writeback_reg: begin 516 | GPR_rs = writeback_data; 517 | rs_lock = 0; 518 | rs_lock_by = 0; 519 | //rs_data_stage = 0; 520 | end 521 | 522 | alu_forward_flag && rs == alu_forward_reg: begin 523 | GPR_rs = alu_forward_data; 524 | rs_lock = 0; 525 | rs_lock_by = 0; 526 | //rs_data_stage = 0; 527 | end 528 | 529 | default: begin 530 | GPR_rs = GPR[rs]; 531 | rs_lock = reg_lock[rs]; 532 | rs_lock_by = reg_lock_by[rs]; 533 | //rs_data_stage = reg_data_stage[rs]; 534 | end 535 | endcase 536 | 537 | case(1'b1) 538 | writeback_flag && rt == writeback_reg: begin 539 | GPR_rt = writeback_data; 540 | rt_lock = 0; 541 | rt_lock_by = 0; 542 | //rt_data_stage = 0; 543 | end 544 | 545 | alu_forward_flag && rt == alu_forward_reg: begin 546 | GPR_rt = alu_forward_data; 547 | rt_lock = 0; 548 | rt_lock_by = 0; 549 | //rt_data_stage = 0; 550 | end 551 | 552 | default: begin 553 | GPR_rt = GPR[rt]; 554 | rt_lock = reg_lock[rt]; 555 | rt_lock_by = reg_lock_by[rt]; 556 | //rt_data_stage = reg_data_stage[rt]; 557 | end 558 | endcase 559 | 560 | if(!prev_busy) begin 561 | if(next_insn_write_reg != 0 && rs == next_insn_write_reg) begin 562 | rs_lock = 1; 563 | //rs_data_stage = next_insn_data_stage; 564 | rs_lock_by = next_insn_id; 565 | end 566 | if(next_insn_write_reg != 0 && rt == next_insn_write_reg) begin 567 | rt_lock = 1; 568 | //rt_data_stage = next_insn_data_stage; 569 | rt_lock_by = next_insn_id; 570 | end 571 | end 572 | 573 | //tmp_GPR_rs <= GPR_rs; 574 | //tmp_GPR_rt <= GPR_rt; 575 | insnPC_add_4 = insnPC + 4; 576 | Branch_target <= insnPC_add_4 + {{14{imm[15]}}, imm, 2'b00}; 577 | BC_target <= insnPC_add_4 + {{14{imm[15]}}, imm, 2'b00}; 578 | BC_long_target <= insnPC_add_4 + {{9{rt[4]}}, rt, imm, 2'b00}; 579 | J_target <= {insnPC_add_4[31:28], rs, rt, imm, 2'b00}; 580 | BC_very_long_target <= insnPC_add_4 + {{4{rs[4]}}, rs, rt, imm, 2'b00}; 581 | 582 | //jump_cond[0] <= 0; 583 | //jump_cond[1] <= 1; 584 | jump_cond_basic[0] <= GPR_rs == GPR_rt; 585 | //jump_cond[3] <= GPR_rs != GPR_rt; 586 | jump_cond_basic[1] <= GPR_rs > GPR_rt; 587 | //jump_cond[5] <= GPR_rs < GPR_rt; 588 | //jump_cond[6] <= GPR_rs >= GPR_rt; 589 | //jump_cond[7] <= GPR_rs <= GPR_rt; 590 | jump_cond_basic[2] <= $signed(GPR_rs) > $signed(GPR_rt); 591 | //jump_cond[9] <= $signed(GPR_rs) < $signed(GPR_rt); 592 | //jump_cond[10] <= $signed(GPR_rs) >= $signed(GPR_rt); 593 | //jump_cond[11] <= $signed(GPR_rs) <= $signed(GPR_rt); 594 | jump_cond_basic[3] <= GPR_rs == 0; 595 | //jump_cond[13] <= GPR_rs != 0; 596 | jump_cond_basic[4] <= $signed(GPR_rs) > 0; 597 | //jump_cond[15] <= $signed(GPR_rs) < 0; 598 | //jump_cond[16] <= $signed(GPR_rs) >= 0; 599 | //jump_cond[17] <= $signed(GPR_rs) <= 0; 600 | jump_cond_basic[5] <= GPR_rt == 0; 601 | //jump_cond[19] <= GPR_rt != 0; 602 | jump_cond_basic[6] <= $signed(GPR_rt) > 0; 603 | //jump_cond[21] <= $signed(GPR_rt) < 0; 604 | //jump_cond[22] <= $signed(GPR_rt) >= 0; 605 | //jump_cond[23] <= $signed(GPR_rt) <= 0; 606 | 607 | if(rt == 0) 608 | POP_insn_type = rs_lock ? 4'd8 : 4'd0; 609 | else if(rs == 0) 610 | POP_insn_type = rt_lock ? 4'd8 : 4'd1; 611 | else if(rs == rt) 612 | POP_insn_type = rt_lock ? 4'd8 : 4'd2; 613 | else 614 | POP_insn_type = rs_lock || rt_lock ? 4'd8 : 4'd4; 615 | 616 | tmp_busy = 0; 617 | case(opcode) 618 | OPCD_SPECIAL: begin 619 | if(opfunc == OPFUNC_JR || opfunc == OPFUNC_JALR) 620 | tmp_busy = rs_lock; 621 | end 622 | OPCD_REGIMM: tmp_busy = rs_lock; 623 | OPCD_BEQ, OPCD_BNE: tmp_busy = rs_lock || rt_lock; 624 | OPCD_POP06, OPCD_POP07, 625 | OPCD_POP10, OPCD_POP26, 626 | OPCD_POP27, OPCD_POP30, 627 | OPCD_POP66, OPCD_POP76: tmp_busy = POP_insn_type[3]; 628 | endcase 629 | 630 | busy <= tmp_busy; 631 | 632 | jump_cond_id <= NEVER; 633 | jump_type <= JUMP_J; 634 | 635 | clear_next_insn <= 0; 636 | if(!prev_placeholder_insn) begin 637 | /*prev_next_insn <= 0; 638 | prev_next_insn_enabled <= 0; 639 | drop_next_insn <= 0;*/ 640 | clear_next_insn <= 1; 641 | end 642 | if(!next_busy) begin 643 | if(insn_id == 3'b011) 644 | insn_id = 0; 645 | else 646 | insn_id = insn_id + 1; 647 | end 648 | next_insn_write_reg_pending <= 0; 649 | //next_insn_data_stage_pending <= 0; 650 | alu_opcode <= `ALU_NOP; 651 | alu_src1 <= 0; 652 | alu_src2 <= 0; 653 | alu_src1_forward <= 0; 654 | alu_src2_forward <= 0; 655 | alu_src1_forward_from <= 0; 656 | alu_src2_forward_from <= 0; 657 | mem_opcode <= `MEM_NOP; 658 | mem_src2 <= 0; 659 | mem_src2_forward <= 0; 660 | mem_src2_forward_from <= 0; 661 | next_insnPC <= insnPC; 662 | next_insn_id <= busy ? 3'b111 : insn_id; 663 | 664 | if(!drop_next_insn && !tmp_busy) begin 665 | case(opcode) 666 | OPCD_SPECIAL: begin 667 | 668 | case(opfunc) 669 | OPFUNC_ADD: decode_rtype(rd, 1, 1, `ALU_ADD, `MEM_NOP); 670 | OPFUNC_ADDU: decode_rtype(rd, 1, 1, `ALU_ADDU, `MEM_NOP); 671 | OPFUNC_SUB: decode_rtype(rd, 1, 1, `ALU_SUB, `MEM_NOP); 672 | OPFUNC_SUBU: decode_rtype(rd, 1, 1, `ALU_SUBU, `MEM_NOP); 673 | OPFUNC_SLLV: decode_rtype(rd, 1, 1, `ALU_SLL, `MEM_NOP); 674 | OPFUNC_SRLV: decode_rtype(rd, 1, 1, sa == 5'h01 ? `ALU_ROR : `ALU_SRL, `MEM_NOP); 675 | OPFUNC_SRAV: decode_rtype(rd, 1, 1, `ALU_SRA, `MEM_NOP); 676 | OPFUNC_AND: decode_rtype(rd, 1, 1, `ALU_AND, `MEM_NOP); 677 | OPFUNC_OR: decode_rtype(rd, 1, 1, `ALU_OR, `MEM_NOP); 678 | OPFUNC_NOR: decode_rtype(rd, 1, 1, `ALU_NOR, `MEM_NOP); 679 | OPFUNC_XOR: decode_rtype(rd, 1, 1, `ALU_XOR, `MEM_NOP); 680 | OPFUNC_SLL: begin 681 | decode_rtype(rd, 0, 1, `ALU_SLL, `MEM_NOP); 682 | alu_src1 <= {27'b0, sa}; 683 | end 684 | OPFUNC_SRL: begin 685 | decode_rtype(rd, 0, 1, rs == 5'h01 ? `ALU_ROR : `ALU_SRL, `MEM_NOP); 686 | alu_src1 <= {27'b0, sa}; 687 | end 688 | OPFUNC_SRA: begin 689 | decode_rtype(rd, 0, 1, `ALU_SRA, `MEM_NOP); 690 | alu_src1 <= {27'b0, sa}; 691 | end 692 | OPFUNC_SOP30: begin 693 | if(sa == 5'b00010) //MUL 694 | decode_rtype(rd, 1, 1, `ALU_MULTL, `MEM_NOP); 695 | else if(sa == 5'b00011) 696 | decode_rtype(rd, 1, 1, `ALU_MULTH, `MEM_NOP); 697 | //TODO: Exception 698 | end 699 | OPFUNC_SOP31: begin 700 | if(sa == 5'b00010) 701 | decode_rtype(rd, 1, 1, `ALU_MULTLU, `MEM_NOP); 702 | else if(sa == 5'b00011) 703 | decode_rtype(rd, 1, 1, `ALU_MULTHU, `MEM_NOP); 704 | //TODO: Exception 705 | end 706 | OPFUNC_SOP32: begin 707 | if(sa == 5'b00010) 708 | decode_rtype(rd, 1, 1, `ALU_DIV, `MEM_NOP); 709 | else if(sa == 5'b00011) 710 | decode_rtype(rd, 1, 1, `ALU_MOD, `MEM_NOP); 711 | //TODO: Exception 712 | end 713 | OPFUNC_SOP33: begin 714 | if(sa == 5'b00010) 715 | decode_rtype(rd, 1, 1, `ALU_DIVU, `MEM_NOP); 716 | else if(sa == 5'b00011) 717 | decode_rtype(rd, 1, 1, `ALU_MODU, `MEM_NOP); 718 | end 719 | OPFUNC_JR: begin 720 | /*if(rs_lock) 721 | busy <= 1; 722 | else*/ begin 723 | jump_cond_id <= ALWAYS; 724 | jump_type <= JUMP_GPR_RS; 725 | end 726 | //decode_jump_reg(rs); 727 | end 728 | OPFUNC_JALR: begin 729 | /*if(rs_lock) 730 | busy <= 1; 731 | else*/ begin 732 | jump_cond_id <= ALWAYS; 733 | jump_type <= JUMP_GPR_RS; 734 | //decode_jump_reg(rs); 735 | alu_src1 <= insnPC + 8; 736 | write_register(31); 737 | end 738 | end 739 | OPFUNC_SLT: decode_rtype(rd, 1, 1, `ALU_SLT, `MEM_NOP); 740 | OPFUNC_SLTU: decode_rtype(rd, 1, 1, `ALU_SLTU, `MEM_NOP); 741 | default:; //TODO: Exception 742 | endcase 743 | end 744 | 745 | //OPCD_ADDI: decode_itype(rt, rs, imm, `ALU_ADD, `MEM_NOP); 746 | OPCD_ADDIU: decode_itype(rt, 1, 1, `ALU_ADDU, `MEM_NOP); 747 | OPCD_ANDI: decode_itype(rt, 1, 0, `ALU_AND, `MEM_NOP); 748 | OPCD_ORI: decode_itype(rt, 1, 0, `ALU_OR, `MEM_NOP); 749 | OPCD_XORI: decode_itype(rt, 1, 0, `ALU_XOR, `MEM_NOP); 750 | OPCD_BEQ: begin 751 | /*if(rs_lock || rt_lock) 752 | busy <= 1; 753 | else*/ begin 754 | //jump_cond_flag = COND_RS_RT; 755 | jump_cond_id <= RS_EQ_RT; 756 | jump_type <= JUMP_J; 757 | end 758 | //else if(CMP_rs_rt[0] /*get_register(rs) == get_register(rt)*/) 759 | // jump_offset(imm); 760 | end 761 | OPCD_BNE: begin 762 | /*if(rs_lock || rt_lock) 763 | busy <= 1; 764 | else*/ begin 765 | //jump_cond_flag = COND_RS_RT; 766 | jump_cond_id <= RS_NE_RT; 767 | //jump_cond_neg = 1; 768 | jump_type <= JUMP_J; 769 | end 770 | //else if(!CMP_rs_rt[0] /*get_register(rs) != get_register(rt)*/) 771 | // jump_offset(imm); 772 | end 773 | OPCD_J: begin 774 | //jump_target = {insnPC[31:28], j_addr, 2'b00}; 775 | //jump_cond_flag = COND_ALWAYS; 776 | jump_cond_id <= ALWAYS; 777 | jump_type <= JUMP_J_LONG; 778 | //prev_next_insn <= {insnPC[31:28], j_addr, 2'b00}; 779 | //prev_next_insn_enabled <= 1; 780 | end 781 | OPCD_JAL: begin 782 | //jump_target = {insnPC[31:28], j_addr, 2'b00}; 783 | //jump_cond_flag = COND_ALWAYS; 784 | jump_cond_id <= ALWAYS; 785 | jump_type <= JUMP_J_LONG; 786 | //prev_next_insn <= {insnPC[31:28], j_addr, 2'b00}; 787 | //prev_next_insn_enabled <= 1; 788 | alu_src1 <= insnPC + 8; 789 | write_register(31); 790 | end 791 | OPCD_BC: begin 792 | //jump_target = insnPC + 4 + {{4{j_addr[25]}}, j_addr, 2'b00}; 793 | //jump_cond_flag = COND_ALWAYS; 794 | jump_cond_id <= ALWAYS; 795 | jump_type <= JUMP_BC_VERY_LONG; 796 | //prev_next_insn <= insnPC + 4 + {{4{j_addr[25]}}, j_addr, 2'b00}; 797 | //prev_next_insn_enabled <= 1; 798 | //drop_next_insn <= 1; 799 | end 800 | OPCD_BALC: begin 801 | //jump_target = insnPC + 4 + {{4{j_addr[25]}}, j_addr, 2'b00}; 802 | //jump_cond_flag = COND_ALWAYS; 803 | jump_cond_id <= ALWAYS; 804 | jump_type <= JUMP_BC_VERY_LONG; 805 | //prev_next_insn <= insnPC + 4 + {{4{j_addr[25]}}, j_addr, 2'b00}; 806 | //prev_next_insn_enabled <= 1; 807 | //drop_next_insn <= 1; 808 | alu_src1 <= insnPC + 4; 809 | write_register(31); 810 | end 811 | OPCD_REGIMM: begin 812 | if(rt[0]/*rt == 5'b00001*/) begin //BGEZ 813 | begin 814 | jump_cond_id <= RS_GE_ZERO; 815 | jump_type <= JUMP_J; 816 | end 817 | end else /*if(rt == 5'b00000)*/ begin //BLTZ 818 | begin 819 | jump_cond_id <= RS_LT_ZERO; 820 | jump_type <= JUMP_J; 821 | end 822 | end 823 | //TODO: Exception 824 | end 825 | OPCD_POP06: begin //BLEZ, BLEZALC, BGEZALC 826 | case(POP_insn_type) 827 | 0: begin //BLEZ 828 | //jump_cond_flag = COND_RS_ZERO; 829 | jump_cond_id <= RS_LE_ZERO; 830 | //jump_cond_neg = 1; 831 | jump_type <= JUMP_J; 832 | //else if(!CMP_rs_zero[1]/*$signed(get_register(rs)) <= 0*/) 833 | // jump_offset(imm); 834 | end 835 | 836 | 1: begin //BLEZALC 837 | //jump_cond_flag = COND_RT_ZERO; 838 | jump_cond_id <= RT_LE_ZERO; 839 | //jump_cond_neg = 1; 840 | jump_type <= JUMP_BALC; 841 | alu_src1 <= insnPC + 4; 842 | //else if(!CMP_rt_zero[1]/*$signed(get_register(rt)) <= 0*/) 843 | // branch_compact_offset_and_link(imm); 844 | end 845 | 846 | 2: begin //BGEZALC 847 | //jump_cond_flag = COND_RT_ZERO; 848 | jump_cond_id <= RT_GE_ZERO; 849 | //jump_cond_neg = 1; 850 | jump_type <= JUMP_BALC; 851 | alu_src1 <= insnPC + 4; 852 | //else if(!CMP_rt_zero[2]/*$signed(get_register(rt)) >= 0*/) 853 | // branch_compact_offset_and_link(imm); 854 | end 855 | 856 | 4: begin //BGEUC 857 | //jump_cond_flag = COND_RS_RT; 858 | jump_cond_id <= RS_GEU_RT; 859 | //jump_cond_neg = 1; 860 | jump_type <= JUMP_BC; 861 | //else if(!CMP_rs_rt[2]/*get_register(rs) >= get_register(rt)*/) 862 | // branch_compact_offset(imm); 863 | end 864 | 865 | //8: busy <= 1; 866 | endcase 867 | end 868 | OPCD_POP07: begin 869 | case(POP_insn_type) 870 | 0: begin //BGTZ 871 | //jump_cond_flag = COND_RS_ZERO; 872 | jump_cond_id <= RS_GT_ZERO; 873 | jump_type <= JUMP_J; 874 | //else if(CMP_rs_zero[1]/*$signed(get_register(rs)) > 0*/) 875 | // jump_offset(imm); 876 | end 877 | 878 | 1: begin //BGTZALC 879 | //jump_cond_flag = COND_RT_ZERO; 880 | jump_cond_id <= RT_GT_ZERO; 881 | jump_type <= JUMP_BALC; 882 | alu_src1 <= insnPC + 4; 883 | //else if(CMP_rt_zero[1]/*$signed(get_register(rt)) > 0*/) 884 | // branch_compact_offset_and_link(imm); 885 | end 886 | 887 | 2: begin //BLTZALC 888 | //jump_cond_flag = COND_RT_ZERO; 889 | jump_cond_id <= RT_LT_ZERO; 890 | jump_type <= JUMP_BALC; 891 | alu_src1 <= insnPC + 4; 892 | //else if(CMP_rt_zero[2]/*$signed(get_register(rt)) < 0*/) 893 | // branch_compact_offset_and_link(imm); 894 | end 895 | 896 | 4: begin //BLTUC 897 | //jump_cond_flag = COND_RS_RT; 898 | jump_cond_id <= RS_LTU_RT; 899 | jump_type <= JUMP_BC; 900 | //else if(CMP_rs_rt[2]/*get_register(rs) < get_register(rt)*/) 901 | // branch_compact_offset(imm); 902 | end 903 | 904 | //8: busy <= 1; 905 | endcase 906 | end 907 | OPCD_POP10: begin 908 | case(POP_insn_type) 909 | 1: begin //BEQZALC 910 | //jump_cond_flag = COND_RT_ZERO; 911 | jump_cond_id <= RT_EQ_ZERO; 912 | jump_type <= JUMP_BALC; 913 | alu_src1 <= insnPC + 4; 914 | //else if(CMP_rt_zero[0]/*get_register(rt) == 0*/) 915 | // branch_compact_offset_and_link(imm); 916 | end 917 | 918 | 4: begin //BEQC 919 | //jump_cond_flag = COND_RS_RT; 920 | jump_cond_id <= RS_EQ_RT; 921 | jump_type <= JUMP_BC; 922 | //else if(CMP_rs_rt[0]/*get_register(rs) == get_register(rt)*/) 923 | // branch_compact_offset(imm); 924 | end 925 | 926 | //8: busy <= 1; 927 | endcase 928 | end 929 | OPCD_POP30: begin 930 | case(POP_insn_type) 931 | 1: begin //BNEZALC 932 | //jump_cond_flag = COND_RT_ZERO; 933 | jump_cond_id <= RT_NE_ZERO; 934 | //jump_cond_neg = 1; 935 | jump_type <= JUMP_BALC; 936 | alu_src1 <= insnPC + 4; 937 | //else if(!CMP_rt_zero[0]/*get_register(rt) != 0*/) 938 | // branch_compact_offset_and_link(imm); 939 | end 940 | 941 | 4: begin //BNEC 942 | //jump_cond_flag = COND_RS_RT; 943 | jump_cond_id <= RS_NE_RT; 944 | //jump_cond_neg = 1; 945 | jump_type <= JUMP_BC; 946 | //else if(!CMP_rs_rt[0]/*get_register(rs) != get_register(rt)*/) 947 | // branch_compact_offset(imm); 948 | end 949 | 950 | //8: busy <= 1; 951 | endcase 952 | end 953 | OPCD_POP26: begin 954 | case(POP_insn_type) 955 | 1: begin //BLEZC 956 | //jump_cond_flag = COND_RT_ZERO; 957 | jump_cond_id <= RT_LE_ZERO; 958 | //jump_cond_neg = 1; 959 | jump_type <= JUMP_BC; 960 | //else if(!CMP_rt_zero[1]/*$signed(get_register(rt)) <= 0*/) 961 | // branch_compact_offset(imm); 962 | end 963 | 964 | 2: begin //BGEZC 965 | //jump_cond_flag = COND_RT_ZERO; 966 | jump_cond_id <= RT_GE_ZERO; 967 | //jump_cond_neg = 1; 968 | jump_type <= JUMP_BC; 969 | //else if(!CMP_rt_zero[2]/*$signed(get_register(rt)) >= 0*/) 970 | // branch_compact_offset(imm); 971 | end 972 | 973 | 4: begin //BGEC 974 | //jump_cond_flag = COND_RS_RT; 975 | jump_cond_id <= RS_GE_RT; 976 | //jump_cond_neg = 1; 977 | jump_type <= JUMP_BC; 978 | //else if(!CMP_rs_rt[4]/*$signed(get_register(rs)) >= $signed(get_register(rt))*/) 979 | // branch_compact_offset(imm); 980 | end 981 | 982 | //8: busy <= 1; 983 | endcase 984 | end 985 | OPCD_POP27: begin 986 | case(POP_insn_type) 987 | 1: begin //BGTZC 988 | //jump_cond_flag = COND_RT_ZERO; 989 | jump_cond_id <= RT_GT_ZERO; 990 | jump_type <= JUMP_BC; 991 | //else if(CMP_rt_zero[1]/*$signed(get_register(rt)) > 0*/) 992 | // branch_compact_offset(imm); 993 | end 994 | 995 | 2: begin //BLTZC 996 | //jump_cond_flag = COND_RT_ZERO; 997 | jump_cond_id <= RT_LT_ZERO; 998 | jump_type <= JUMP_BC; 999 | //else if(CMP_rt_zero[2]/*$signed(get_register(rt)) < 0*/) 1000 | // branch_compact_offset(imm); 1001 | end 1002 | 1003 | 4: begin //BLTC 1004 | //jump_cond_flag = COND_RS_RT; 1005 | jump_cond_id <= RS_LT_RT; 1006 | jump_type <= JUMP_BC; 1007 | //else if(CMP_rs_rt[4]/*$signed(get_register(rs)) < $signed(get_register(rt))*/) 1008 | // branch_compact_offset(imm); 1009 | end 1010 | 1011 | //8: busy <= 1; 1012 | endcase 1013 | end 1014 | OPCD_POP66: begin 1015 | case(POP_insn_type) 1016 | 0: begin 1017 | //jump_cond_flag = COND_RS_ZERO; 1018 | jump_cond_id <= RS_EQ_ZERO; 1019 | jump_type <= JUMP_BC_LONG; 1020 | end 1021 | //else if(CMP_rs_zero[0]/*get_register(rs) == 0*/) begin 1022 | //prev_next_insn <= insnPC + 4 + {{9{insn[20]}}, insn[20:0], 2'b00}; 1023 | // prev_next_insn <= BC_long_target; 1024 | // prev_next_insn_enabled <= 1; 1025 | // drop_next_insn <= 1; 1026 | //end 1027 | 1028 | //8: busy <= 1; 1029 | endcase 1030 | end 1031 | OPCD_POP76: begin 1032 | case(POP_insn_type) 1033 | 0: begin 1034 | //jump_cond_flag = COND_RS_ZERO; 1035 | jump_cond_id <= RS_NE_ZERO; 1036 | //jump_cond_neg = 1; 1037 | jump_type <= JUMP_BC_LONG; 1038 | //else if(!CMP_rs_zero[0]/*get_register(rs) != 0*/) begin 1039 | //prev_next_insn <= insnPC + 4 + {{9{insn[20]}}, insn[20:0], 2'b00}; 1040 | // prev_next_insn <= BC_long_target; 1041 | // prev_next_insn_enabled <= 1; 1042 | // drop_next_insn <= 1; 1043 | //end 1044 | end 1045 | 1046 | //8: busy <= 1; 1047 | endcase 1048 | end 1049 | 1050 | OPCD_SLTI: decode_itype(rt, 1, 1, `ALU_SLT, `MEM_NOP); 1051 | OPCD_SLTIU: decode_itype(rt, 1, 1, `ALU_SLTU, `MEM_NOP); 1052 | OPCD_LB: decode_itype(rt, 1, 1, `ALU_ADDU, `MEM_LB); 1053 | OPCD_LBU: decode_itype(rt, 1, 1, `ALU_ADDU, `MEM_LBU); 1054 | OPCD_LH: decode_itype(rt, 1, 1, `ALU_ADDU, `MEM_LH); 1055 | OPCD_LHU: decode_itype(rt, 1, 1, `ALU_ADDU, `MEM_LHU); 1056 | OPCD_LW: decode_itype(rt, 1, 1, `ALU_ADDU, `MEM_LW); 1057 | OPCD_SB: begin 1058 | decode_itype(0, 1, 1, `ALU_ADDU, `MEM_SB); 1059 | mem_src2 <= GPR_rt; 1060 | mem_src2_forward <= rt_lock; 1061 | mem_src2_forward_from <= rt_lock_by; 1062 | //fetch_register(rt, mem_src2, mem_src2_forward, mem_src2_forward_from); 1063 | end 1064 | OPCD_SH: begin 1065 | decode_itype(0, 1, 1, `ALU_ADDU, `MEM_SH); 1066 | mem_src2 <= GPR_rt; 1067 | mem_src2_forward <= rt_lock; 1068 | mem_src2_forward_from <= rt_lock_by; 1069 | //fetch_register(rt, mem_src2, mem_src2_forward, mem_src2_forward_from); 1070 | end 1071 | OPCD_SW: begin 1072 | decode_itype(0, 1, 1, `ALU_ADDU, `MEM_SW); 1073 | mem_src2 <= GPR_rt; 1074 | mem_src2_forward <= rt_lock; 1075 | mem_src2_forward_from <= rt_lock_by; 1076 | //fetch_register(rt, mem_src2, mem_src2_forward, mem_src2_forward_from); 1077 | end 1078 | OPCD_AUI: begin 1079 | fetch_rs(); 1080 | //fetch_register(rs, alu_src1, alu_src1_forward, alu_src1_forward_from); 1081 | alu_src2 <= {imm, 16'b0}; 1082 | alu_opcode <= `ALU_ADDU; 1083 | write_register(rt); 1084 | end 1085 | 1086 | default:; //TODO: Exception 1087 | endcase 1088 | end 1089 | 1090 | last_next_insn <= prev_next_insn; 1091 | last_next_insn_enabled <= prev_next_insn_enabled; 1092 | last_drop_next_insn <= drop_next_insn; 1093 | end 1094 | end 1095 | 1096 | always @(*) begin 1097 | prev_next_insn = last_next_insn; 1098 | prev_next_insn_enabled = last_next_insn_enabled; 1099 | drop_next_insn = last_drop_next_insn; 1100 | if(clear_next_insn) begin 1101 | prev_next_insn = 0; 1102 | prev_next_insn_enabled = 0; 1103 | drop_next_insn = 0; 1104 | end 1105 | 1106 | //next_insn_data_stage = next_insn_data_stage_pending; 1107 | next_insn_write_reg = next_insn_write_reg_pending; 1108 | 1109 | jump_cond[0] = 0; 1110 | jump_cond[1] = 1; 1111 | jump_cond[2] = jump_cond_basic[0]; 1112 | jump_cond[3] = !jump_cond_basic[0]; 1113 | jump_cond[4] = jump_cond_basic[1]; 1114 | jump_cond[5] = !(jump_cond_basic[0] || jump_cond_basic[1]); 1115 | jump_cond[6] = jump_cond_basic[0] || jump_cond_basic[1]; 1116 | jump_cond[7] = !jump_cond_basic[1]; 1117 | jump_cond[8] = jump_cond_basic[2]; 1118 | jump_cond[9] = !(jump_cond_basic[0] || jump_cond_basic[2]); 1119 | jump_cond[10] = jump_cond_basic[0] || jump_cond_basic[2]; 1120 | jump_cond[11] = !jump_cond_basic[2]; 1121 | jump_cond[12] = jump_cond_basic[3]; 1122 | jump_cond[13] = !jump_cond_basic[3]; 1123 | jump_cond[14] = jump_cond_basic[4]; 1124 | jump_cond[15] = !(jump_cond_basic[3] || jump_cond_basic[4]); 1125 | jump_cond[16] = jump_cond_basic[3] || jump_cond_basic[4]; 1126 | jump_cond[17] = !jump_cond_basic[4]; 1127 | jump_cond[18] = jump_cond_basic[5]; 1128 | jump_cond[19] = !jump_cond_basic[5]; 1129 | jump_cond[20] = jump_cond_basic[6]; 1130 | jump_cond[21] = !(jump_cond_basic[5] || jump_cond_basic[6]); 1131 | jump_cond[22] = jump_cond_basic[5] || jump_cond_basic[6]; 1132 | jump_cond[23] = !jump_cond_basic[6]; 1133 | 1134 | if(jump_cond[jump_cond_id]) begin 1135 | case(jump_type) 1136 | JUMP_J: begin 1137 | prev_next_insn = Branch_target; 1138 | prev_next_insn_enabled = 1; 1139 | end 1140 | JUMP_BC: begin 1141 | prev_next_insn = BC_target; 1142 | prev_next_insn_enabled = 1; 1143 | drop_next_insn = 1; 1144 | end 1145 | JUMP_BALC: begin 1146 | prev_next_insn = BC_target; 1147 | prev_next_insn_enabled = 1; 1148 | drop_next_insn = 1; 1149 | //alu_src1 <= insnPC + 4; 1150 | //write_register(31, 1); 1151 | //next_insn_data_stage = 1; 1152 | next_insn_write_reg = 31; 1153 | end 1154 | JUMP_BC_LONG: begin 1155 | prev_next_insn = BC_long_target; 1156 | prev_next_insn_enabled = 1; 1157 | drop_next_insn = 1; 1158 | end 1159 | JUMP_GPR_RS: begin 1160 | prev_next_insn = GPR_rs; 1161 | prev_next_insn_enabled = 1; 1162 | end 1163 | JUMP_J_LONG: begin 1164 | prev_next_insn = J_target; 1165 | prev_next_insn_enabled = 1; 1166 | end 1167 | JUMP_BC_VERY_LONG: begin 1168 | prev_next_insn = BC_very_long_target; 1169 | prev_next_insn_enabled = 1; 1170 | drop_next_insn = 1; 1171 | end 1172 | default:; 1173 | endcase 1174 | end 1175 | end 1176 | endmodule 1177 | --------------------------------------------------------------------------------