├── riscv ├── out │ └── .gitkeep ├── crt0.s ├── fibonacci.c ├── linker.ld ├── gen_instr_mem.py └── Makefile ├── src ├── dokifive_p50_top.sld ├── modules │ ├── packages │ │ ├── signals.sv │ │ ├── io.sv │ │ └── types.sv │ ├── muxes │ │ ├── mux2.sv │ │ ├── mux4.sv │ │ └── mux8.sv │ ├── memory │ │ ├── data_bram.qip │ │ ├── instruction_memory.sv │ │ ├── gprmm_registers.sv │ │ ├── memory_controller.sv │ │ └── data_bram.v │ ├── cpu │ │ ├── datapath │ │ │ ├── register_file.sv │ │ │ ├── f_iw_register.sv │ │ │ ├── imm_extender.sv │ │ │ ├── iw_d_register.sv │ │ │ ├── alu.sv │ │ │ ├── byte_store_unit.sv │ │ │ ├── e_m_register.sv │ │ │ ├── m_w_register.sv │ │ │ ├── byte_load_unit.sv │ │ │ ├── d_e_register.sv │ │ │ └── datapath.sv │ │ ├── hazard_unit │ │ │ ├── lw_fsm.sv │ │ │ └── hazard_unit.sv │ │ ├── control_unit │ │ │ ├── control_m_w_register.sv │ │ │ ├── byte_half_decoder.sv │ │ │ ├── control_e_m_register.sv │ │ │ ├── alu_decoder.sv │ │ │ ├── control_d_e_register.sv │ │ │ ├── control_unit.sv │ │ │ └── main_decoder.sv │ │ └── cpu.sv │ ├── sync │ │ └── en_clr_arst_register.sv │ └── dokifive_soc.sv ├── dokifive_p50_top.qpf ├── instr_init.mem ├── dokifive_p50_top.jditmp ├── peripherals │ ├── clock_divider.sv │ └── sevenseg.sv ├── dokifive_p50_top.sv ├── dokifive_p50_top.sdc └── dokifive_p50_top.qsf ├── .settings ├── com.sigasi.hdt.vhdl.version.prefs ├── com.sigasi.hdt.toolchains.active.prefs ├── com.sigasi.hdt.verilog.version.prefs ├── com.sigasi.hdt.libraries.active.prefs ├── com.sigasi.hdt.vhdl.linting.prefs ├── com.sigasi.hdt.verilog.linting.prefs └── org.eclipse.core.resources.prefs ├── simulation ├── vsim.wlf ├── instr_init.mem ├── data_init.mem ├── rf_init.mem ├── wave.do └── dokifive_p50.cr.mti ├── .gitignore ├── tests ├── tb_soc.sv ├── tb_imm_extender.sv └── tb_alu.sv ├── .library_mapping.xml ├── .project ├── LICENSE.md └── README.md /riscv/out/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/dokifive_p50_top.sld: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.settings/com.sigasi.hdt.vhdl.version.prefs: -------------------------------------------------------------------------------- 1 | =2008 2 | -------------------------------------------------------------------------------- /.settings/com.sigasi.hdt.toolchains.active.prefs: -------------------------------------------------------------------------------- 1 | Quartus=24.1std 2 | -------------------------------------------------------------------------------- /.settings/com.sigasi.hdt.verilog.version.prefs: -------------------------------------------------------------------------------- 1 | =sv2012 2 | -------------------------------------------------------------------------------- /.settings/com.sigasi.hdt.libraries.active.prefs: -------------------------------------------------------------------------------- 1 | altera_mf_ver=Quartus 2 | -------------------------------------------------------------------------------- /.settings/com.sigasi.hdt.vhdl.linting.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | isEnabled=true 3 | -------------------------------------------------------------------------------- /simulation/vsim.wlf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/julienfdev/dokifive_p50/HEAD/simulation/vsim.wlf -------------------------------------------------------------------------------- /.settings/com.sigasi.hdt.verilog.linting.prefs: -------------------------------------------------------------------------------- 1 | 3/severity//=WARNING 2 | eclipse.preferences.version=1 3 | isEnabled=true 4 | -------------------------------------------------------------------------------- /src/modules/packages/signals.sv: -------------------------------------------------------------------------------- 1 | package signals; 2 | typedef logic [31:0] imm_ext_t; 3 | typedef logic [31:7] imm_instr_t; 4 | endpackage 5 | -------------------------------------------------------------------------------- /src/dokifive_p50_top.qpf: -------------------------------------------------------------------------------- 1 | DATE = "19:14:34 April 28, 2025" 2 | QUARTUS_VERSION = "16.0.0" 3 | 4 | # Revisions 5 | 6 | PROJECT_REVISION = "dokifive_p50_top" 7 | -------------------------------------------------------------------------------- /riscv/crt0.s: -------------------------------------------------------------------------------- 1 | .globl _start 2 | .section .text 3 | _start: 4 | la sp, _stack_top # Set stack pointer to _stack_top 5 | call main # Call main() 6 | 1: j 1b # Infinite loop after main returns -------------------------------------------------------------------------------- /src/instr_init.mem: -------------------------------------------------------------------------------- 1 | 10020117 2 | 00010113 3 | 008000ef 4 | 0000006f 5 | 300005b7 6 | 02000713 7 | 00100793 8 | 00000693 9 | 00078613 10 | 00d787b3 11 | fff70713 12 | 00f5a023 13 | 00060693 14 | fe0716e3 15 | fddff06f 16 | -------------------------------------------------------------------------------- /simulation/instr_init.mem: -------------------------------------------------------------------------------- 1 | 10020117 2 | 00010113 3 | 008000ef 4 | 0000006f 5 | 300005b7 6 | 02000713 7 | 00100793 8 | 00000693 9 | 00078613 10 | 00d787b3 11 | fff70713 12 | 00f5a023 13 | 00060693 14 | fe0716e3 15 | fddff06f 16 | -------------------------------------------------------------------------------- /.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//Common\ Libraries/IEEE=UTF-8 3 | encoding//Common\ Libraries/IEEE\ Synopsys=UTF-8 4 | encoding//Common\ Libraries/STD=UTF-8 5 | encoding//Common\ Libraries=UTF-8 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | simulation/work 2 | *.o 3 | *.elf 4 | simulation/wlf* 5 | src/db 6 | *.rpt 7 | *.summary 8 | *.bak 9 | *.done 10 | *.smsg 11 | *.jdi 12 | *.pin 13 | *.pof 14 | *.sof 15 | *.qws 16 | src/incremental_db 17 | src/greybox_tmp 18 | riscv/*.mem -------------------------------------------------------------------------------- /src/modules/muxes/mux2.sv: -------------------------------------------------------------------------------- 1 | module mux2 #( 2 | parameter WIDTH = 32 3 | ) ( 4 | input logic s, 5 | input logic [WIDTH-1:0] a, b, 6 | output logic [WIDTH-1:0] out 7 | ); 8 | 9 | assign out = s ? b : a; 10 | endmodule 11 | -------------------------------------------------------------------------------- /src/dokifive_p50_top.jditmp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/modules/memory/data_bram.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name IP_TOOL_NAME "RAM: 1-PORT" 2 | set_global_assignment -name IP_TOOL_VERSION "24.1" 3 | set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{MAX 10}" 4 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "data_bram.v"] 5 | set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "data_bram_inst.v"] 6 | -------------------------------------------------------------------------------- /src/modules/packages/io.sv: -------------------------------------------------------------------------------- 1 | package io; 2 | // define two general purpose registers 3 | typedef struct packed { 4 | logic [31:0] GPR1; 5 | logic [31:0] GPR2; 6 | } GPREGS_T; 7 | localparam GPRMMSTART = 32'h30000000; 8 | localparam GPRMM1 = 32'h30000000; 9 | localparam GPRMM2 = 32'h30000001; 10 | localparam GPRMMEND = 32'h40000000; 11 | endpackage -------------------------------------------------------------------------------- /src/peripherals/clock_divider.sv: -------------------------------------------------------------------------------- 1 | module clock_divider #( 2 | parameter WIDTH = 25 3 | ) ( 4 | input logic clk, rst, 5 | output logic div_clk 6 | ); 7 | 8 | logic [WIDTH-1:0] counter; 9 | assign div_clk = counter[WIDTH-1]; 10 | 11 | always_ff @(posedge clk or posedge rst) begin 12 | if(rst) counter <= 0; 13 | else counter <= counter + 1; 14 | end 15 | 16 | endmodule -------------------------------------------------------------------------------- /simulation/data_init.mem: -------------------------------------------------------------------------------- 1 | 00000000 2 | 00001337 3 | 00000000 4 | 00000000 5 | 00000000 6 | 00000000 7 | 00000000 8 | 00000000 9 | 00000000 10 | 00000000 11 | 00000000 12 | 00000000 13 | 00000000 14 | 00000000 15 | 00000000 16 | 00000000 17 | 00000000 18 | 00000000 19 | 00000000 20 | 00000000 21 | 00000000 22 | 00000000 23 | 00000000 24 | 00000000 25 | 00000000 26 | 00000000 27 | 00000000 28 | 00000000 29 | 00000000 30 | 00000000 31 | 00000000 32 | -------------------------------------------------------------------------------- /riscv/fibonacci.c: -------------------------------------------------------------------------------- 1 | #define GPR1_ADDR ((volatile unsigned int*)0x30000000) 2 | 3 | int main() { 4 | while (1) { 5 | unsigned int a = 0; 6 | unsigned int b = 1; 7 | for (int i = 0; i < 32; ++i) { 8 | unsigned int temp = a + b; 9 | a = b; 10 | b = temp; 11 | *GPR1_ADDR = b; 12 | } 13 | // After 20 iterations, reset and repeat 14 | } 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /simulation/rf_init.mem: -------------------------------------------------------------------------------- 1 | 00000000 2 | 00000000 3 | 00000000 4 | 00000000 5 | 00000000 6 | 00000200 7 | 00000000 8 | 00000000 9 | 00000000 10 | 00000000 11 | 00000000 12 | 00000000 13 | 00000000 14 | 00000000 15 | 00000000 16 | 00000000 17 | 00000000 18 | 00000000 19 | 00000000 20 | 00000000 21 | 00000000 22 | 00000000 23 | 00000000 24 | 00000000 25 | 00000000 26 | 00000000 27 | 00000000 28 | 00000000 29 | 00000000 30 | 00000000 31 | 00000000 32 | 00000000 33 | -------------------------------------------------------------------------------- /src/modules/muxes/mux4.sv: -------------------------------------------------------------------------------- 1 | module mux4 #( 2 | parameter WIDTH = 32 3 | ) ( 4 | input logic [1:0] s, 5 | input logic [WIDTH-1:0] a, b, c, d, 6 | output logic [WIDTH-1:0] out 7 | ); 8 | 9 | always_comb begin 10 | case (s) 11 | 2'b00 : out = a; 12 | 2'b01 : out = b; 13 | 2'b10 : out = c; 14 | 2'b11 : out = d; 15 | default : out = 'hDEADBEEF; 16 | endcase 17 | 18 | end 19 | 20 | 21 | endmodule 22 | -------------------------------------------------------------------------------- /src/modules/muxes/mux8.sv: -------------------------------------------------------------------------------- 1 | module mux8 #( 2 | parameter WIDTH = 32 3 | ) ( 4 | input logic [2:0] s, 5 | input logic [WIDTH-1:0] a, b, c, d, e, f, g, h, 6 | output logic [WIDTH-1:0] out 7 | ); 8 | 9 | always_comb begin 10 | case (s) 11 | 3'b000 : out = a; 12 | 3'b001 : out = b; 13 | 3'b010 : out = c; 14 | 3'b011 : out = d; 15 | 3'b100 : out = e; 16 | 3'b101 : out = f; 17 | 3'b110 : out = g; 18 | 3'b111 : out = h; 19 | default : out = 'hDEADBEEF; 20 | endcase 21 | 22 | end 23 | 24 | 25 | endmodule 26 | -------------------------------------------------------------------------------- /tests/tb_soc.sv: -------------------------------------------------------------------------------- 1 | `timescale 10ps/1ps 2 | import io::*; 3 | 4 | module tb_soc; 5 | // Clock and reset 6 | logic clk = 0; 7 | logic rst = 1; 8 | GPREGS_T GPREGS; 9 | 10 | // SoC instance 11 | dokifive_soc #( 12 | .INITIAL_INSTR("instr_init.mem") 13 | ) uut ( 14 | .clk(clk), 15 | .rst(rst), 16 | .GPREGS(GPREGS) 17 | ); 18 | 19 | // Clock generation 20 | always #5 clk = ~clk; // 100MHz clock 21 | 22 | // Reset logic 23 | initial begin 24 | rst = 1; 25 | #22; 26 | rst = 0; 27 | end 28 | 29 | // No stop condition, manual control in QuestaSim 30 | endmodule -------------------------------------------------------------------------------- /.library_mapping.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /riscv/linker.ld: -------------------------------------------------------------------------------- 1 | ENTRY(_start) 2 | 3 | SECTIONS 4 | { 5 | /* Instructions and constants start at 0x0 */ 6 | .text 0x00000000 : 7 | { 8 | *(.text._start) /* Place _start at beginning */ 9 | *(.text*) /* All code */ 10 | *(.rodata*) /* Read-only data like const strings */ 11 | } 12 | 13 | /* Global data starts at 0x10000000 */ 14 | .data 0x10000000 : 15 | { 16 | *(.data*) 17 | } 18 | 19 | /* BSS follows data (auto-placement) */ 20 | .bss : 21 | { 22 | __bss_start = .; 23 | *(.bss*) 24 | *(COMMON) 25 | __bss_end = .; 26 | } 27 | . = 0x10000000 + 0x8000; /* Reserve 32KB for .data + .bss + stack */ 28 | _stack_top = .; 29 | } 30 | -------------------------------------------------------------------------------- /src/modules/cpu/datapath/register_file.sv: -------------------------------------------------------------------------------- 1 | // 3 ported 32x32 register file 2 | module register_file( 3 | input clk, we3, 4 | input logic [4:0] ra1, ra2, wa3, // read and write addresses 5 | input logic [31:0] wd3, // write data 6 | output logic [31:0] rd1, rd2 // read data 7 | ); 8 | 9 | (* ramstyle = "logic" *) logic [31:0] rf [0:31]; // register file, we prevent synthesizing it as a block RAM to avoid latency issues 10 | 11 | assign rd1 = (ra1 == 5'b0) ? 32'b0 : rf[ra1]; // read data 1 12 | assign rd2 = (ra2 == 5'b0) ? 32'b0 : rf[ra2]; // read data 2 13 | 14 | always_ff @(posedge clk) begin 15 | if (we3) begin 16 | rf[wa3] <= wd3; // write data 17 | end 18 | end 19 | endmodule 20 | -------------------------------------------------------------------------------- /src/modules/cpu/datapath/f_iw_register.sv: -------------------------------------------------------------------------------- 1 | module f_iw_register( 2 | input logic clk, rst, en, clr, 3 | input logic [31:0] pc_f, pc_plus_4_f, // instruction fetched and PC + 4 4 | 5 | output logic [31:0] pc_iw, pc_plus_4_iw // instruction to be decoded and PC + 4 6 | ); 7 | 8 | en_clr_arst_register #( 9 | .WIDTH(32) 10 | ) pc_f_d ( 11 | .d(pc_f), 12 | .q(pc_iw), 13 | .clk(clk), 14 | .rst(rst), 15 | .en(en), 16 | .clr(clr) 17 | ); 18 | 19 | en_clr_arst_register #( 20 | .WIDTH(32) 21 | ) pc_plus_4_f_d ( 22 | .d(pc_plus_4_f), 23 | .q(pc_plus_4_iw), 24 | .clk(clk), 25 | .rst(rst), 26 | .en(en), 27 | .clr(clr) 28 | ); 29 | 30 | endmodule 31 | -------------------------------------------------------------------------------- /riscv/gen_instr_mem.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import subprocess 3 | import re 4 | 5 | if len(sys.argv) != 3: 6 | print(f"Usage: {sys.argv[0]} ") 7 | sys.exit(1) 8 | 9 | input_elf = sys.argv[1] 10 | output_mem = sys.argv[2] 11 | 12 | # Dump instructions using objdump 13 | objdump = subprocess.check_output([ 14 | "riscv64-unknown-elf-objdump", 15 | "-d", "-M", "no-aliases", "--section=.text", input_elf 16 | ], encoding="utf-8") 17 | 18 | # Extract instruction hex codes 19 | lines = objdump.splitlines() 20 | instrs = [] 21 | for line in lines: 22 | m = re.match(r'\s*[0-9a-f]+:\s*([0-9a-f]{8})', line) 23 | if m: 24 | instrs.append(m.group(1)) 25 | 26 | # Write to output memory file 27 | with open(output_mem, "w") as f: 28 | for instr in instrs: 29 | f.write(instr + "\n") -------------------------------------------------------------------------------- /src/modules/sync/en_clr_arst_register.sv: -------------------------------------------------------------------------------- 1 | module en_clr_arst_register #( 2 | parameter WIDTH = 32, // Default width of the register 3 | parameter OFFSET = 0 // Default offset for the register 4 | ) ( 5 | input logic [WIDTH-1:0] d, // Data input 6 | output logic [WIDTH-1:0] q, // Data output 7 | input logic clk, rst, en, clr // Clock, reset, and enable signals 8 | ); 9 | 10 | // Asynchronous reset and synchronous enable 11 | always_ff @(posedge clk or posedge rst) begin 12 | if (rst) begin 13 | q <= OFFSET; // Reset the register to zero on reset 14 | end else if (clr) begin 15 | q <= '0; // Clear the register if clr is asserted, should be zero instead of offset 16 | end else if (en) begin 17 | q <= d; // Load the data into the register if enable is asserted 18 | end 19 | end 20 | 21 | endmodule 22 | -------------------------------------------------------------------------------- /riscv/Makefile: -------------------------------------------------------------------------------- 1 | RISCV_GCC = riscv64-unknown-elf-gcc 2 | RISCV_OBJDUMP = riscv64-unknown-elf-objdump 3 | RISCV_OBJCOPY = riscv64-unknown-elf-objcopy 4 | AS = riscv64-unknown-elf-as 5 | LD = riscv64-unknown-elf-ld 6 | PYTHON = python3 7 | 8 | ASFLAGS = -march=rv32i -mabi=ilp32 -Wall 9 | CFLAGS = -march=rv32i -mabi=ilp32 -Wall -O2 -nostdlib -ffreestanding 10 | LDFLAGS = -T linker.ld -nostdlib 11 | 12 | all: instr_init.mem 13 | 14 | crt0.o: crt0.s 15 | $(AS) $(ASFLAGS) -o ./out/$@ $< 16 | 17 | fibonacci.o: fibonacci.c 18 | $(RISCV_GCC) $(CFLAGS) -c -o ./out/$@ $< 19 | 20 | main.elf: crt0.o fibonacci.o 21 | $(RISCV_GCC) $(CFLAGS) ./out/crt0.o ./out/fibonacci.o -o ./out/$@ $(LDFLAGS) 22 | 23 | instr_init.mem: main.elf 24 | $(PYTHON) gen_instr_mem.py ./out/main.elf instr_init.mem 25 | 26 | clean: 27 | rm -f ./out/*.o /out/*.elf instr_init.mem 28 | 29 | dump: main.elf 30 | $(RISCV_OBJDUMP) -D -M no-aliases --section=.text ./out/main.elf -------------------------------------------------------------------------------- /src/modules/cpu/datapath/imm_extender.sv: -------------------------------------------------------------------------------- 1 | import signals::*; 2 | import types::*; 3 | 4 | module imm_extender( 5 | input immsrc_t immsrc, 6 | input imm_instr_t instr_31_7, 7 | output imm_ext_t imm_ext 8 | ); 9 | 10 | always_comb begin 11 | case (immsrc) 12 | IMMSRC_I_TYPE : imm_ext = {{20{instr_31_7[31]}}, instr_31_7[31:20]}; 13 | IMMSRC_UI_TYPE : imm_ext = {27'b0, instr_31_7[24:20]}; 14 | IMMSRC_S_TYPE : imm_ext = {{20{instr_31_7[31]}}, instr_31_7[31:25], instr_31_7[11:7]}; 15 | IMMSRC_B_TYPE : imm_ext = {{20{instr_31_7[31]}}, instr_31_7[7], instr_31_7[30:25], instr_31_7[11:8], 1'b0}; 16 | IMMSRC_J_TYPE : imm_ext = {{12{instr_31_7[31]}}, instr_31_7[19:12], instr_31_7[20], instr_31_7[30:21], 1'b0}; 17 | IMMSRC_U_TYPE : imm_ext = {instr_31_7[31:12], 12'b0}; 18 | default : imm_ext = 'hDEADBEEF; 19 | endcase 20 | 21 | end 22 | 23 | endmodule 24 | -------------------------------------------------------------------------------- /src/modules/memory/instruction_memory.sv: -------------------------------------------------------------------------------- 1 | import types::*; 2 | 3 | // Mock and fully combinational data memory, point is to be able to validate the pipeline without the hazard state machine (1 cycle read delay) 4 | module instruction_memory #( 5 | INITIAL = "" 6 | ) ( 7 | input logic clk, rst, en, 8 | input logic [13:0] addr, 9 | output logic [31:0] rdata 10 | ); 11 | 12 | (* ramstyle = "M9K" *) logic [31:0] data[0:16383]; // 16K words, 64KB of instruction memory 13 | logic [18:0] reg_addr; 14 | 15 | always_ff @(posedge clk) begin 16 | if(!rst && en) begin 17 | reg_addr <= addr; 18 | end 19 | end 20 | 21 | assign rdata = data[reg_addr]; 22 | 23 | initial begin 24 | if(INITIAL != "") begin 25 | $display("Initializing instruction memory from %s", INITIAL); 26 | $readmemh(INITIAL, data); 27 | end 28 | end 29 | 30 | endmodule 31 | -------------------------------------------------------------------------------- /src/peripherals/sevenseg.sv: -------------------------------------------------------------------------------- 1 | module sevenseg( 2 | input logic [3:0] data, 3 | output logic [6:0] segments 4 | ); 5 | 6 | always_comb 7 | begin 8 | case (data) 9 | 4'h0: 10 | segments = 7'h40; 11 | 4'h1: 12 | segments = 7'h79; 13 | 4'h2: 14 | segments = 7'h24; 15 | 4'h3: 16 | segments = 7'h30; 17 | 4'h4: 18 | segments = 7'h19; 19 | 4'h5: 20 | segments = 7'h12; 21 | 4'h6: 22 | segments = 7'h2; 23 | 4'h7: 24 | segments = 7'h78; 25 | 4'h8: 26 | segments = 7'h0; 27 | 4'h9: 28 | segments = 7'h18; 29 | 4'ha: 30 | segments = 7'h8; 31 | 4'hb: 32 | segments = 7'h3; 33 | 4'hc: 34 | segments = 7'h27; 35 | 4'hd: 36 | segments = 7'h21; 37 | 4'he: 38 | segments = 7'h6; 39 | 4'hf: 40 | segments = 7'he; 41 | default: 42 | begin 43 | segments = 7'b1111111; 44 | end 45 | endcase 46 | end 47 | 48 | endmodule 49 | -------------------------------------------------------------------------------- /src/modules/cpu/datapath/iw_d_register.sv: -------------------------------------------------------------------------------- 1 | module iw_d_register( 2 | input logic clk, rst, en, clr, 3 | input logic [31:0] instr_iw, pc_iw, pc_plus_4_iw, // instruction fetched and PC + 4 4 | 5 | output logic [31:0] instr_d, pc_d, pc_plus_4_d // instruction to be decoded and PC + 4 6 | ); 7 | 8 | en_clr_arst_register #( 9 | .WIDTH(32) 10 | ) instr_f_d ( 11 | .d(instr_iw), 12 | .q(instr_d), 13 | .clk(clk), 14 | .rst(rst), 15 | .en(en), 16 | .clr(clr) 17 | ); 18 | 19 | en_clr_arst_register #( 20 | .WIDTH(32) 21 | ) pc_f_d ( 22 | .d(pc_iw), 23 | .q(pc_d), 24 | .clk(clk), 25 | .rst(rst), 26 | .en(en), 27 | .clr(clr) 28 | ); 29 | 30 | en_clr_arst_register #( 31 | .WIDTH(32) 32 | ) pc_plus_4_f_d ( 33 | .d(pc_plus_4_iw), 34 | .q(pc_plus_4_d), 35 | .clk(clk), 36 | .rst(rst), 37 | .en(en), 38 | .clr(clr) 39 | ); 40 | 41 | endmodule 42 | -------------------------------------------------------------------------------- /src/modules/cpu/hazard_unit/lw_fsm.sv: -------------------------------------------------------------------------------- 1 | import types::*; 2 | 3 | module lw_fsm( 4 | input logic clk, rst, lwstall, readdatavalid, 5 | output logic readdatawait 6 | ); 7 | 8 | lw_fsm_state_t nextstate, state; 9 | 10 | // Next state logic 11 | always_comb begin 12 | case(state) 13 | LW_NOT_LW: begin 14 | if(lwstall) begin 15 | nextstate = LW_WAITING_READVALID; 16 | end else begin 17 | nextstate = LW_NOT_LW; 18 | end 19 | end 20 | LW_WAITING_READVALID: begin 21 | if(readdatavalid) begin 22 | nextstate = LW_NOT_LW; 23 | end else begin 24 | nextstate = LW_WAITING_READVALID; 25 | end 26 | end 27 | default: nextstate = LW_NOT_LW; 28 | endcase 29 | end 30 | 31 | // FSM Register 32 | always_ff @(posedge clk or posedge rst) begin 33 | if(rst) begin 34 | state <= LW_NOT_LW; 35 | end else begin 36 | state <= nextstate; 37 | end 38 | end 39 | 40 | // Output logic 41 | assign readdatawait = state == LW_WAITING_READVALID; 42 | 43 | 44 | endmodule 45 | -------------------------------------------------------------------------------- /src/modules/cpu/datapath/alu.sv: -------------------------------------------------------------------------------- 1 | import types::*; 2 | 3 | module alu( 4 | input logic [31:0] a, b, 5 | input alu_op_t alu_op, 6 | output logic [31:0] result, 7 | output logic zero 8 | ); 9 | 10 | always_comb begin 11 | case (alu_op) 12 | ALU_OP_ADD: result = a + b; 13 | ALU_OP_SUB: result = a - b; 14 | ALU_OP_AND: result = a & b; 15 | ALU_OP_OR : result = a | b; 16 | ALU_OP_SLT: result = ($signed(a) < $signed(b)) ? 1 : 0; 17 | ALU_OP_SLTU: result = (a < b) ? 1 : 0; 18 | ALU_OP_SGE: result = ($signed(a) >= $signed(b)) ? 1 : 0; 19 | ALU_OP_SGEU: result = (a >= b) ? 1 : 0; 20 | ALU_OP_XOR: result = a ^ b; 21 | ALU_OP_SLL: result = a << b[4:0]; 22 | ALU_OP_SRL: result = a >> b[4:0]; 23 | ALU_OP_SRA: result = $signed(a) >>> b[4:0]; 24 | default : result = 'hDEADBEEF; // Undefined operation 25 | endcase 26 | 27 | zero = (result == 32'b0) ? 1'b1 : 1'b0; // Set zero flag if result is zero 28 | end 29 | 30 | 31 | endmodule 32 | -------------------------------------------------------------------------------- /src/modules/cpu/datapath/byte_store_unit.sv: -------------------------------------------------------------------------------- 1 | // The byte store unit is responsible for shitfing and masking bytes before storing them 2 | // It performs shifting based on the byte_half_sel_m signal 3 | import types::*; 4 | 5 | module byte_store_unit( 6 | input logic [31:0] data_in, // Data to be stored 7 | input byte_half_sel_t byte_half_sel_m, // Byte/half select signal 8 | output logic [31:0] data_out // Data to be stored after shifting and masking 9 | ); 10 | 11 | always_comb begin 12 | data_out = data_in; // Default to input data 13 | case(byte_half_sel_m) 14 | BYTE_HALF_BYTE_0: data_out = {24'b0, data_in[7:0]}; // Store byte 0 15 | BYTE_HALF_BYTE_1: data_out = {16'b0, data_in[7:0], 8'b0}; // Store byte 1 16 | BYTE_HALF_BYTE_2: data_out = {8'b0, data_in[7:0], 16'b0}; // Store byte 2 17 | BYTE_HALF_BYTE_3: data_out = {data_in[7:0], 24'b0}; // Store byte 3 18 | BYTE_HALF_HALF_0: data_out = {16'b0, data_in[15:0]}; // Store halfword 0 19 | BYTE_HALF_HALF_1: data_out = {data_in[15:0], 16'b0}; // Store halfword 20 | default: data_out = data_in; // No shift or mask, just pass through 21 | endcase 22 | end 23 | 24 | 25 | endmodule 26 | -------------------------------------------------------------------------------- /src/modules/memory/gprmm_registers.sv: -------------------------------------------------------------------------------- 1 | import io::*; 2 | 3 | module gprmm_registers( 4 | // Signals 5 | input logic clk, rst, wen, 6 | // Inputs 7 | input logic [31:0] rwaddr, 8 | input logic [31:0] wdata, 9 | // Outputs 10 | output logic [31:0] rdata, 11 | output GPREGS_T GPREGS 12 | ); 13 | 14 | // Address space checking 15 | logic valid; 16 | assign valid = rwaddr >= GPRMMSTART && rwaddr < GPRMMEND; 17 | 18 | // Write port 19 | always_ff @(posedge clk or posedge rst) begin 20 | if(rst) begin 21 | GPREGS <= '0; 22 | end else if(wen && valid) begin 23 | case (rwaddr) 24 | GPRMM1 : GPREGS.GPR1 <= wdata; 25 | GPRMM2 : GPREGS.GPR2 <= wdata; 26 | default : ; // We do nothing 27 | endcase 28 | 29 | end 30 | end 31 | 32 | always_comb begin 33 | rdata = 32'hDEADBEEF; 34 | if(wen) begin 35 | rdata = wdata; 36 | end else begin 37 | case(rwaddr) 38 | GPRMM1 : rdata = GPREGS.GPR1; 39 | GPRMM2 : rdata = GPREGS.GPR2; 40 | default : rdata = 32'hDEADBEEF; 41 | endcase 42 | end 43 | end 44 | 45 | 46 | 47 | endmodule 48 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | dokifive_p50 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.xtext.ui.shared.xtextBuilder 10 | 11 | 12 | 13 | 14 | 15 | com.sigasi.hdt.verilog.ui.verilogNature 16 | com.sigasi.hdt.vhdl.ui.vhdlNature 17 | org.eclipse.xtext.ui.shared.xtextNature 18 | 19 | 20 | 21 | Common Libraries 22 | 2 23 | virtual:/virtual 24 | 25 | 26 | Common Libraries/IEEE 27 | 2 28 | sigasiresource:/vhdl/2008/IEEE 29 | 30 | 31 | Common Libraries/IEEE Synopsys 32 | 2 33 | sigasiresource:/vhdl/2008/IEEE%20Synopsys 34 | 35 | 36 | Common Libraries/STD 37 | 2 38 | sigasiresource:/vhdl/2008/STD 39 | 40 | 41 | Common Libraries/altera_mf_ver 42 | 2 43 | SIGASI_LIBRARY_ALTERA_MF_VER 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2025, Dokitek SARL 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the [YOUR NAME or ORGANIZATION] nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /src/modules/cpu/control_unit/control_m_w_register.sv: -------------------------------------------------------------------------------- 1 | import types::*; 2 | 3 | module control_m_w_register( 4 | input logic clk, rst, en, clr, 5 | // Debug input 6 | input logic [31:0] instr_m, // Debug input 7 | // Debug output 8 | output logic [31:0] instr_w, // Debug output 9 | // Memory inputs 10 | input bool_t reg_write_m, 11 | input result_src_t result_src_m, 12 | // Writeback outputs 13 | output bool_t reg_write_w, 14 | output result_src_t result_src_w 15 | ); 16 | 17 | // Intermediate logic vectors 18 | logic [0:0] reg_write_m_vec; 19 | assign reg_write_w = bool_t'(reg_write_m_vec); 20 | 21 | logic [$bits(result_src_t)-1:0] result_src_w_vec; 22 | assign result_src_w = result_src_t'(result_src_w_vec); 23 | 24 | // MEMORY_WRITEBACK REGISTER 25 | en_clr_arst_register #( 26 | .WIDTH(1) 27 | ) reg_write_m_w ( 28 | .d(reg_write_m), 29 | .q(reg_write_m_vec), 30 | .clk(clk), 31 | .rst(rst), 32 | .en(en), 33 | .clr(clr) 34 | ); 35 | 36 | en_clr_arst_register #( 37 | .WIDTH($bits(result_src_t)) 38 | ) result_src_m_w ( 39 | .d(result_src_m), 40 | .q(result_src_w_vec), 41 | .clk(clk), 42 | .rst(rst), 43 | .en(en), 44 | .clr(clr) 45 | ); 46 | 47 | en_clr_arst_register #( 48 | .WIDTH(32) 49 | ) instr_m_w ( 50 | .d(instr_m), 51 | .q(instr_w), 52 | .clk(clk), 53 | .rst(rst), 54 | .en(en), 55 | .clr(clr) 56 | ); 57 | 58 | endmodule 59 | -------------------------------------------------------------------------------- /src/modules/cpu/datapath/e_m_register.sv: -------------------------------------------------------------------------------- 1 | module e_m_register( 2 | input logic clk, rst, en, clr, 3 | input logic [31:0] alu_result_e, w_data_e, pc_plus_4_e, imm_ext_e, 4 | input logic [4:0] wa3_e, // write address for the register file 5 | 6 | output logic [31:0] alu_result_m, w_data_m, pc_plus_4_m, imm_ext_m, 7 | output logic [4:0] wa3_m // write address for the register file 8 | ); 9 | 10 | // EXECUTE_MEMORY REGISTER 11 | en_clr_arst_register #( 12 | .WIDTH(32) 13 | ) alu_result_e_m ( 14 | .d(alu_result_e), 15 | .q(alu_result_m), 16 | .clk(clk), 17 | .rst(rst), 18 | .en(en), 19 | .clr(clr) 20 | ); 21 | 22 | en_clr_arst_register #( 23 | .WIDTH(32) 24 | ) w_data_e_m ( 25 | .d(w_data_e), 26 | .q(w_data_m), 27 | .clk(clk), 28 | .rst(rst), 29 | .en(en), 30 | .clr(clr) 31 | ); 32 | 33 | en_clr_arst_register #( 34 | .WIDTH(32) 35 | ) pc_plus_4_e_m ( 36 | .d(pc_plus_4_e), 37 | .q(pc_plus_4_m), 38 | .clk(clk), 39 | .rst(rst), 40 | .en(en), 41 | .clr(clr) 42 | ); 43 | 44 | en_clr_arst_register #( 45 | .WIDTH(5) 46 | ) wa3_e_m ( 47 | .d(wa3_e), 48 | .q(wa3_m), 49 | .clk(clk), 50 | .rst(rst), 51 | .en(en), 52 | .clr(clr) 53 | ); 54 | 55 | en_clr_arst_register #( 56 | .WIDTH(32) 57 | ) imm_ext_e_m ( 58 | .d(imm_ext_e), 59 | .q(imm_ext_m), 60 | .clk(clk), 61 | .rst(rst), 62 | .en(en), 63 | .clr(clr) 64 | ); 65 | 66 | endmodule 67 | -------------------------------------------------------------------------------- /src/modules/cpu/datapath/m_w_register.sv: -------------------------------------------------------------------------------- 1 | module m_w_register( 2 | input logic clk, rst, en, clr, 3 | // input nets 4 | input logic [31:0] alu_result_m, r_data_m, pc_plus_4_m, imm_ext_m, 5 | input logic [4:0] wa3_m, // write address for the register file 6 | 7 | // output nets 8 | output logic [31:0] alu_result_w, r_data_w, pc_plus_4_w, imm_ext_w, // Multiplexer inputs for the writeback stage 9 | output logic [4:0] wa3_w // write address for the register file 10 | ); 11 | 12 | // MEMORY_WRITEBACK REGISTER 13 | en_clr_arst_register #( 14 | .WIDTH(32) 15 | ) alu_result_m_w ( 16 | .d(alu_result_m), 17 | .q(alu_result_w), 18 | .clk(clk), 19 | .rst(rst), 20 | .en(en), 21 | .clr(clr) 22 | ); 23 | 24 | en_clr_arst_register #( 25 | .WIDTH(32) 26 | ) r_data_m_w ( 27 | .d(r_data_m), 28 | .q(r_data_w), 29 | .clk(clk), 30 | .rst(rst), 31 | .en(en), 32 | .clr(clr) 33 | ); 34 | 35 | en_clr_arst_register #( 36 | .WIDTH(32) 37 | ) pc_plus_4_m_w ( 38 | .d(pc_plus_4_m), 39 | .q(pc_plus_4_w), 40 | .clk(clk), 41 | .rst(rst), 42 | .en(en), 43 | .clr(clr) 44 | ); 45 | 46 | en_clr_arst_register #( 47 | .WIDTH(5) 48 | ) wa3_m_w ( 49 | .d(wa3_m), 50 | .q(wa3_w), 51 | .clk(clk), 52 | .rst(rst), 53 | .en(en), 54 | .clr(clr) 55 | ); 56 | 57 | en_clr_arst_register #( 58 | .WIDTH(32) 59 | ) imm_ext_m_w ( 60 | .d(imm_ext_m), 61 | .q(imm_ext_w), 62 | .clk(clk), 63 | .rst(rst), 64 | .en(en), 65 | .clr(clr) 66 | ); 67 | 68 | endmodule 69 | -------------------------------------------------------------------------------- /tests/tb_imm_extender.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ps / 1ps 2 | 3 | import types::*; 4 | module tb_imm_extender(); 5 | // Inputs 6 | immsrc_t immsrc; 7 | logic [31:0] instr; 8 | // Outputs 9 | logic [31:0] imm_ext; 10 | 11 | // Instantiate the Unit Under Test (UUT) 12 | imm_extender uut ( 13 | .immsrc(immsrc), 14 | .instr_31_7(instr[31:7]), 15 | .imm_ext(imm_ext) 16 | ); 17 | 18 | // Test vectors 19 | initial begin 20 | $display("Starting testbench for imm_extender"); 21 | 22 | // I-Type: addi s0, s0, 1337 23 | immsrc = IMMSRC_I_TYPE; 24 | instr = 32'h53980113; // 0x53980113 25 | #10; 26 | $display("I_TYPE (addi x2, x16, 1337): instr=0x%h, imm_ext=%d", instr, imm_ext); 27 | 28 | // S-Type: sw s0, 1337(t0) 29 | immsrc = IMMSRC_S_TYPE; 30 | instr = 32'h53988223; // 0x53988223 31 | #10; 32 | $display("S_TYPE (sb x25, 1316(x17): instr=0x%h, imm_ext=%d", instr, imm_ext); 33 | 34 | // B-Type: beq s0, t0, 1336 35 | immsrc = IMMSRC_B_TYPE; 36 | instr = 32'h53888463; // 0x53888463 37 | #10; 38 | $display("B_TYPE (beq x17, x24, 1320): instr=0x%h, imm_ext=%d", instr, imm_ext); 39 | 40 | // J-Type: jal s0, 1336 41 | immsrc = IMMSRC_J_TYPE; 42 | instr = 32'h5380106f; // 0x5380106f 43 | #10; 44 | $display("J_TYPE (jal x0, 5432): instr=0x%h, imm_ext=%d", instr, imm_ext); 45 | 46 | // U-Type: lui s0, 0x12345 47 | immsrc = IMMSRC_U_TYPE; 48 | instr = 32'h12345137; // 0x12345137 49 | #10; 50 | $display("U_TYPE (lui x2, 74565): instr=0x%h, imm_ext=%h", instr, imm_ext); 51 | 52 | $display("Testbench completed"); 53 | $stop; 54 | end 55 | 56 | endmodule -------------------------------------------------------------------------------- /src/modules/dokifive_soc.sv: -------------------------------------------------------------------------------- 1 | import types::*; 2 | import io::*; 3 | 4 | module dokifive_soc #( 5 | parameter INITIAL_INSTR = "" 6 | ) ( 7 | input logic clk, rst, 8 | 9 | // Memory mapped IO 10 | output GPREGS_T GPREGS 11 | ); 12 | 13 | // Wire definition 14 | bool_t mem_write; 15 | logic stall_f; 16 | logic flush_d; 17 | logic read_en; 18 | logic [31:0] instr_addr, instr_data, mem_addr, mem_data_r, mem_data_w; 19 | byte_half_sel_t byteenablea; 20 | 21 | // We need a registered flush_d signal (1 clock cycle behind !flush_d signal) 22 | // Because our memory has a registered address but not a registered output 23 | en_clr_arst_register #( 24 | .WIDTH(1) 25 | ) en_clr_arst_register_instance ( 26 | .d(~flush_d), 27 | .q(read_en), 28 | .clk(clk), 29 | .rst(rst), 30 | .en(~rst), 31 | .clr(1'b0) 32 | ); 33 | 34 | cpu cpu_instance ( 35 | .clk(clk), 36 | .rst(rst), 37 | .instr_data(instr_data), 38 | .mem_data_r(mem_data_r), 39 | .instr_addr(instr_addr), 40 | .mem_addr_m(mem_addr), 41 | .mem_data_w(mem_data_w), 42 | .mem_write(mem_write), 43 | .stall_f(stall_f), 44 | .flush_d(flush_d), 45 | .byte_half_sel_m(byteenablea) 46 | ); 47 | 48 | memory_controller #( 49 | .INITIAL_MOCK_INSTR(INITIAL_INSTR) 50 | ) memory_controller_instance ( 51 | .clk(clk), 52 | .rst(rst), 53 | .stall_f(stall_f), 54 | .read_en(read_en), 55 | .instr_addr(instr_addr), 56 | .instr_data(instr_data), 57 | .mem_write(mem_write), 58 | .mem_addr(mem_addr), 59 | .mem_write_data(mem_data_w), 60 | .mem_read_data(mem_data_r), 61 | .byteenablea(byteenablea), 62 | .GPREGS(GPREGS) 63 | ); 64 | 65 | endmodule 66 | -------------------------------------------------------------------------------- /simulation/wave.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | quietly WaveActivateNextPane {} 0 3 | add wave -noupdate /tb_soc/clk 4 | add wave -noupdate /tb_soc/rst 5 | add wave -noupdate /tb_soc/uut/instr_addr 6 | add wave -noupdate /tb_soc/uut/instr_data 7 | add wave -noupdate /tb_soc/uut/mem_addr 8 | add wave -noupdate /tb_soc/uut/mem_data_r 9 | add wave -noupdate /tb_soc/uut/cpu_instance/datapath_instance/f_iw_register_instance/pc_f 10 | add wave -noupdate /tb_soc/uut/cpu_instance/datapath_instance/f_d_register_instance/pc_iw 11 | add wave -noupdate /tb_soc/uut/cpu_instance/datapath_instance/d_e_register_instance/pc_d 12 | add wave -noupdate /tb_soc/uut/cpu_instance/datapath_instance/d_e_register_instance/pc_e 13 | add wave -noupdate /tb_soc/uut/memory_controller_instance/data_memory_instance/addr 14 | add wave -noupdate /tb_soc/uut/memory_controller_instance/data_memory_instance/wdata 15 | add wave -noupdate /tb_soc/uut/memory_controller_instance/data_memory_instance/rdata 16 | add wave -noupdate /tb_soc/uut/memory_controller_instance/data_memory_instance/data 17 | add wave -noupdate /tb_soc/uut/memory_controller_instance/data_valid 18 | add wave -noupdate /tb_soc/uut/cpu_instance/datapath_instance/rf/we3 19 | add wave -noupdate /tb_soc/uut/cpu_instance/datapath_instance/rf/wa3 20 | add wave -noupdate /tb_soc/uut/cpu_instance/datapath_instance/rf/wd3 21 | add wave -noupdate /tb_soc/uut/cpu_instance/datapath_instance/rf/rf 22 | TreeUpdate [SetDefaultTree] 23 | WaveRestoreCursors {{Cursor 1} {0 ps} 0} 24 | quietly wave cursor active 1 25 | configure wave -namecolwidth 513 26 | configure wave -valuecolwidth 184 27 | configure wave -justifyvalue left 28 | configure wave -signalnamewidth 0 29 | configure wave -snapdistance 10 30 | configure wave -datasetprefix 0 31 | configure wave -rowmargin 4 32 | configure wave -childrowmargin 2 33 | configure wave -gridoffset 0 34 | configure wave -gridperiod 1 35 | configure wave -griddelta 40 36 | configure wave -timeline 0 37 | configure wave -timelineunits ps 38 | update 39 | WaveRestoreZoom {0 ps} {1584 ps} 40 | -------------------------------------------------------------------------------- /src/modules/cpu/control_unit/byte_half_decoder.sv: -------------------------------------------------------------------------------- 1 | import types::*; 2 | 3 | module byte_half_decoder( 4 | input logic byte_half_en_m, 5 | input logic [2:0] funct3_m, 6 | input logic [1:0] mem_addr_m, 7 | output byte_half_sel_t byte_half_sel, 8 | output word_ext_t word_ext 9 | ); 10 | 11 | // Byte select 12 | always_comb begin 13 | if(byte_half_en_m) begin 14 | casez (funct3_m) 15 | 3'b?00 : begin // For LB, we look at individual byte addressing , we don't care about byte 2 because it's used for the sign extension 16 | case (mem_addr_m[1:0]) 17 | 2'b00 : byte_half_sel = BYTE_HALF_BYTE_0; // Mask for byte 0 18 | 2'b01 : byte_half_sel = BYTE_HALF_BYTE_1; // Mask for byte 1 19 | 2'b10 : byte_half_sel = BYTE_HALF_BYTE_2; // Mask for byte 2 20 | 2'b11 : byte_half_sel = BYTE_HALF_BYTE_3; // Mask for byte 3 21 | default: byte_half_sel = BYTE_HALF_NONE; // No mask 22 | endcase 23 | end 24 | 3'b?01 : begin // For LH, we look at individual halfword addressing 25 | case (mem_addr_m[1:0]) 26 | 2'b00 : byte_half_sel = BYTE_HALF_HALF_0; // Mask for halfword 0 27 | 2'b10 : byte_half_sel = BYTE_HALF_HALF_1; // Mask for halfword 1 28 | default: byte_half_sel = BYTE_HALF_NONE; // No mask, undefined behavior as per RISC-V spec 29 | endcase 30 | end 31 | default: begin // LW, we don't care about the byte addressing, we just want the whole word 32 | byte_half_sel = BYTE_HALF_NONE; // No mask 33 | end 34 | endcase 35 | end else begin 36 | byte_half_sel = BYTE_HALF_NONE; // No mask, undefined behavior as per RISC-V spec 37 | end 38 | end 39 | 40 | // Extension select 41 | assign word_ext = (funct3_m[2] && byte_half_en_m) ? WORD_EXT_ZERO : WORD_EXT_SIGN; 42 | 43 | endmodule 44 | -------------------------------------------------------------------------------- /src/modules/cpu/datapath/byte_load_unit.sv: -------------------------------------------------------------------------------- 1 | import types::*; 2 | module byte_load_unit( 3 | input logic [31:0] data_in, // Data to be loaded 4 | input byte_half_sel_t byte_half_sel_m, // Byte/half select signal 5 | input word_ext_t word_ext_m, // Word extension signal 6 | 7 | output logic [31:0] data_out // Data to be loaded after shifting and masking 8 | ); 9 | 10 | always_comb begin 11 | data_out = data_in; // Default to input data 12 | case(word_ext_m) 13 | WORD_EXT_ZERO: begin 14 | case(byte_half_sel_m) 15 | BYTE_HALF_BYTE_0: data_out = {24'b0, data_in[7:0]}; // Load byte 0 16 | BYTE_HALF_BYTE_1: data_out = {24'b0, data_in[15:8]}; // Load byte 1 17 | BYTE_HALF_BYTE_2: data_out = {24'b0, data_in[23:16]}; // Load byte 2 18 | BYTE_HALF_BYTE_3: data_out = {24'b0, data_in[31:24]}; // Load byte 3 19 | BYTE_HALF_HALF_0: data_out = {16'b0, data_in[15:0]}; // Load halfword 0 20 | BYTE_HALF_HALF_1: data_out = {16'b0, data_in[31:16]}; // Load halfword 1 21 | default: data_out = data_in; // No shift or mask, just pass through 22 | endcase 23 | end 24 | WORD_EXT_SIGN: begin 25 | case(byte_half_sel_m) 26 | BYTE_HALF_BYTE_0: data_out = {{24{data_in[7]}}, data_in[7:0]}; // Load byte 0 with sign extension 27 | BYTE_HALF_BYTE_1: data_out = {{24{data_in[15]}}, data_in[15:8]}; // Load byte 1 with sign extension 28 | BYTE_HALF_BYTE_2: data_out = {{24{data_in[23]}}, data_in[23:16]}; // Load byte 2 with sign extension 29 | BYTE_HALF_BYTE_3: data_out = {{24{data_in[31]}}, data_in[31:24]}; // Load byte 3 with sign extension 30 | BYTE_HALF_HALF_0: data_out = {{16{data_in[15]}}, data_in[15:0]}; // Load halfword 0 with sign extension 31 | BYTE_HALF_HALF_1: data_out = {{16{data_in[31]}}, data_in[31:16]}; // Load halfword 1 with sign extension 32 | default: data_out = data_in; // No shift or mask, just pass through 33 | endcase 34 | end 35 | default: data_out = data_in; // No shift or mask, just pass through 36 | endcase 37 | end 38 | 39 | 40 | endmodule 41 | -------------------------------------------------------------------------------- /src/modules/cpu/datapath/d_e_register.sv: -------------------------------------------------------------------------------- 1 | module d_e_register( 2 | input logic clk, rst, en, clr, 3 | // input nets 4 | input logic [31:0] rd1_d, rd2_d, imm_ext_d, pc_d, pc_plus_4_d, 5 | input logic [4:0] ra1_d, ra2_d, wa3_d, // source registers addresses 6 | // output nets 7 | output logic [31:0] rd1_e, rd2_e, imm_ext_e, pc_e, pc_plus_4_e, 8 | output logic [4:0] ra1_e, ra2_e, wa3_e // source registers addresses 9 | ); 10 | 11 | // DECODE_EXECUTE REGISTER 12 | en_clr_arst_register #( 13 | .WIDTH(32) 14 | ) rd1_d_e ( 15 | .d(rd1_d), 16 | .q(rd1_e), 17 | .clk(clk), 18 | .rst(rst), 19 | .en(en), 20 | .clr(clr) 21 | ); 22 | 23 | en_clr_arst_register #( 24 | .WIDTH(32) 25 | ) rd2_d_e ( 26 | .d(rd2_d), 27 | .q(rd2_e), 28 | .clk(clk), 29 | .rst(rst), 30 | .en(en), 31 | .clr(clr) 32 | ); 33 | 34 | en_clr_arst_register #( 35 | .WIDTH(32) 36 | ) imm_ext_d_e ( 37 | .d(imm_ext_d), 38 | .q(imm_ext_e), 39 | .clk(clk), 40 | .rst(rst), 41 | .en(en), 42 | .clr(clr) 43 | ); 44 | 45 | en_clr_arst_register #( 46 | .WIDTH(32) 47 | ) pc_d_e ( 48 | .d(pc_d), 49 | .q(pc_e), 50 | .clk(clk), 51 | .rst(rst), 52 | .en(en), 53 | .clr(clr) 54 | ); 55 | 56 | en_clr_arst_register #( 57 | .WIDTH(32) 58 | ) pc_plus_4_d_e ( 59 | .d(pc_plus_4_d), 60 | .q(pc_plus_4_e), 61 | .clk(clk), 62 | .rst(rst), 63 | .en(en), 64 | .clr(clr) 65 | ); 66 | 67 | en_clr_arst_register #( 68 | .WIDTH(5) 69 | ) ra1_d_e ( 70 | .d(ra1_d), 71 | .q(ra1_e), 72 | .clk(clk), 73 | .rst(rst), 74 | .en(en), 75 | .clr(clr) 76 | ); 77 | 78 | en_clr_arst_register #( 79 | .WIDTH(5) 80 | ) ra2_d_e ( 81 | .d(ra2_d), 82 | .q(ra2_e), 83 | .clk(clk), 84 | .rst(rst), 85 | .en(en), 86 | .clr(clr) 87 | ); 88 | 89 | en_clr_arst_register #( 90 | .WIDTH(5) 91 | ) wa3_d_e ( 92 | .d(wa3_d), 93 | .q(wa3_e), 94 | .clk(clk), 95 | .rst(rst), 96 | .en(en), 97 | .clr(clr) 98 | ); 99 | 100 | endmodule 101 | -------------------------------------------------------------------------------- /tests/tb_alu.sv: -------------------------------------------------------------------------------- 1 | // Testbench for ALU 2 | // filepath: tests/tb_alu.sv 3 | 4 | `timescale 10ps/1ps 5 | import types::*; 6 | 7 | module tb_alu; 8 | // Inputs 9 | logic [31:0] a, b; 10 | alu_op_t alu_op; 11 | // Outputs 12 | logic [31:0] result; 13 | logic zero; 14 | 15 | // Instantiate the ALU 16 | alu dut( 17 | .a(a), 18 | .b(b), 19 | .alu_op(alu_op), 20 | .result(result), 21 | .zero(zero) 22 | ); 23 | 24 | // Test vector struct 25 | typedef struct { 26 | logic [31:0] a, b; 27 | alu_op_t alu_op; 28 | logic [31:0] expected_result; 29 | logic expected_zero; 30 | string desc; 31 | } alu_vec_t; 32 | 33 | // Test vectors 34 | alu_vec_t vectors[] = '{ 35 | '{32'd10, 32'd5, ALU_OP_ADD, 32'd15, 1'b0, "ADD"}, 36 | '{32'd10, 32'd5, ALU_OP_SUB, 32'd5, 1'b0, "SUB"}, 37 | '{32'hF0F0F0F0, 32'h0F0F0F0F, ALU_OP_AND, 32'h00000000, 1'b1, "AND"}, 38 | '{32'hF0F0F0F0, 32'h0F0F0F0F, ALU_OP_OR, 32'hFFFFFFFF, 1'b0, "OR"}, 39 | '{-32'd5, 32'd10, ALU_OP_SLT, 32'd1, 1'b0, "SLT (signed)"}, 40 | '{32'd10, 32'd5, ALU_OP_SLT, 32'd0, 1'b1, "SLT (signed, zero)"}, 41 | '{32'd5, 32'd10, ALU_OP_SLTU, 32'd1, 1'b0, "SLTU (unsigned)"}, 42 | '{32'd10, 32'd5, ALU_OP_SLTU, 32'd0, 1'b1, "SLTU (unsigned, zero)"}, 43 | '{32'd5, 32'd10, ALU_OP_SGE, 32'd0, 1'b1, "SGE (signed)"}, 44 | '{32'd10, 32'd5, ALU_OP_SGE, 32'd1, 1'b0, "SGE (signed)"}, 45 | '{32'd5, 32'd10, ALU_OP_SGEU, 32'd0, 1'b1, "SGEU (unsigned)"}, 46 | '{32'd10, 32'd5, ALU_OP_SGEU, 32'd1, 1'b0, "SGEU (unsigned)"}, 47 | '{32'hAAAA5555, 32'h5555AAAA, ALU_OP_XOR, 32'hFFFFFFFF, 1'b0, "XOR"}, 48 | '{32'h00000001, 32'd4, ALU_OP_SLL, 32'h00000010, 1'b0, "SLL"}, 49 | '{32'h10, 32'd2, ALU_OP_SRL, 32'h4, 1'b0, "SRL"}, 50 | '{32'h80000000, 32'd1, ALU_OP_SRA, 32'hC0000000, 1'b0, "SRA (arithmetic right shift)"}, 51 | '{32'd0, 32'd0, ALU_OP_ADD, 32'd0, 1'b1, "ADD zero"}, 52 | '{32'd0, 32'd0, ALU_OP_SUB, 32'd0, 1'b1, "SUB zero"} 53 | }; 54 | 55 | initial begin 56 | $display("Starting ALU testbench..."); 57 | foreach (vectors[i]) begin 58 | a = vectors[i].a; 59 | b = vectors[i].b; 60 | alu_op = vectors[i].alu_op; 61 | #1; // Wait for combinational logic to settle 62 | if (result !== vectors[i].expected_result || zero !== vectors[i].expected_zero) begin 63 | $error("Test %0d (%s) FAILED: a=%h b=%h alu_op=%0d | result=%h (expected %h) zero=%b (expected %b)", 64 | i, vectors[i].desc, a, b, alu_op, result, vectors[i].expected_result, zero, vectors[i].expected_zero); 65 | $stop; 66 | end else begin 67 | $display("Test %0d (%s) PASSED", i, vectors[i].desc); 68 | end 69 | end 70 | $display("All ALU tests PASSED."); 71 | $stop; 72 | end 73 | endmodule 74 | -------------------------------------------------------------------------------- /src/modules/memory/memory_controller.sv: -------------------------------------------------------------------------------- 1 | import types::*; 2 | import io::*; 3 | module memory_controller #( 4 | parameter INITIAL_MOCK_INSTR = "" 5 | ) ( 6 | input logic clk, rst, 7 | // Hazard signals 8 | input logic stall_f, 9 | input logic read_en, // we need a registered read_en (1 clock cycle behind !flush_d signal) 10 | 11 | // Port A, instruction memory 12 | input logic [31:0] instr_addr, 13 | output logic [31:0] instr_data, 14 | // Port B, data memory 15 | input bool_t mem_write, 16 | input logic [31:0] mem_addr, mem_write_data, 17 | output logic [31:0] mem_read_data, 18 | input byte_half_sel_t byteenablea, 19 | 20 | // Memory mapped IO 21 | output GPREGS_T GPREGS 22 | ); 23 | localparam INSTRUCTION_ROM_START = 'h0; 24 | localparam INSTRUCTION_ROM_END = 'h10000; // 64KB of ROM 25 | localparam DATA_RAM_START = 'h10000000; 26 | localparam DATA_RAM_END = 'h10008000; // 32KB of RAM 27 | 28 | // Instruction 29 | logic [31:0] instr_data_raw; 30 | logic instruction_valid; 31 | 32 | always_comb begin 33 | instruction_valid = instr_addr >= INSTRUCTION_ROM_START && instr_addr < INSTRUCTION_ROM_END; 34 | if(!instruction_valid) begin 35 | instr_data = 'hDEADBEEF; 36 | end else if(!read_en) begin 37 | instr_data = 'h0; // zero out the instruction, like we've done on the decode stage 38 | end else begin 39 | instr_data = instr_data_raw; 40 | end 41 | end 42 | 43 | 44 | // RAM 45 | logic [31:0] mem_data_raw; 46 | logic data_valid; 47 | bool_t write_valid; 48 | assign data_valid = mem_addr >= DATA_RAM_START && mem_addr < DATA_RAM_END; 49 | assign write_valid = (data_valid && mem_write == TRUE) ? TRUE : FALSE; 50 | // GPRMM 51 | logic [31:0] gprmm_read_raw; 52 | 53 | 54 | // MEM READ DATA MULTIPLEXER 55 | always_comb begin 56 | mem_read_data = 32'hDEADBEEF; 57 | if(mem_addr >= DATA_RAM_START && mem_addr < DATA_RAM_END ) begin 58 | mem_read_data = mem_data_raw; 59 | end else if (mem_addr >= GPRMMSTART && mem_addr < GPRMMEND) begin 60 | mem_read_data = gprmm_read_raw; 61 | end 62 | end 63 | // MEM READ DATA MULTIPLEXER 64 | 65 | 66 | instruction_memory #( 67 | .INITIAL(INITIAL_MOCK_INSTR) 68 | ) instruction_memory_instance ( 69 | .clk(clk), 70 | .rst(rst), 71 | .en(~stall_f), 72 | .addr(instr_addr >> 2), // Word aligned 73 | .rdata(instr_data_raw) 74 | ); 75 | 76 | // 32KB of BRAM 77 | data_bram data_bram_inst ( 78 | .address(mem_addr >> 2), 79 | .byteena(byteenablea), // Masking from the control unit 80 | .clock (clk), 81 | .data (mem_write_data), 82 | .wren (write_valid), 83 | .q (mem_data_raw) 84 | ); 85 | 86 | 87 | gprmm_registers gprmm_registers_instance ( 88 | .clk(clk), 89 | .rst(rst), 90 | .wen(mem_write), 91 | .rwaddr(mem_addr), // Byte aligned 92 | .wdata(mem_write_data), 93 | .rdata(gprmm_read_raw), 94 | .GPREGS(GPREGS) 95 | ); 96 | 97 | endmodule 98 | -------------------------------------------------------------------------------- /src/modules/cpu/control_unit/control_e_m_register.sv: -------------------------------------------------------------------------------- 1 | import types::*; 2 | 3 | module control_e_m_register( 4 | input logic clk, rst, en, clr, 5 | // Debug input 6 | input logic [31:0] instr_e, // Debug input 7 | // Debug output 8 | output logic [31:0] instr_m, // Debug output 9 | 10 | // Execute inputs 11 | input bool_t reg_write_e, 12 | input bool_t mem_write_e, 13 | input result_src_t result_src_e, 14 | input logic byte_half_enable_e, // Byte/half enable signal, used for byte/half instructions 15 | input logic [2:0] funct3_e, // funct3 field from the instruction, used for byte/half instructions 16 | 17 | // Memory outputs 18 | output bool_t reg_write_m, 19 | output bool_t mem_write_m, 20 | output result_src_t result_src_m, 21 | output logic byte_half_enable_m, // Byte/half enable signal, used for byte/half instructions 22 | output logic [2:0] funct3_m // funct3 field from the instruction, used for byte/half instructions 23 | ); 24 | 25 | // Intermediate logic vectors 26 | logic [0:0] reg_write_m_vec, mem_write_m_vec; 27 | assign reg_write_m = bool_t'(reg_write_m_vec); 28 | assign mem_write_m = bool_t'(mem_write_m_vec); 29 | 30 | logic [$bits(result_src_t)-1:0] result_src_m_vec; 31 | assign result_src_m = result_src_t'(result_src_m_vec); 32 | 33 | // EXECUTE_MEMORY REGISTER 34 | en_clr_arst_register #( 35 | .WIDTH(1) 36 | ) reg_write_e_m ( 37 | .d(reg_write_e), 38 | .q(reg_write_m_vec), 39 | .clk(clk), 40 | .rst(rst), 41 | .en(en), 42 | .clr(clr) 43 | ); 44 | 45 | en_clr_arst_register #( 46 | .WIDTH(1) 47 | ) mem_write_e_m ( 48 | .d(mem_write_e), 49 | .q(mem_write_m_vec), 50 | .clk(clk), 51 | .rst(rst), 52 | .en(en), 53 | .clr(clr) 54 | ); 55 | 56 | en_clr_arst_register #( 57 | .WIDTH($bits(result_src_t)) 58 | ) result_src_e_m ( 59 | .d(result_src_e), 60 | .q(result_src_m_vec), 61 | .clk(clk), 62 | .rst(rst), 63 | .en(en), 64 | .clr(clr) 65 | ); 66 | 67 | en_clr_arst_register #( 68 | .WIDTH(32) 69 | ) en_clr_arst_register_instance ( 70 | .d(instr_e), 71 | .q(instr_m), 72 | .clk(clk), 73 | .rst(rst), 74 | .en(en), 75 | .clr(clr) 76 | ); 77 | 78 | en_clr_arst_register #( 79 | .WIDTH(1) 80 | ) byte_half_enable_e_m ( 81 | .d(byte_half_enable_e), 82 | .q(byte_half_enable_m), 83 | .clk(clk), 84 | .rst(rst), 85 | .en(en), 86 | .clr(clr) 87 | ); 88 | 89 | en_clr_arst_register #( 90 | .WIDTH(3) 91 | ) funct3_e_m ( 92 | .d(funct3_e), 93 | .q(funct3_m), 94 | .clk(clk), 95 | .rst(rst), 96 | .en(en), 97 | .clr(clr) 98 | ); 99 | 100 | endmodule 101 | -------------------------------------------------------------------------------- /src/modules/cpu/hazard_unit/hazard_unit.sv: -------------------------------------------------------------------------------- 1 | import types::*; 2 | 3 | module hazard_unit( 4 | input logic clk, rst, // will be used for the Memory FSM 5 | // Input signals 6 | // Forwarding 7 | input logic [4:0] rs1_addr_e, rs2_addr_e, // rs1 and rs2 addresses from the execute stage 8 | input logic [4:0] rd_addr_m, rd_addr_wb, // rd address from the memory and writeback stages 9 | input bool_t reg_write_m, reg_write_wb, // reg_write signals from the memory and writeback stages 10 | // Stalls 11 | input logic readdatavalid, 12 | input logic [4:0] rs1_addr_d, rs2_addr_d, rd_addr_e, 13 | input result_src_t result_src_e, 14 | 15 | // Control Hazards 16 | input pc_src_t pc_src_e, 17 | 18 | // Forwarding signals 19 | output rd1_fwd_t rd1_fwd_sel_e, // select signal for the first read data (rd1) 20 | output rd2_fwd_t rd2_fwd_sel_e, // select signal for the second read data (rd2) 21 | 22 | // Stalls signals 23 | output logic stall_f, stall_d, stall_e, stall_m, stall_wb, flush_d, flush_e 24 | ); 25 | 26 | // Control Hazard 27 | logic control_hazard; 28 | assign control_hazard = pc_src_e == PC_SRC_PC_TARGET; 29 | 30 | // Declaration 31 | logic lw_stall, readdatawait; // a load word stall induces a stall of f (and IW) and d registers, and introduces a bubble in e 32 | assign stall_f = lw_stall | readdatawait; 33 | assign stall_d = lw_stall | readdatawait; 34 | assign stall_e = readdatawait; 35 | assign stall_m = readdatawait; 36 | assign stall_wb = readdatawait; 37 | assign flush_d = control_hazard; 38 | assign flush_e = lw_stall | control_hazard; 39 | // STALL M and WB will be asserted by the cycle latency FSM when switching to BRAM 40 | 41 | 42 | // Forwarding logic 43 | always_comb begin 44 | rd1_fwd_sel_e = RD1_FWD_NONE; // Default value 45 | rd2_fwd_sel_e = RD2_FWD_NONE; // Default value 46 | 47 | // Handling RS1 48 | // P0 : Forward from memory stage 49 | if((rs1_addr_e == rd_addr_m && reg_write_m == TRUE) && rs1_addr_e != 0) begin 50 | rd1_fwd_sel_e = RD1_FWD_MEM; 51 | // P1 : Forward from WB 52 | end else if((rs1_addr_e == rd_addr_wb && reg_write_wb == TRUE) && rs1_addr_e != 0) begin 53 | rd1_fwd_sel_e = RD1_FWD_WB; 54 | end 55 | 56 | // Handling RS2 57 | // P0 : Forward from memory stage 58 | if((rs2_addr_e == rd_addr_m && reg_write_m == TRUE) && rs2_addr_e != 0) begin 59 | rd2_fwd_sel_e = RD2_FWD_MEM; 60 | // P1 : Forward from WB 61 | end else if((rs2_addr_e == rd_addr_wb && reg_write_wb == TRUE) && rs2_addr_e != 0) begin 62 | rd2_fwd_sel_e = RD2_FWD_WB; 63 | end 64 | end 65 | 66 | // Stall detection, will be asserted for 1 clock cycle as we're introducing a bubble in E 67 | // read latency will be handled by the state machine when we switch to BRAM 68 | assign lw_stall = (result_src_e == RESULT_SRC_MEM) && ((rs1_addr_d == rd_addr_e) || (rs2_addr_d == rd_addr_e)); 69 | 70 | 71 | // Read data wait FSM 72 | lw_fsm lw_fsm_instance ( 73 | .clk(clk), 74 | .rst(rst), 75 | .lwstall(lw_stall), 76 | .readdatavalid(readdatavalid), 77 | .readdatawait(readdatawait) 78 | ); 79 | 80 | 81 | endmodule 82 | -------------------------------------------------------------------------------- /src/dokifive_p50_top.sv: -------------------------------------------------------------------------------- 1 | import io::*; 2 | //======================================================= 3 | // This code is generated by Terasic System Builder 4 | //======================================================= 5 | 6 | module dokifive_p50_top( 7 | 8 | //////////// CLOCK ////////// 9 | input ADC_CLK_10, 10 | input MAX10_CLK1_50, 11 | input MAX10_CLK2_50, 12 | 13 | //////////// SDRAM ////////// 14 | output [12:0] DRAM_ADDR, 15 | output [1:0] DRAM_BA, 16 | output DRAM_CAS_N, 17 | output DRAM_CKE, 18 | output DRAM_CLK, 19 | output DRAM_CS_N, 20 | inout [15:0] DRAM_DQ, 21 | output DRAM_LDQM, 22 | output DRAM_RAS_N, 23 | output DRAM_UDQM, 24 | output DRAM_WE_N, 25 | 26 | //////////// SEG7 ////////// 27 | output [7:0] HEX0, 28 | output [7:0] HEX1, 29 | output [7:0] HEX2, 30 | output [7:0] HEX3, 31 | output [7:0] HEX4, 32 | output [7:0] HEX5, 33 | 34 | //////////// KEY ////////// 35 | input [1:0] KEY, 36 | 37 | //////////// LED ////////// 38 | output [9:0] LEDR, 39 | 40 | //////////// SW ////////// 41 | input [9:0] SW, 42 | 43 | //////////// VGA ////////// 44 | output [3:0] VGA_B, 45 | output [3:0] VGA_G, 46 | output VGA_HS, 47 | output [3:0] VGA_R, 48 | output VGA_VS, 49 | 50 | //////////// Arduino ////////// 51 | inout [15:0] ARDUINO_IO, 52 | inout ARDUINO_RESET_N 53 | ); 54 | 55 | 56 | 57 | //======================================================= 58 | // REG/WIRE declarations 59 | //======================================================= 60 | // Uncomment the following line to use the clock divider 61 | // logic clk_div; 62 | GPREGS_T GPREGS; 63 | logic [6:0] seg0, seg1, seg2, seg3, seg4, seg5; 64 | 65 | assign HEX0 = {1'b1, seg0}; 66 | assign HEX1 = {1'b1, seg1}; 67 | assign HEX2 = {1'b1, seg2}; 68 | assign HEX3 = {1'b1, seg3}; 69 | assign HEX4 = {1'b1, seg4}; 70 | assign HEX5 = {1'b1, seg5}; 71 | assign LEDR = GPREGS.GPR1[9:0]; 72 | 73 | //======================================================= 74 | // Structural coding 75 | //======================================================= 76 | dokifive_soc #( 77 | .INITIAL_INSTR("instr_init.mem") 78 | ) dokifive_soc_instance ( 79 | .clk(MAX10_CLK1_50), 80 | .rst(~KEY[0]), 81 | .GPREGS(GPREGS) 82 | ); 83 | 84 | // Seven segment decoders 85 | sevenseg sevenseg_0 ( 86 | .data(GPREGS.GPR1), 87 | .segments(seg0) 88 | ); 89 | sevenseg sevenseg_1 ( 90 | .data(GPREGS.GPR1 >> 4), 91 | .segments(seg1) 92 | ); 93 | sevenseg sevenseg_2 ( 94 | .data(GPREGS.GPR1 >> 8), 95 | .segments(seg2) 96 | ); 97 | sevenseg sevenseg_3 ( 98 | .data(GPREGS.GPR1 >> 12), 99 | .segments(seg3) 100 | ); 101 | sevenseg sevenseg_4 ( 102 | .data(GPREGS.GPR1 >> 16), 103 | .segments(seg4) 104 | ); 105 | sevenseg sevenseg_5 ( 106 | .data(GPREGS.GPR1 >> 20), 107 | .segments(seg5) 108 | ); 109 | 110 | // Uncomment and assign clk_div to the SoC if needed 111 | // clock_divider #( 112 | // .WIDTH(18) 113 | // ) clock_divider_instance ( 114 | // .clk(ADC_CLK_10), 115 | // .rst(~KEY[0]), 116 | // .div_clk(clk_div) 117 | // ); 118 | 119 | endmodule 120 | -------------------------------------------------------------------------------- /src/modules/packages/types.sv: -------------------------------------------------------------------------------- 1 | package types; 2 | typedef enum logic [2:0] { 3 | IMMSRC_I_TYPE, 4 | IMMSRC_UI_TYPE, 5 | IMMSRC_S_TYPE, 6 | IMMSRC_B_TYPE, 7 | IMMSRC_J_TYPE, 8 | IMMSRC_U_TYPE 9 | } immsrc_t; 10 | typedef enum logic [3:0] { 11 | ALU_OP_ADD, 12 | ALU_OP_SUB, 13 | ALU_OP_AND, 14 | ALU_OP_OR, 15 | ALU_OP_SLT, 16 | ALU_OP_SLTU, 17 | ALU_OP_SGE, 18 | ALU_OP_SGEU, 19 | ALU_OP_XOR, 20 | ALU_OP_SLL, 21 | ALU_OP_SRL, 22 | ALU_OP_SRA 23 | } alu_op_t; 24 | typedef enum logic [2:0] { 25 | ALU_CONTROL_ADD, 26 | ALU_CONTROL_SUB, 27 | ALU_CONTROL_ITYPE, 28 | ALU_CONTROL_RTYPE, 29 | ALU_CONTROL_BTYPE 30 | } alu_control_t; 31 | typedef enum logic [1:0] { 32 | RESULT_SRC_ALU = 2'b00, 33 | RESULT_SRC_MEM = 2'b01, 34 | RESULT_SRC_PC_PLUS_4 = 2'b10, 35 | RESULT_SRC_IMM = 2'b11 36 | } result_src_t; 37 | typedef enum logic { 38 | PC_SRC_PC_PLUS_4 = 1'b0, // PC + 4 39 | PC_SRC_PC_TARGET = 1'b1 // Target address for branch/jump 40 | } pc_src_t; 41 | typedef enum logic { 42 | PC_TARGET_PC, // JAL 43 | PC_TARGET_RS1 // JALR 44 | } pc_target_src_t; 45 | typedef enum logic { 46 | ALU_SRC_A_RS1 = 1'b0, // First source is rs1 (rd1) 47 | ALU_SRC_A_PC = 1'b1 // Using the program counter (AUIPC) 48 | } alu_src_a_sig_t; 49 | typedef enum logic { 50 | ALU_SRC_B_RS2 = 1'b0, // Second source is rs2 (rd2) 51 | ALU_SRC_B_IMM = 1'b1 // Second source is immediate (imm_ext) 52 | } alu_src_b_sig_t; 53 | typedef enum logic { 54 | FALSE = 1'b0, 55 | TRUE = 1'b1 56 | } bool_t; 57 | typedef enum logic [6:0] { 58 | OPCODE_LOAD = 7'd3, 59 | OPCODE_I_TYPE = 7'd19, 60 | OPCODE_AUIPC = 7'd23, 61 | OPCODE_STORE = 7'd35, 62 | OPCODE_R = 7'd51, 63 | OPCODE_LUI = 7'd55, 64 | OPCODE_BRANCH = 7'd99, 65 | OPCODE_JALR = 7'd103, 66 | OPCODE_JAL = 7'd111 67 | } opcode_t; // Opcode for the instruction 68 | typedef enum logic [1:0] { 69 | RD1_FWD_NONE = 2'b00, // No forwarding 70 | RD1_FWD_WB = 2'b01, // Forwarding from WB stage 71 | RD1_FWD_MEM = 2'b10 // Forwarding from MEM stage 72 | } rd1_fwd_t; // Select signal for the first read data (rd1) 73 | typedef enum logic [1:0] { 74 | RD2_FWD_NONE = 2'b00, // No forwarding 75 | RD2_FWD_WB = 2'b01, // Forwarding from WB stage 76 | RD2_FWD_MEM = 2'b10 // Forwarding from MEM stage 77 | } rd2_fwd_t; // Select signal for the second read data (rd2) 78 | typedef enum logic { 79 | LW_NOT_LW, 80 | LW_WAITING_READVALID 81 | } lw_fsm_state_t; 82 | typedef enum logic [1:0] { 83 | BRANCH_VALID_ZERO = 2'b00, 84 | BRANCH_VALID_ZEROB = 2'b01, 85 | BRANCH_VALID_ALU0 = 2'b10 86 | } branch_valid_src_t; 87 | // Signal types for partial word loads and stores 88 | typedef enum logic [3:0] { 89 | BYTE_HALF_NONE = 4'b1111, // No mask 90 | BYTE_HALF_BYTE_0 = 4'b0001, // Mask for byte 0 91 | BYTE_HALF_BYTE_1 = 4'b0010, // Mask for byte 1 92 | BYTE_HALF_BYTE_2 = 4'b0100, // Mask for byte 2 93 | BYTE_HALF_BYTE_3 = 4'b1000, // Mask for byte 3 94 | BYTE_HALF_HALF_0 = 4'b0011, // Mask for halfword 0 95 | BYTE_HALF_HALF_1 = 4'b1100 // Mask for halfword 1 96 | } byte_half_sel_t; 97 | // Type for load b/h extension depending on instruction 98 | typedef enum logic { 99 | WORD_EXT_ZERO, 100 | WORD_EXT_SIGN 101 | } word_ext_t; 102 | endpackage 103 | -------------------------------------------------------------------------------- /src/modules/cpu/control_unit/alu_decoder.sv: -------------------------------------------------------------------------------- 1 | import types::*; 2 | 3 | module alu_decoder( 4 | input alu_control_t alu_control, 5 | input logic funct7_5, 6 | input logic [2:0] funct3, 7 | output alu_op_t alu_op 8 | ); 9 | 10 | always_comb begin 11 | case (alu_control) 12 | ALU_CONTROL_ADD: alu_op = ALU_OP_ADD; // ADD operation 13 | ALU_CONTROL_SUB: alu_op = ALU_OP_SUB; // SUB operation 14 | ALU_CONTROL_ITYPE: begin // We look at the function bits 15 | case(funct3) 16 | 3'b000: alu_op = ALU_OP_ADD; // ADDI operation 17 | 3'b001: alu_op = ALU_OP_SLL; // SLLI operation 18 | 3'b010: alu_op = ALU_OP_SLT; // SLTI operation 19 | 3'b011: alu_op = ALU_OP_SLTU; // SLTIU operation 20 | 3'b100: alu_op = ALU_OP_XOR; // XORI operation 21 | 3'b101: begin 22 | case(funct7_5) 23 | 1'b0: alu_op = ALU_OP_SRL; // SRLI operation 24 | 1'b1: alu_op = ALU_OP_SRA; // SRAI operation 25 | default: alu_op = ALU_OP_SRL; // Default to SRLI operation, should not happen 26 | endcase 27 | end 28 | 3'b110: alu_op = ALU_OP_OR; // ORI operation 29 | 3'b111: alu_op = ALU_OP_AND; // ANDI operation 30 | default: alu_op = ALU_OP_ADD; // Default to ADD operation 31 | endcase 32 | end 33 | ALU_CONTROL_RTYPE: begin 34 | case(funct3) // We look at the function bits 35 | 3'b000: begin 36 | case(funct7_5) 37 | 1'b0: alu_op = ALU_OP_ADD; // ADD operation 38 | 1'b1: alu_op = ALU_OP_SUB; // SUB operation 39 | default: alu_op = ALU_OP_ADD; // Default to ADD operation, should not happen 40 | endcase 41 | end 42 | 3'b001: alu_op = ALU_OP_SLL; // SLL operation 43 | 3'b010: alu_op = ALU_OP_SLT; // SLT operation 44 | 3'b011: alu_op = ALU_OP_SLTU; // SLTU operation 45 | 3'b100: alu_op = ALU_OP_XOR; // XOR operation 46 | 3'b101: begin 47 | case(funct7_5) 48 | 1'b0: alu_op = ALU_OP_SRL; // SRL operation 49 | 1'b1: alu_op = ALU_OP_SRA; // SRA operation 50 | default: alu_op = ALU_OP_SRL; // Default to SRL operation, should not happen 51 | endcase 52 | end 53 | 3'b110: alu_op = ALU_OP_OR; // OR operation 54 | 3'b111: alu_op = ALU_OP_AND; // AND operation 55 | default: alu_op = ALU_OP_ADD; // Default to ADD operation 56 | endcase 57 | end 58 | ALU_CONTROL_BTYPE: begin 59 | case(funct3) 60 | 3'b000: alu_op = ALU_OP_SUB; // BEQ, we need to sub to check for zero flag 61 | 3'b001: alu_op = ALU_OP_SUB; // BNE, we need to sub to check for not zero flag 62 | 3'b100: alu_op = ALU_OP_SLT; // BLT operation, we need to check if a < b 63 | 3'b101: alu_op = ALU_OP_SGE; // BGE operation, we need to check if a < a (we will invert the alusrca and alusrcb in the multiplexer) 64 | 3'b110: alu_op = ALU_OP_SLTU; // BLTU operation, we need to check if a < b unsigned 65 | 3'b111: alu_op = ALU_OP_SGEU; // BGEU operation, we need to check if b < a unsigned (we will invert the alusrca and alusrcb in the multiplexer) 66 | default: alu_op = ALU_OP_ADD; // Default to ADD operation 67 | endcase 68 | end 69 | default : alu_op = ALU_OP_ADD; // Default to ADD operation 70 | endcase 71 | 72 | end 73 | 74 | 75 | endmodule 76 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DokiFive P50: RISC-V CPU for DE10-Lite 2 | 3 | ## Overview 4 | DokiFive P50 is a custom RISC-V RV32I CPU core designed for the Intel/Altera DE10-Lite FPGA board. The CPU implements the full RV32I instruction set architecture, supporting all base integer instructions, including arithmetic, logic, control flow, memory access, and system instructions. The design is modular, with a clear separation between datapath, control unit, hazard handling, and memory subsystems. 5 | 6 | The core can easily be edited to run on different hardware, juste make sure to replace the instruction and data memory with your vendor IP. 7 | 8 | ## CPU Architecture 9 | The CPU is a classic 5-stage pipeline (Fetch, Decode, Execute, Memory, Writeback) RISC-V processor, but modified to accomodate real hardware BRAM timings (it has an additional "Instruction Wait" pipeline stage) with hazard detection and forwarding logic. The Hazard Unit implements an FSM that can easily be extended to support slower memory (using the `readdatavalid` logic signal) 10 | 11 | It features: 12 | - Full support for RV32I, including all load/store, branch, jump, and arithmetic instructions. 13 | - Byte and halfword memory access with proper sign/zero extension. 14 | - Data hazard detection and forwarding to minimize pipeline stalls. 15 | - Control hazard handling with flush and stall signals. 16 | - Modular design: separate modules for ALU, register file, control logic, hazard unit, and memory controller. 17 | 18 | ### Memory map 19 | 20 | - **Instruction ROM**: 0x00000000 - 0x0000FFFF (64 KB) 21 | - **Data RAM**: 0x10000000 - 0x10007FFF (32 KB) 22 | - **GPRMM (General Purpose Registers, Memory-Mapped IO)**: 0x30000000 - 0x3FFFFFFF 23 | - GPRMM1: 0x30000000 24 | - GPRMM2: 0x30000001 25 | 26 | Please note that Instruction and Data memories are address-registered, data read is combinational. 27 | General purpose registers are synchronous write, combinational read. 28 | 29 | Addresses outside these ranges return undefined or default values (e.g., 0xDEADBEEF for unmapped memory). 30 | 31 | ## FPGA Integration (DE10-Lite) 32 | The top-level module (`DokiFive_p50_top`) instantiates the CPU and connects it to on-chip memory, SDRAM, and peripherals (LEDs, switches, 7-segment displays, VGA, Arduino headers). Pin assignments and I/O standards are defined in the Quartus `.qsf` file for the DE10-Lite board. The memory controller provides access to instruction and data memory, as well as memory-mapped I/O for peripherals. 33 | 34 | ### Performance 35 | On standard DE10-Lite hardware, considering no peripheral constraints, the core can run at a calculated 55.72MHz, it's perfectly suited to use with the 50MHz clock. 36 | 37 | ## Simulation and Testing 38 | The `simulation/` folder contains ModelSim/Questa simulation project files, testbenches, and memory initialization files. The testbench (`tb_soc.sv`) simulates the SoC, including the CPU and memory system. You can run simulations to verify correct execution of RISC-V programs and observe CPU behavior. 39 | 40 | ## RISC-V Software and Code Examples 41 | The `riscv/` folder contains: 42 | - Example C and assembly programs (e.g., `fibonacci.c`, `crt0.s`). 43 | - A linker script (`linker.ld`) that places code and data using the correct memory map for the CPU. 44 | - A Makefile to build RISC-V binaries using GCC and convert them to memory initialization files (`instr_init.mem`) for simulation or FPGA loading. 45 | - A Python script (`gen_instr_mem.py`) to extract instruction memory contents from ELF files and format it in a `$readmemh` friendly format. 46 | 47 | You can write your own C or assembly programs, build them with the provided toolchain, and run them on the CPU in simulation or on the FPGA. 48 | 49 | ## Getting Started 50 | 1. Build your RISC-V program in the `riscv/` folder using the Makefile. 51 | 2. Load the generated `instr_init.mem` into the simulation or FPGA bitstream. 52 | 3. Use the provided testbenches or deploy to the DE10-Lite board to observe program execution and interact with peripherals. 53 | 54 | ## License 55 | See `LICENSE.md` for licensing information. 56 | 57 | ## ❤️ Acknowledgments 58 | 59 | - The RISC-V community for creating such an open and elegant ISA 60 | - *Digital Design and Computer Architecture: RISC-V Edition* by David Money Harris & Sarah L. Harris 61 | - **Shawn Hymel**, for his clear and accessible courses on Digital Design. 62 | - **V. Hunter Adams**, for his incredibles courses and inspiration 63 | 64 | -------------------------------------------------------------------------------- /src/modules/cpu/control_unit/control_d_e_register.sv: -------------------------------------------------------------------------------- 1 | import types::*; 2 | 3 | module control_d_e_register( 4 | input logic clk, rst, en, clr, 5 | // Debug input 6 | input logic [31:0] instr_d, // Debug input 7 | // Debug output 8 | output logic [31:0] instr_e, // Debug output 9 | 10 | // Decode inputs 11 | input bool_t reg_write_d, 12 | input bool_t mem_write_d, jump_d, branch_d, 13 | input result_src_t result_src_d, 14 | input alu_op_t alu_op_d, 15 | input alu_src_a_sig_t alu_src_a_sig_d, 16 | input alu_src_b_sig_t alu_src_b_sig_d, 17 | input pc_target_src_t pc_target_src_d, 18 | input branch_valid_src_t branch_valid_src_d, 19 | input logic byte_half_enable_d, // Byte/half enable signal, used for byte/half instructions 20 | input logic [2:0] funct3_d, // funct3 field from the instruction, used for byte/half instructions 21 | // Execute outputs 22 | output bool_t reg_write_e, 23 | output bool_t mem_write_e, jump_e, branch_e, 24 | output result_src_t result_src_e, 25 | output alu_op_t alu_op_e, 26 | output alu_src_a_sig_t alu_src_a_sig_e, 27 | output alu_src_b_sig_t alu_src_b_sig_e, 28 | output pc_target_src_t pc_target_src_e, 29 | output branch_valid_src_t branch_valid_src_e, 30 | output logic byte_half_enable_e, // Byte/half enable signal, used for byte/half instructions 31 | output logic [2:0] funct3_e // funct3 field from the instruction, used for byte/half instructions 32 | 33 | ); 34 | 35 | logic [0:0] reg_write_e_vec, mem_write_e_vec, jump_e_vec, branch_e_vec; 36 | assign reg_write_e = bool_t'(reg_write_e_vec); 37 | assign mem_write_e = bool_t'(mem_write_e_vec); 38 | assign jump_e = bool_t'(jump_e_vec); 39 | assign branch_e = bool_t'(branch_e_vec); 40 | 41 | logic [$bits(result_src_t)-1:0] result_src_e_vec; 42 | assign result_src_e = result_src_t'(result_src_e_vec); 43 | 44 | logic [$bits(alu_op_t)-1:0] alu_op_e_vec; 45 | assign alu_op_e = alu_op_t'(alu_op_e_vec); 46 | 47 | logic [$bits(alu_src_a_sig_t)-1:0] alu_src_a_sig_e_vec; 48 | assign alu_src_a_sig_e = alu_src_a_sig_t'(alu_src_a_sig_e_vec); 49 | 50 | logic [$bits(alu_src_b_sig_t)-1:0] alu_src_b_sig_e_vec; 51 | assign alu_src_b_sig_e = alu_src_b_sig_t'(alu_src_b_sig_e_vec); 52 | 53 | logic [$bits(pc_target_src_t)-1:0] pc_target_src_e_vec; 54 | assign pc_target_src_e = pc_target_src_t'(pc_target_src_e_vec); 55 | 56 | logic [$bits(branch_valid_src_t)-1:0] branch_valid_src_e_vec; 57 | assign branch_valid_src_e = branch_valid_src_t'(branch_valid_src_e_vec); 58 | 59 | en_clr_arst_register #( 60 | .WIDTH(1) 61 | ) en_clr_arst_register_instance ( 62 | .d(reg_write_d), 63 | .q(reg_write_e_vec), 64 | .clk(clk), 65 | .rst(rst), 66 | .en(en), 67 | .clr(clr) 68 | ); 69 | 70 | en_clr_arst_register #( 71 | .WIDTH(1) 72 | ) mem_write_en_clr_arst_register_instance ( 73 | .d(mem_write_d), 74 | .q(mem_write_e_vec), 75 | .clk(clk), 76 | .rst(rst), 77 | .en(en), 78 | .clr(clr) 79 | ); 80 | 81 | en_clr_arst_register #( 82 | .WIDTH(1) 83 | ) jump_en_clr_arst_register_instance ( 84 | .d(jump_d), 85 | .q(jump_e_vec), 86 | .clk(clk), 87 | .rst(rst), 88 | .en(en), 89 | .clr(clr) 90 | ); 91 | 92 | en_clr_arst_register #( 93 | .WIDTH(1) 94 | ) branch_en_clr_arst_register_instance ( 95 | .d(branch_d), 96 | .q(branch_e_vec), 97 | .clk(clk), 98 | .rst(rst), 99 | .en(en), 100 | .clr(clr) 101 | ); 102 | 103 | en_clr_arst_register #( 104 | .WIDTH($bits(result_src_t)) 105 | ) result_src_en_clr_arst_register_instance ( 106 | .d(result_src_d), 107 | .q(result_src_e_vec), 108 | .clk(clk), 109 | .rst(rst), 110 | .en(en), 111 | .clr(clr) 112 | ); 113 | 114 | en_clr_arst_register #( 115 | .WIDTH($bits(alu_op_t)) 116 | ) alu_op_en_clr_arst_register_instance ( 117 | .d(alu_op_d), 118 | .q(alu_op_e_vec), 119 | .clk(clk), 120 | .rst(rst), 121 | .en(en), 122 | .clr(clr) 123 | ); 124 | 125 | en_clr_arst_register #( 126 | .WIDTH($bits(alu_src_b_sig_t)) 127 | ) alu_src_b_sig_en_clr_arst_register_instance ( 128 | .d(alu_src_b_sig_d), 129 | .q(alu_src_b_sig_e_vec), 130 | .clk(clk), 131 | .rst(rst), 132 | .en(en), 133 | .clr(clr) 134 | ); 135 | 136 | en_clr_arst_register #( 137 | .WIDTH($bits(pc_target_src_t)) 138 | ) pc_target_src_en_clr_arst_register_instance ( 139 | .d(pc_target_src_d), 140 | .q(pc_target_src_e_vec), 141 | .clk(clk), 142 | .rst(rst), 143 | .en(en), 144 | .clr(clr) 145 | ); 146 | 147 | en_clr_arst_register #( 148 | .WIDTH($bits(alu_src_a_sig_t)) 149 | ) alu_src_a_sig_en_clr_arst_register_instance ( 150 | .d(alu_src_a_sig_d), 151 | .q(alu_src_a_sig_e_vec), 152 | .clk(clk), 153 | .rst(rst), 154 | .en(en), 155 | .clr(clr) 156 | ); 157 | 158 | en_clr_arst_register #( 159 | .WIDTH($bits(branch_valid_src_t)) 160 | ) branch_valid_src_en_clr_arst_register_instance ( 161 | .d(branch_valid_src_d), 162 | .q(branch_valid_src_e_vec), 163 | .clk(clk), 164 | .rst(rst), 165 | .en(en), 166 | .clr(clr) 167 | ); 168 | 169 | // Debug output 170 | en_clr_arst_register #( 171 | .WIDTH(32) 172 | ) instr_e_en_clr_arst_register_instance ( 173 | .d(instr_d), 174 | .q(instr_e), 175 | .clk(clk), 176 | .rst(rst), 177 | .en(en), 178 | .clr(clr) 179 | ); 180 | 181 | en_clr_arst_register #( 182 | .WIDTH(1) 183 | ) byte_half_enable_en_clr_arst_register_instance ( 184 | .d(byte_half_enable_d), 185 | .q(byte_half_enable_e), 186 | .clk(clk), 187 | .rst(rst), 188 | .en(en), 189 | .clr(clr) 190 | ); 191 | 192 | en_clr_arst_register #( 193 | .WIDTH(3) 194 | ) funct3_en_clr_arst_register_instance ( 195 | .d(funct3_d), 196 | .q(funct3_e), 197 | .clk(clk), 198 | .rst(rst), 199 | .en(en), 200 | .clr(clr) 201 | ); 202 | 203 | endmodule 204 | -------------------------------------------------------------------------------- /src/modules/cpu/cpu.sv: -------------------------------------------------------------------------------- 1 | import types::*; 2 | 3 | module cpu( 4 | input logic clk, rst, 5 | // Memory controller 6 | input logic [31:0] instr_data, mem_data_r, // From the memory controller 7 | output logic [31:0] instr_addr, mem_addr_m, mem_data_w, // To the memory controller 8 | output bool_t mem_write, // Memory write signal, will be used by the control unit to control the memory controller 9 | output logic stall_f, // we need the info for the memory 10 | output logic flush_d, 11 | output byte_half_sel_t byte_half_sel_m // To memory byteenablea 12 | ); 13 | 14 | // WIRE DECLARATIONS 15 | logic [31:0] instr_f, pc_f; // instruction fetched from memory and the next PC value 16 | // Control unit signals 17 | logic [31:0] instr_d; // Instruction to be decoded, must be forwarded to the control unit 18 | logic branch_valid_e; // zero flag from the ALU, used for branch/jump instructions 19 | // decode 20 | immsrc_t immsrc_d; // immediate source for the decode stage 21 | // execute 22 | pc_src_t pc_src_e; 23 | pc_target_src_t pc_target_src_sig_e; // PC source for branch/jump, used to switch between PC + 4 and the target address 24 | branch_valid_src_t branch_valid_src_e; 25 | alu_src_a_sig_t alu_src_a_sig_e; // ALU source A, used to switch between rs1 and the PC (AUIPC) 26 | alu_src_b_sig_t alu_src_b_sig_e; // ALU source, used to switch between the second operand and the immediate value 27 | alu_op_t alu_op; // ALU operation, used to select the operation to be performed by the ALU 28 | // memory 29 | word_ext_t word_ext_m; // Word extension signal, used for byte/half instructions 30 | result_src_t result_src_m; // Used in forwarding logic (if result_src is IMMEXT) 31 | // writeback 32 | bool_t reg_write_w; // register write signal, used to control the register file 33 | result_src_t result_src_w; // result source, used to select the source of the data to be written back to the register file 34 | 35 | // Hazard unit signals 36 | // Stalls 37 | logic [4:0] rs1_addr_d, rs2_addr_d, rd_addr_e; // from datapath 38 | result_src_t result_src_e; // from control unit 39 | logic stall_d, stall_e, stall_m, stall_wb; // stalls for fetch, decode, execute, memory and writeback stages respectively 40 | // Flushes 41 | logic flush_e; // flush signals for decode and execute stages 42 | // Forwards 43 | rd1_fwd_t rd1_fwd_sel_e; 44 | rd2_fwd_t rd2_fwd_sel_e; 45 | logic [4:0] rs1_addr_e, rs2_addr_e, rd_addr_m, rd_addr_wb; 46 | bool_t reg_write_m; 47 | 48 | // WIRE ASSIGNMENTS 49 | assign instr_addr = pc_f; // PC_fnext is the address of the instruction to be fetched (registered in the memory controller, synced with pc_f) 50 | assign instr_f = instr_data; // instruction fetched from memory 51 | 52 | datapath datapath_instance ( 53 | .clk(clk), 54 | .rst(rst), 55 | .instr_iw(instr_f), 56 | .mem_data_r_m(mem_data_r), 57 | .pc_f(pc_f), 58 | .instr_d(instr_d), 59 | .branch_valid_e(branch_valid_e), 60 | .mem_addr_m(mem_addr_m), 61 | .mem_data_w_m(mem_data_w), 62 | .stall_f(stall_f), 63 | .stall_d(stall_d), 64 | .stall_e(stall_e), 65 | .stall_m(stall_m), 66 | .stall_wb(stall_wb), 67 | .flush_d(flush_d), 68 | .flush_e(flush_e), 69 | .rd1_fwd_sel_e(rd1_fwd_sel_e), 70 | .rd2_fwd_sel_e(rd2_fwd_sel_e), 71 | .rs1_addr_e(rs1_addr_e), 72 | .rs2_addr_e(rs2_addr_e), 73 | .rd_addr_m(rd_addr_m), 74 | .rd_addr_wb(rd_addr_wb), 75 | .rs1_addr_d(rs1_addr_d), 76 | .rs2_addr_d(rs2_addr_d), 77 | .rd_addr_e(rd_addr_e), 78 | .immsrc_d(immsrc_d), 79 | .pc_src_e(pc_src_e), 80 | .alu_src_a_sig_e(alu_src_a_sig_e), 81 | .alu_src_b_sig_e(alu_src_b_sig_e), 82 | .alu_op(alu_op), 83 | .pc_target_src_sig_e(pc_target_src_sig_e), 84 | .branch_valid_src_e(branch_valid_src_e), 85 | .byte_half_sel_m(byte_half_sel_m), // byte/half extension signal for memory 86 | .word_ext_m(word_ext_m), // word extension signal for memory 87 | .result_src_m(result_src_m), 88 | .reg_write_w(reg_write_w), 89 | .result_src_w(result_src_w) 90 | ); 91 | 92 | 93 | // Control unit 94 | control_unit control_unit_instance ( 95 | .clk(clk), 96 | .rst(rst), 97 | .flush_e(flush_e), 98 | .stall_e(stall_e), 99 | .stall_m(stall_m), 100 | .stall_wb(stall_wb), 101 | .instr_d(instr_d), 102 | .branch_valid_e(branch_valid_e), 103 | .mem_addr_m(mem_addr_m), 104 | .immsrc_d(immsrc_d), 105 | .pc_src_e(pc_src_e), 106 | .alu_src_a_sig_e(alu_src_a_sig_e), 107 | .alu_src_b_sig_e(alu_src_b_sig_e), 108 | .alu_op_e(alu_op), 109 | .pc_target_src_e(pc_target_src_sig_e), 110 | .reg_write_m(reg_write_m), 111 | .reg_write_w(reg_write_w), 112 | .result_src_m(result_src_m), 113 | .result_src_w(result_src_w), 114 | .mem_write_m(mem_write), 115 | .branch_valid_src_e(branch_valid_src_e), 116 | .byte_half_sel_m(byte_half_sel_m), // byte/half extension signal for memory 117 | .word_ext_m(word_ext_m), // word extension signal for memory 118 | .result_src_e(result_src_e) 119 | ); 120 | 121 | // Hazard unit 122 | hazard_unit hazard_unit_instance ( 123 | .clk(clk), 124 | .rst(rst), 125 | .rs1_addr_e(rs1_addr_e), 126 | .rs2_addr_e(rs2_addr_e), 127 | .rd_addr_m(rd_addr_m), 128 | .rd_addr_wb(rd_addr_wb), 129 | .reg_write_m(reg_write_m), 130 | .reg_write_wb(reg_write_w), 131 | .readdatavalid(1'b1), // 1 cycle latency all the time 132 | .rs1_addr_d(rs1_addr_d), 133 | .rs2_addr_d(rs2_addr_d), 134 | .rd_addr_e(rd_addr_e), 135 | .result_src_e(result_src_e), 136 | .pc_src_e(pc_src_e), 137 | .rd1_fwd_sel_e(rd1_fwd_sel_e), 138 | .rd2_fwd_sel_e(rd2_fwd_sel_e), 139 | .stall_f(stall_f), 140 | .stall_d(stall_d), 141 | .stall_e(stall_e), 142 | .stall_m(stall_m), 143 | .stall_wb(stall_wb), 144 | .flush_d(flush_d), 145 | .flush_e(flush_e) 146 | ); 147 | endmodule 148 | -------------------------------------------------------------------------------- /src/modules/cpu/control_unit/control_unit.sv: -------------------------------------------------------------------------------- 1 | import types::*; 2 | 3 | module control_unit( 4 | input logic clk, rst, flush_e, stall_e, stall_m, stall_wb, // Control signals 5 | input logic [31:0] instr_d, // Instruction to be decoded 6 | input logic branch_valid_e, // Zero flag from the ALU, used for branch/jump instructions 7 | input logic [31:0] mem_addr_m, // Memory address for the memory stage, used to decode byte/half instructions 8 | 9 | output immsrc_t immsrc_d, // Immediate source for the decode stage 10 | output pc_src_t pc_src_e, // PC source for branch/jump, used to switch between PC + 4 and the target address 11 | output alu_src_a_sig_t alu_src_a_sig_e, // ALU source A, used to switch between rs1 and the PC (AUIPC) 12 | output alu_src_b_sig_t alu_src_b_sig_e, // ALU source, used to switch between the second operand and the immediate value 13 | output alu_op_t alu_op_e, // ALU operation, used to select the operation to be performed by the ALU 14 | output pc_target_src_t pc_target_src_e, 15 | output bool_t reg_write_m, // for hazard handling 16 | output bool_t reg_write_w, // Register write signal, used to control the register file 17 | output result_src_t result_src_m, 18 | output result_src_t result_src_w, // Result source, used to select the source of the data to be written back to the register file 19 | output bool_t mem_write_m, // Memory write signal, now bool_t 20 | output branch_valid_src_t branch_valid_src_e, 21 | output byte_half_sel_t byte_half_sel_m, // Byte/half select signal, used for byte/half instructions 22 | output word_ext_t word_ext_m, // Word extension signal, used for byte/half instructions 23 | // Hazard handling 24 | output result_src_t result_src_e 25 | ); 26 | 27 | logic [6:0] opcode_d; // Opcode from the instruction 28 | logic [2:0] funct3_d; // Function 3 from the instruction 29 | logic funct7_5_d; // Function 7 from the instruction 30 | alu_control_t alu_control; // ALU control signal, comes from the main decoder 31 | 32 | // instruction assignemnts 33 | assign opcode_d = instr_d[6:0]; // Opcode from the instruction 34 | assign funct3_d = instr_d[14:12]; // Function 3 from the instruction 35 | assign funct7_5_d = instr_d[30]; // Function 7, bit 5 from the instruction 36 | 37 | // Signals 38 | // Decode 39 | bool_t reg_write_d; 40 | result_src_t result_src_d; 41 | bool_t mem_write_d; 42 | bool_t jump_d; 43 | bool_t branch_d; 44 | alu_op_t alu_op_d; 45 | alu_src_a_sig_t alu_src_a_sig_d; 46 | alu_src_b_sig_t alu_src_b_sig_d; 47 | pc_target_src_t pc_target_src_d; 48 | branch_valid_src_t branch_valid_src_d; 49 | logic byte_half_enable_d; // Byte/half enable signal, used for byte/half instructions 50 | // Debug signals 51 | logic [31:0] instr_e, instr_m, instr_w; // Debug output, instruction to be executed 52 | // Execute 53 | bool_t reg_write_e; 54 | bool_t mem_write_e; 55 | bool_t jump_e; 56 | bool_t branch_e; 57 | logic byte_half_enable_e; // Byte/half enable signal, used for byte/half instructions 58 | logic [2:0] funct3_e; // funct3 field from the instruction, used for byte/half instructions 59 | // Memory 60 | logic byte_half_enable_m; // Byte/half enable signal, used for byte/half instructions 61 | logic [2:0] funct3_m; // funct3 field from the instruction, used for byte/half instructions 62 | // Writeback 63 | 64 | // DECODE STAGE 65 | main_decoder main_decoder_instance ( 66 | .opcode(opcode_d), 67 | .funct3(funct3_d), 68 | .reg_write(reg_write_d), 69 | .result_src(result_src_d), 70 | .mem_write(mem_write_d), 71 | .jump(jump_d), 72 | .branch(branch_d), 73 | .alu_control(alu_control), 74 | .alu_src_a_sig(alu_src_a_sig_d), 75 | .alu_src_b_sig(alu_src_b_sig_d), 76 | .immsrc(immsrc_d), 77 | .pc_target_src(pc_target_src_d), 78 | .branch_valid_src(branch_valid_src_d), 79 | .byte_half_enable_d(byte_half_enable_d) 80 | ); 81 | 82 | // Alu decoder 83 | alu_decoder alu_decoder_instance ( 84 | .alu_control(alu_control), 85 | .funct7_5(funct7_5_d), 86 | .funct3(funct3_d), 87 | .alu_op(alu_op_d) 88 | ); 89 | 90 | // DECODE_EXECUTE REGISTER 91 | control_d_e_register control_d_e_register_instance ( 92 | .clk(clk), 93 | .rst(rst), 94 | .en(~stall_e), 95 | .clr(flush_e), 96 | .instr_d(instr_d), 97 | .instr_e(instr_e), 98 | .reg_write_d(reg_write_d), 99 | .mem_write_d(mem_write_d), 100 | .jump_d(jump_d), 101 | .branch_d(branch_d), 102 | .result_src_d(result_src_d), 103 | .alu_op_d(alu_op_d), 104 | .alu_src_a_sig_d(alu_src_a_sig_d), 105 | .alu_src_b_sig_d(alu_src_b_sig_d), 106 | .pc_target_src_d(pc_target_src_d), 107 | .branch_valid_src_d(branch_valid_src_d), 108 | .byte_half_enable_d(byte_half_enable_d), 109 | .funct3_d(funct3_d), // funct3 field from the instruction, used for byte/half instructions 110 | .reg_write_e(reg_write_e), 111 | .mem_write_e(mem_write_e), 112 | .jump_e(jump_e), 113 | .branch_e(branch_e), 114 | .result_src_e(result_src_e), 115 | .alu_op_e(alu_op_e), 116 | .alu_src_a_sig_e(alu_src_a_sig_e), 117 | .alu_src_b_sig_e(alu_src_b_sig_e), 118 | .pc_target_src_e(pc_target_src_e), 119 | .branch_valid_src_e(branch_valid_src_e), 120 | .byte_half_enable_e(byte_half_enable_e), 121 | .funct3_e(funct3_e) // funct3 field from the instruction, used for byte/half instructions 122 | ); 123 | 124 | // EXECUTE STAGE 125 | // We need to assign PCSrcE 126 | assign pc_src_e = (branch_e & branch_valid_e) | jump_e ? PC_SRC_PC_TARGET : PC_SRC_PC_PLUS_4; // PC source for branch/jump instructions 127 | 128 | // EXECUTE_MEMORY REGISTER 129 | control_e_m_register control_e_m_register_instance ( 130 | .clk(clk), 131 | .rst(rst), 132 | .en(~stall_m), 133 | .clr(1'b0), // No clear signal for the memory stage 134 | .instr_e(instr_e), 135 | .instr_m(instr_m), 136 | .reg_write_e(reg_write_e), 137 | .mem_write_e(mem_write_e), 138 | .result_src_e(result_src_e), 139 | .byte_half_enable_e(byte_half_enable_e), 140 | .funct3_e(funct3_e), // funct3 field from the instruction, used for byte/half instructions 141 | .reg_write_m(reg_write_m), 142 | .mem_write_m(mem_write_m), 143 | .result_src_m(result_src_m), 144 | .byte_half_enable_m(byte_half_enable_m), 145 | .funct3_m(funct3_m) // funct3 field from the instruction, used for byte/half instructions 146 | ); 147 | 148 | // MEMORY STAGE, we introduce the BYTE_HALF_DECODER 149 | byte_half_decoder byte_half_decoder_instance ( 150 | .byte_half_en_m(byte_half_enable_m), 151 | .funct3_m(funct3_m), 152 | .mem_addr_m(mem_addr_m[1:0]), 153 | .byte_half_sel(byte_half_sel_m), 154 | .word_ext(word_ext_m) 155 | ); 156 | 157 | 158 | // MEMORY_WRITEBACK REGISTER 159 | control_m_w_register control_m_w_register_instance ( 160 | .clk(clk), 161 | .rst(rst), 162 | .en(~stall_wb), 163 | .clr(1'b0), // No clear signal for the writeback stage 164 | .instr_m(instr_m), 165 | .instr_w(instr_w), 166 | .reg_write_m(reg_write_m), 167 | .result_src_m(result_src_m), 168 | .reg_write_w(reg_write_w), 169 | .result_src_w(result_src_w) 170 | ); 171 | 172 | endmodule 173 | -------------------------------------------------------------------------------- /src/modules/memory/data_bram.v: -------------------------------------------------------------------------------- 1 | // megafunction wizard: %RAM: 1-PORT% 2 | // GENERATION: STANDARD 3 | // VERSION: WM1.0 4 | // MODULE: altsyncram 5 | 6 | // ============================================================ 7 | // File Name: data_bram.v 8 | // Megafunction Name(s): 9 | // altsyncram 10 | // 11 | // Simulation Library Files(s): 12 | // altera_mf 13 | // ============================================================ 14 | // ************************************************************ 15 | // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! 16 | // 17 | // 24.1std.0 Build 1077 03/04/2025 SC Lite Edition 18 | // ************************************************************ 19 | 20 | 21 | //Copyright (C) 2025 Altera Corporation. All rights reserved. 22 | //Your use of Altera Corporation's design tools, logic functions 23 | //and other software and tools, and any partner logic 24 | //functions, and any output files from any of the foregoing 25 | //(including device programming or simulation files), and any 26 | //associated documentation or information are expressly subject 27 | //to the terms and conditions of the Altera Program License 28 | //Subscription Agreement, the Altera Quartus Prime License Agreement, 29 | //the Altera IP License Agreement, or other applicable license 30 | //agreement, including, without limitation, that your use is for 31 | //the sole purpose of programming logic devices manufactured by 32 | //Altera and sold by Altera or its authorized distributors. Please 33 | //refer to the Altera Software License Subscription Agreements 34 | //on the Quartus Prime software download page. 35 | 36 | 37 | // synopsys translate_off 38 | `timescale 1 ps / 1 ps 39 | // synopsys translate_on 40 | module data_bram ( 41 | address, 42 | byteena, 43 | clock, 44 | data, 45 | wren, 46 | q); 47 | 48 | input [12:0] address; 49 | input [3:0] byteena; 50 | input clock; 51 | input [31:0] data; 52 | input wren; 53 | output [31:0] q; 54 | `ifndef ALTERA_RESERVED_QIS 55 | // synopsys translate_off 56 | `endif 57 | tri1 [3:0] byteena; 58 | tri1 clock; 59 | `ifndef ALTERA_RESERVED_QIS 60 | // synopsys translate_on 61 | `endif 62 | 63 | wire [31:0] sub_wire0; 64 | wire [31:0] q = sub_wire0[31:0]; 65 | 66 | altsyncram altsyncram_component ( 67 | .address_a (address), 68 | .byteena_a (byteena), 69 | .clock0 (clock), 70 | .data_a (data), 71 | .wren_a (wren), 72 | .q_a (sub_wire0), 73 | .aclr0 (1'b0), 74 | .aclr1 (1'b0), 75 | .address_b (1'b1), 76 | .addressstall_a (1'b0), 77 | .addressstall_b (1'b0), 78 | .byteena_b (1'b1), 79 | .clock1 (1'b1), 80 | .clocken0 (1'b1), 81 | .clocken1 (1'b1), 82 | .clocken2 (1'b1), 83 | .clocken3 (1'b1), 84 | .data_b (1'b1), 85 | .eccstatus (), 86 | .q_b (), 87 | .rden_a (1'b1), 88 | .rden_b (1'b1), 89 | .wren_b (1'b0)); 90 | defparam 91 | altsyncram_component.byte_size = 8, 92 | altsyncram_component.clock_enable_input_a = "BYPASS", 93 | altsyncram_component.clock_enable_output_a = "BYPASS", 94 | altsyncram_component.intended_device_family = "MAX 10", 95 | altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO", 96 | altsyncram_component.lpm_type = "altsyncram", 97 | altsyncram_component.numwords_a = 8192, 98 | altsyncram_component.operation_mode = "SINGLE_PORT", 99 | altsyncram_component.outdata_aclr_a = "NONE", 100 | altsyncram_component.outdata_reg_a = "UNREGISTERED", 101 | altsyncram_component.power_up_uninitialized = "FALSE", 102 | altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ", 103 | altsyncram_component.widthad_a = 13, 104 | altsyncram_component.width_a = 32, 105 | altsyncram_component.width_byteena_a = 4; 106 | 107 | 108 | endmodule 109 | 110 | // ============================================================ 111 | // CNX file retrieval info 112 | // ============================================================ 113 | // Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" 114 | // Retrieval info: PRIVATE: AclrAddr NUMERIC "0" 115 | // Retrieval info: PRIVATE: AclrByte NUMERIC "0" 116 | // Retrieval info: PRIVATE: AclrData NUMERIC "0" 117 | // Retrieval info: PRIVATE: AclrOutput NUMERIC "0" 118 | // Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "1" 119 | // Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" 120 | // Retrieval info: PRIVATE: BlankMemory NUMERIC "1" 121 | // Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" 122 | // Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" 123 | // Retrieval info: PRIVATE: Clken NUMERIC "0" 124 | // Retrieval info: PRIVATE: DataBusSeparated NUMERIC "1" 125 | // Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" 126 | // Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" 127 | // Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" 128 | // Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "MAX 10" 129 | // Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" 130 | // Retrieval info: PRIVATE: JTAG_ID STRING "NONE" 131 | // Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" 132 | // Retrieval info: PRIVATE: MIFfilename STRING "" 133 | // Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "8192" 134 | // Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" 135 | // Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3" 136 | // Retrieval info: PRIVATE: RegAddr NUMERIC "1" 137 | // Retrieval info: PRIVATE: RegData NUMERIC "1" 138 | // Retrieval info: PRIVATE: RegOutput NUMERIC "0" 139 | // Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" 140 | // Retrieval info: PRIVATE: SingleClock NUMERIC "1" 141 | // Retrieval info: PRIVATE: UseDQRAM NUMERIC "1" 142 | // Retrieval info: PRIVATE: WRCONTROL_ACLR_A NUMERIC "0" 143 | // Retrieval info: PRIVATE: WidthAddr NUMERIC "13" 144 | // Retrieval info: PRIVATE: WidthData NUMERIC "32" 145 | // Retrieval info: PRIVATE: rden NUMERIC "0" 146 | // Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all 147 | // Retrieval info: CONSTANT: BYTE_SIZE NUMERIC "8" 148 | // Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" 149 | // Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" 150 | // Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "MAX 10" 151 | // Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" 152 | // Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" 153 | // Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "8192" 154 | // Retrieval info: CONSTANT: OPERATION_MODE STRING "SINGLE_PORT" 155 | // Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" 156 | // Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED" 157 | // Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE" 158 | // Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_NO_NBE_READ" 159 | // Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "13" 160 | // Retrieval info: CONSTANT: WIDTH_A NUMERIC "32" 161 | // Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "4" 162 | // Retrieval info: USED_PORT: address 0 0 13 0 INPUT NODEFVAL "address[12..0]" 163 | // Retrieval info: USED_PORT: byteena 0 0 4 0 INPUT VCC "byteena[3..0]" 164 | // Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" 165 | // Retrieval info: USED_PORT: data 0 0 32 0 INPUT NODEFVAL "data[31..0]" 166 | // Retrieval info: USED_PORT: q 0 0 32 0 OUTPUT NODEFVAL "q[31..0]" 167 | // Retrieval info: USED_PORT: wren 0 0 0 0 INPUT NODEFVAL "wren" 168 | // Retrieval info: CONNECT: @address_a 0 0 13 0 address 0 0 13 0 169 | // Retrieval info: CONNECT: @byteena_a 0 0 4 0 byteena 0 0 4 0 170 | // Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 171 | // Retrieval info: CONNECT: @data_a 0 0 32 0 data 0 0 32 0 172 | // Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0 173 | // Retrieval info: CONNECT: q 0 0 32 0 @q_a 0 0 32 0 174 | // Retrieval info: GEN_FILE: TYPE_NORMAL data_bram.v TRUE 175 | // Retrieval info: GEN_FILE: TYPE_NORMAL data_bram.inc FALSE 176 | // Retrieval info: GEN_FILE: TYPE_NORMAL data_bram.cmp FALSE 177 | // Retrieval info: GEN_FILE: TYPE_NORMAL data_bram.bsf FALSE 178 | // Retrieval info: GEN_FILE: TYPE_NORMAL data_bram_inst.v TRUE 179 | // Retrieval info: GEN_FILE: TYPE_NORMAL data_bram_bb.v FALSE 180 | // Retrieval info: LIB_FILE: altera_mf 181 | -------------------------------------------------------------------------------- /src/modules/cpu/control_unit/main_decoder.sv: -------------------------------------------------------------------------------- 1 | import types::*; 2 | 3 | module main_decoder( 4 | input logic [6:0] opcode, 5 | input logic [2:0] funct3, 6 | 7 | output bool_t reg_write, 8 | output result_src_t result_src, 9 | output bool_t mem_write, 10 | output bool_t jump, 11 | output bool_t branch, 12 | output alu_control_t alu_control, 13 | output alu_src_a_sig_t alu_src_a_sig, 14 | output alu_src_b_sig_t alu_src_b_sig, 15 | output immsrc_t immsrc, 16 | output pc_target_src_t pc_target_src, 17 | output branch_valid_src_t branch_valid_src, 18 | output logic byte_half_enable_d 19 | ); 20 | 21 | always_comb begin 22 | reg_write = FALSE; 23 | result_src = RESULT_SRC_ALU; 24 | mem_write = FALSE; 25 | jump = FALSE; 26 | branch = FALSE; 27 | alu_control = ALU_CONTROL_ADD; 28 | alu_src_a_sig = ALU_SRC_A_RS1; 29 | alu_src_b_sig = ALU_SRC_B_RS2; 30 | immsrc = IMMSRC_I_TYPE; 31 | pc_target_src = PC_TARGET_PC; 32 | branch_valid_src = BRANCH_VALID_ZERO; 33 | byte_half_enable_d = 1'b0; // Default value for byte/half enable signal 34 | 35 | case (opcode) 36 | OPCODE_LOAD: begin 37 | reg_write = TRUE; 38 | result_src = RESULT_SRC_MEM; 39 | mem_write = FALSE; 40 | jump = FALSE; 41 | branch = FALSE; 42 | alu_control = ALU_CONTROL_ADD; 43 | alu_src_a_sig = ALU_SRC_A_RS1; 44 | alu_src_b_sig = ALU_SRC_B_IMM; 45 | immsrc = IMMSRC_I_TYPE; 46 | pc_target_src = PC_TARGET_PC; // We don't care 47 | branch_valid_src = BRANCH_VALID_ZERO; 48 | byte_half_enable_d = 1'b1; // Enable byte/half extension for load instructions 49 | end 50 | OPCODE_I_TYPE: begin 51 | reg_write = TRUE; 52 | result_src = RESULT_SRC_ALU; 53 | mem_write = FALSE; 54 | jump = FALSE; 55 | branch = FALSE; 56 | alu_control = ALU_CONTROL_ITYPE; // We delegate the operation control to the ALU decoder 57 | alu_src_a_sig = ALU_SRC_A_RS1; // We use rs1 as the first operand 58 | alu_src_b_sig = ALU_SRC_B_IMM; // We use the immediate 59 | case(funct3) // We look at funct3 to chose between I or UI type immediate decoding 60 | // UIMM for SLLI, SRLI, SRAI (SRLI and SRAI both have funct3 101) 61 | 3'b001: immsrc = IMMSRC_UI_TYPE; 62 | 3'b101: immsrc = IMMSRC_UI_TYPE; 63 | default: immsrc = IMMSRC_I_TYPE; 64 | endcase 65 | pc_target_src = PC_TARGET_PC; 66 | branch_valid_src = BRANCH_VALID_ZERO; 67 | byte_half_enable_d = 1'b0; 68 | end 69 | OPCODE_AUIPC: begin 70 | reg_write = TRUE; 71 | result_src = RESULT_SRC_ALU; 72 | mem_write = FALSE; 73 | jump = FALSE; 74 | branch = FALSE; 75 | alu_control = ALU_CONTROL_ADD; // Add upper immediate to program counter 76 | alu_src_a_sig = ALU_SRC_A_PC; 77 | alu_src_b_sig = ALU_SRC_B_IMM; 78 | immsrc = IMMSRC_U_TYPE; 79 | pc_target_src = PC_TARGET_PC; 80 | branch_valid_src = BRANCH_VALID_ZERO; 81 | byte_half_enable_d = 1'b0; // No byte/half extension for AUIPC 82 | end 83 | OPCODE_STORE: begin 84 | reg_write = FALSE; // we discard the result after the mem stage because we don't care 85 | result_src = RESULT_SRC_ALU; // We don't care 86 | mem_write = TRUE; 87 | jump = FALSE; 88 | branch = FALSE; 89 | alu_control = ALU_CONTROL_ADD; // we add rs1 with the immediate 90 | alu_src_a_sig = ALU_SRC_A_RS1; 91 | alu_src_b_sig = ALU_SRC_B_IMM; 92 | immsrc = IMMSRC_S_TYPE; 93 | pc_target_src = PC_TARGET_PC; 94 | branch_valid_src = BRANCH_VALID_ZERO; 95 | byte_half_enable_d = 1'b1; // Enable byte/half extension for store instructions 96 | end 97 | OPCODE_R: begin 98 | reg_write = TRUE; 99 | result_src = RESULT_SRC_ALU; 100 | mem_write = FALSE; 101 | jump = FALSE; 102 | branch = FALSE; 103 | alu_control = ALU_CONTROL_RTYPE; 104 | alu_src_a_sig = ALU_SRC_A_RS1; 105 | alu_src_b_sig = ALU_SRC_B_RS2; 106 | immsrc = IMMSRC_I_TYPE; // we don't care 107 | pc_target_src = PC_TARGET_PC; 108 | branch_valid_src = BRANCH_VALID_ZERO; 109 | byte_half_enable_d = 1'b0; // No byte/half extension for R-type instructions 110 | end 111 | OPCODE_LUI: begin 112 | reg_write = TRUE; 113 | result_src = RESULT_SRC_IMM; 114 | mem_write = FALSE; 115 | jump = FALSE; 116 | branch = FALSE; 117 | alu_control = ALU_CONTROL_ADD; // We don't care 118 | alu_src_a_sig = ALU_SRC_A_RS1; // We don't care 119 | alu_src_b_sig = ALU_SRC_B_IMM; // We don't care 120 | immsrc = IMMSRC_U_TYPE; // LUI uses U-Type immediate 121 | pc_target_src = PC_TARGET_PC; // We don't care 122 | branch_valid_src = BRANCH_VALID_ZERO; 123 | byte_half_enable_d = 1'b0; // No byte/half extension for LUI 124 | end 125 | OPCODE_BRANCH: begin 126 | // Only handle BEQ for now, we'll need alu_result[0] and a funct3 and a multiplexer (branch_flag_src) on the control logic to chose between zero flag and alu_result[0] 127 | // PCTarget is calculated by the execute stage by the PC adder so we're not using the MEM and WB stage 128 | reg_write = FALSE; 129 | result_src = RESULT_SRC_ALU; // We don't care 130 | mem_write = FALSE; 131 | jump = FALSE; 132 | branch = TRUE; 133 | alu_control = ALU_CONTROL_BTYPE; 134 | alu_src_a_sig = ALU_SRC_A_RS1; // We use rs1 as the first operand 135 | alu_src_b_sig = ALU_SRC_B_RS2; // We use rs2 as the second operand 136 | immsrc = IMMSRC_B_TYPE; 137 | pc_target_src = PC_TARGET_PC; // We use the PC + Imm as BTA 138 | case(funct3) 139 | 3'b000: branch_valid_src = BRANCH_VALID_ZERO; // When beq, select the zero flag 140 | 3'b001: branch_valid_src = BRANCH_VALID_ZEROB; // When bne, select the "not zero" flag 141 | default: branch_valid_src = BRANCH_VALID_ALU0; // in any other case, we look at the ALU result (BLT, BGE...) 142 | endcase 143 | byte_half_enable_d = 1'b0; // No byte/half extension for branch instructions 144 | end 145 | OPCODE_JAL: begin 146 | reg_write = TRUE; // we write PC+4 to RD 147 | result_src = RESULT_SRC_PC_PLUS_4; 148 | mem_write = FALSE; 149 | jump = TRUE; 150 | branch = FALSE; 151 | alu_control = ALU_CONTROL_ADD; // We don't care, we're not using the result 152 | alu_src_a_sig = ALU_SRC_A_RS1; // We don't care 153 | alu_src_b_sig = ALU_SRC_B_RS2; // We don't care 154 | immsrc = IMMSRC_J_TYPE; // J-Type immediate, label is 20 bit immediate 155 | pc_target_src = PC_TARGET_PC; // We use the PC + imm as JTA 156 | branch_valid_src = BRANCH_VALID_ZERO; // We don't care 157 | byte_half_enable_d = 1'b0; // No byte/half extension for JAL 158 | 159 | end 160 | OPCODE_JALR: begin 161 | reg_write = TRUE; // We write PC+4 to RD 162 | result_src = RESULT_SRC_PC_PLUS_4; 163 | mem_write = FALSE; 164 | jump = TRUE; 165 | branch = FALSE; 166 | alu_control = ALU_CONTROL_ADD; // We're not using the ALU 167 | alu_src_a_sig = ALU_SRC_A_RS1; // We don't care 168 | alu_src_b_sig = ALU_SRC_B_RS2; // We don't care 169 | immsrc = IMMSRC_I_TYPE; // JALR uses I-Type immediate 170 | pc_target_src = PC_TARGET_RS1; // We use RS1 + imm as our JTA 171 | branch_valid_src = BRANCH_VALID_ZERO; // We don't care 172 | byte_half_enable_d = 1'b0; // No byte/half extension for JALR 173 | end 174 | default: ; // Use default values 175 | endcase 176 | 177 | end 178 | 179 | 180 | endmodule 181 | -------------------------------------------------------------------------------- /src/dokifive_p50_top.sdc: -------------------------------------------------------------------------------- 1 | ## Generated SDC file "dokifive_p50_top.sdc" 2 | 3 | ## Copyright (C) 2025 Altera Corporation. All rights reserved. 4 | ## Your use of Altera Corporation's design tools, logic functions 5 | ## and other software and tools, and any partner logic 6 | ## functions, and any output files from any of the foregoing 7 | ## (including device programming or simulation files), and any 8 | ## associated documentation or information are expressly subject 9 | ## to the terms and conditions of the Altera Program License 10 | ## Subscription Agreement, the Altera Quartus Prime License Agreement, 11 | ## the Altera IP License Agreement, or other applicable license 12 | ## agreement, including, without limitation, that your use is for 13 | ## the sole purpose of programming logic devices manufactured by 14 | ## Altera and sold by Altera or its authorized distributors. Please 15 | ## refer to the Altera Software License Subscription Agreements 16 | ## on the Quartus Prime software download page. 17 | 18 | 19 | ## VENDOR "Altera" 20 | ## PROGRAM "Quartus Prime" 21 | ## VERSION "Version 24.1std.0 Build 1077 03/04/2025 SC Lite Edition" 22 | 23 | ## DATE "Sat May 3 17:09:40 2025" 24 | 25 | ## 26 | ## DEVICE "10M50DAF484C7G" 27 | ## 28 | 29 | 30 | #************************************************************** 31 | # Time Information 32 | #************************************************************** 33 | 34 | set_time_format -unit ns -decimal_places 3 35 | 36 | 37 | 38 | #************************************************************** 39 | # Create Clock 40 | #************************************************************** 41 | 42 | create_clock -name {ADC_CLK_10} -period 100.000 -waveform { 0.000 50.000 } [get_ports {ADC_CLK_10}] 43 | create_clock -name {MAX10_CLK1_50} -period 20.000 -waveform { 0.000 10.000 } [get_ports {MAX10_CLK1_50}] 44 | create_clock -name {MAX10_CLK2_50} -period 20.000 -waveform { 0.000 10.000 } [get_ports {MAX10_CLK2_50}] 45 | 46 | 47 | #************************************************************** 48 | # Create Generated Clock 49 | #************************************************************** 50 | 51 | 52 | 53 | #************************************************************** 54 | # Set Clock Latency 55 | #************************************************************** 56 | 57 | 58 | 59 | #************************************************************** 60 | # Set Clock Uncertainty 61 | #************************************************************** 62 | 63 | set_clock_uncertainty -rise_from [get_clocks {MAX10_CLK1_50}] -rise_to [get_clocks {MAX10_CLK1_50}] 0.020 64 | set_clock_uncertainty -rise_from [get_clocks {MAX10_CLK1_50}] -fall_to [get_clocks {MAX10_CLK1_50}] 0.020 65 | set_clock_uncertainty -fall_from [get_clocks {MAX10_CLK1_50}] -rise_to [get_clocks {MAX10_CLK1_50}] 0.020 66 | set_clock_uncertainty -fall_from [get_clocks {MAX10_CLK1_50}] -fall_to [get_clocks {MAX10_CLK1_50}] 0.020 67 | 68 | 69 | #************************************************************** 70 | # Set Input Delay 71 | #************************************************************** 72 | 73 | set_input_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {KEY[0]}] 74 | set_input_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {KEY[1]}] 75 | 76 | 77 | #************************************************************** 78 | # Set Output Delay 79 | #************************************************************** 80 | 81 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX0[0]}] 82 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX0[1]}] 83 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX0[2]}] 84 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX0[3]}] 85 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX0[4]}] 86 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX0[5]}] 87 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX0[6]}] 88 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX0[7]}] 89 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX1[0]}] 90 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX1[1]}] 91 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX1[2]}] 92 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX1[3]}] 93 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX1[4]}] 94 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX1[5]}] 95 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX1[6]}] 96 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX1[7]}] 97 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX2[0]}] 98 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX2[1]}] 99 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX2[2]}] 100 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX2[3]}] 101 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX2[4]}] 102 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX2[5]}] 103 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX2[6]}] 104 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX2[7]}] 105 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX3[0]}] 106 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX3[1]}] 107 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX3[2]}] 108 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX3[3]}] 109 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX3[4]}] 110 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX3[5]}] 111 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX3[6]}] 112 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX3[7]}] 113 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX4[0]}] 114 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX4[1]}] 115 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX4[2]}] 116 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX4[3]}] 117 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX4[4]}] 118 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX4[5]}] 119 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX4[6]}] 120 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX4[7]}] 121 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX5[0]}] 122 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX5[1]}] 123 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX5[2]}] 124 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX5[3]}] 125 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX5[4]}] 126 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX5[5]}] 127 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX5[6]}] 128 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {HEX5[7]}] 129 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {LEDR[0]}] 130 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {LEDR[1]}] 131 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {LEDR[2]}] 132 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {LEDR[3]}] 133 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {LEDR[4]}] 134 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {LEDR[5]}] 135 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {LEDR[6]}] 136 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {LEDR[7]}] 137 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {LEDR[8]}] 138 | set_output_delay -add_delay -clock [get_clocks {MAX10_CLK1_50}] 1.000 [get_ports {LEDR[9]}] 139 | 140 | 141 | #************************************************************** 142 | # Set Clock Groups 143 | #************************************************************** 144 | 145 | 146 | 147 | #************************************************************** 148 | # Set False Path 149 | #************************************************************** 150 | 151 | 152 | 153 | #************************************************************** 154 | # Set Multicycle Path 155 | #************************************************************** 156 | 157 | 158 | 159 | #************************************************************** 160 | # Set Maximum Delay 161 | #************************************************************** 162 | 163 | 164 | 165 | #************************************************************** 166 | # Set Minimum Delay 167 | #************************************************************** 168 | 169 | 170 | 171 | #************************************************************** 172 | # Set Input Transition 173 | #************************************************************** 174 | 175 | -------------------------------------------------------------------------------- /src/modules/cpu/datapath/datapath.sv: -------------------------------------------------------------------------------- 1 | import types::*; 2 | 3 | module datapath( 4 | input logic clk, rst, 5 | input logic [31:0] instr_iw, // instruction fetched from memory 6 | input logic [31:0] mem_data_r_m, // data read from memory 7 | // OUTPUTS 8 | // Fetch stage 9 | output logic [31:0] pc_f, // it's fed before the clock edge to the memory controller because the memory is registered 10 | // Decode stage 11 | output logic [31:0] instr_d, // Instruction to be decoded, must be forwarded to the control unit as well as used by the decode stage 12 | // Execute stage 13 | output logic branch_valid_e, // zero flag from the ALU, used for branch/jump instructions 14 | // Memory stage 15 | output logic [31:0] mem_addr_m, // address for the data memory, used to read/write data from/to memory 16 | output logic [31:0] mem_data_w_m, // data to be written to memory, used to write data to memory 17 | 18 | // Hazard Unit signals 19 | // Stalls 20 | input logic stall_f, // stalls, the fetch stall should also be propagated to the instruction memory controller 21 | input logic stall_d, stall_e, stall_m, stall_wb, // stalls for decode, execute, memory and writeback stages respectively, 22 | // Flushes 23 | input logic flush_d, 24 | input logic flush_e, 25 | // Forwarding signals 26 | input rd1_fwd_t rd1_fwd_sel_e, // select signal for the first read data (rd1) 27 | input rd2_fwd_t rd2_fwd_sel_e, // select signal for the second read data (rd2) 28 | output logic [4:0] rs1_addr_e, rs2_addr_e, // rs1 and rs2 addresses from the execute stage 29 | output logic [4:0] rd_addr_m, rd_addr_wb, // rd address from the memory and writeback stages 30 | // Stall signals 31 | output logic [4:0] rs1_addr_d, rs2_addr_d, rd_addr_e, 32 | 33 | // Control Unit signals 34 | // decode 35 | input immsrc_t immsrc_d, 36 | // execute 37 | input pc_src_t pc_src_e, // PC source for branch/jump, used to switch between PC + 4 and the target address 38 | input alu_src_a_sig_t alu_src_a_sig_e, // ALU source A, used to switch between rs1 and the PC (AUIPC) 39 | input alu_src_b_sig_t alu_src_b_sig_e, // ALU source, used to switch between the second operand and the immediate value 40 | input alu_op_t alu_op, // ALU operation, used to select the operation to be performed by the ALU 41 | input pc_target_src_t pc_target_src_sig_e, 42 | input branch_valid_src_t branch_valid_src_e, 43 | // memory 44 | input byte_half_sel_t byte_half_sel_m, // Byte/half select signal, used for byte/half instructions 45 | input word_ext_t word_ext_m, // Word extension signal, used for byte/half instructions 46 | input result_src_t result_src_m, 47 | // writeback 48 | input bool_t reg_write_w, 49 | input result_src_t result_src_w 50 | // Control signals 51 | ); 52 | // INTERNAL DATAPATH SIGNALS 53 | // FETCH 54 | logic [31:0] pc_fnext, pc_plus_4_f; 55 | // INSTRUCTION WAIT 56 | // Instruction Wait stage 57 | logic [31:0] pc_iw; // PC to be used in the instruction wait stage, must be forwarded to the decode stage 58 | logic [31:0] pc_plus_4_iw; // PC + 4, used to calculate the target address for branch/jump instructions 59 | 60 | // DECODE 61 | logic [31:0] rd1_d, rd2_d, imm_ext_d; 62 | logic [4:0] ra1_d, ra2_d, wa3_d; // source registers addresses 63 | logic [31:0] pc_d, pc_plus_4_d; 64 | // EXECUTE 65 | logic [31:0] pc_e, pc_plus_4_e, imm_ext_e, pc_target_e, pc_target_src_e; 66 | logic [31:0] rd1_e, rd2_e; // operands for ALU, before forwarding 67 | logic [31:0] rd1_fwd_e, rd2_fwd_e; // operands for ALU, after forwarding 68 | logic [4:0] ra1_e, ra2_e, wa3_e; // source registers addresses 69 | logic [31:0] alu_src_a_e, alu_src_b_e, alu_result_e, w_data_e; // Alu result and write data from rd2_e (or forwared values) 70 | logic zero_e; 71 | 72 | // MEMORY 73 | logic [31:0] forwarded_value_m; // alu_result_m if result_src is not IMM 74 | logic [31:0] alu_result_m, pc_plus_4_m, imm_ext_m; // ALU result and write data from rd2_e (or forwared values) 75 | logic [4:0] wa3_m; // write address for the register file 76 | logic [31:0] mem_data_w_m_raw; 77 | logic [31:0] mem_data_r_m_ext; // data to be written to memory, after shifting logic 78 | 79 | // WRITEBACK 80 | logic [4:0] wa3_w; // write address for the register file 81 | logic [31:0] result_w; // result to be written back to the register file 82 | logic [31:0] r_data_w, pc_plus_4_w, alu_result_w, imm_ext_w; // Multiplexer inputs for the writeback stage 83 | 84 | // LOGIC 85 | // FETCH STAGE 86 | mux2 #( 87 | .WIDTH(32) 88 | ) mux2_pc_src ( 89 | .s(pc_src_e), 90 | .a(pc_plus_4_f), 91 | .b(pc_target_e), 92 | .out(pc_fnext) 93 | ); 94 | en_clr_arst_register #( 95 | .WIDTH(32), 96 | .OFFSET('h0000) // Should be 0x8000 when we introduce the bootloader 97 | ) pc_register ( 98 | .d(pc_fnext), 99 | .q(pc_f), 100 | .clk(clk), 101 | .rst(rst), 102 | .en(~stall_f), // enable the register only if not stalled 103 | .clr(1'b0) // no clear signal for the PC register 104 | ); 105 | assign pc_plus_4_f = pc_f + 4; // PC + 4 106 | 107 | // FETCH_INSTRUCTION_WAIT REGISTER 108 | f_iw_register f_iw_register_instance ( // waste one clock cycle for the instruction to arrive from memory 109 | .clk(clk), 110 | .rst(rst), 111 | .en(~stall_f), 112 | .clr(flush_d), 113 | .pc_f(pc_f), // Will be flushed with the iw_d register, that's what we want because of the RAM latency 114 | .pc_plus_4_f(pc_plus_4_f), 115 | .pc_iw(pc_iw), 116 | .pc_plus_4_iw(pc_plus_4_iw) 117 | ); 118 | 119 | // INSTRUCTION_WAIT_DECODE REGISTER 120 | iw_d_register f_d_register_instance ( 121 | .clk(clk), 122 | .rst(rst), 123 | .en(~stall_d), // enable the register only if not stalled 124 | .clr(flush_d), 125 | .instr_iw(instr_iw), 126 | .pc_iw(pc_iw), 127 | .pc_plus_4_iw(pc_plus_4_iw), 128 | .instr_d(instr_d), 129 | .pc_d(pc_d), 130 | .pc_plus_4_d(pc_plus_4_d) 131 | ); 132 | 133 | // DECODE STAGE 134 | assign ra1_d = instr_d[19:15]; // rs1 is instr_d[19:15] 135 | assign ra2_d = instr_d[24:20]; // rs2 is instr_d[24:20] 136 | assign wa3_d = instr_d[11:7]; // rd is instr_d[11:7] 137 | 138 | // Hazard unit assignment 139 | assign rs1_addr_d = ra1_d; 140 | assign rs2_addr_d = ra2_d; 141 | 142 | register_file rf ( 143 | .clk(~clk), // register file is clocked on the falling edge of the clock for simultaneous read/write operations 144 | .we3(reg_write_w), // write enable signal, comes from the writeback stage 145 | .ra1(ra1_d), 146 | .ra2(ra2_d), 147 | .wa3(wa3_w), // wa3 is the write address, comes from the writeback stage 148 | .wd3(result_w), // wd3 is the write data, comes from the writeback stage 149 | .rd1(rd1_d), 150 | .rd2(rd2_d) 151 | ); 152 | 153 | imm_extender imm_ext ( 154 | .immsrc(immsrc_d), 155 | .instr_31_7(instr_d[31:7]), 156 | .imm_ext(imm_ext_d) 157 | ); 158 | 159 | // DECODE_EXECUTE REGISTER 160 | d_e_register d_e_register_instance ( 161 | .clk(clk), 162 | .rst(rst), 163 | .en(~stall_e), // enable the register only if not stalled 164 | .clr(flush_e), 165 | .rd1_d(rd1_d), 166 | .rd2_d(rd2_d), 167 | .imm_ext_d(imm_ext_d), 168 | .pc_d(pc_d), 169 | .pc_plus_4_d(pc_plus_4_d), 170 | .ra1_d(ra1_d), 171 | .ra2_d(ra2_d), 172 | .wa3_d(wa3_d), 173 | .rd1_e(rd1_e), 174 | .rd2_e(rd2_e), 175 | .imm_ext_e(imm_ext_e), 176 | .pc_e(pc_e), 177 | .pc_plus_4_e(pc_plus_4_e), 178 | .ra1_e(ra1_e), 179 | .ra2_e(ra2_e), 180 | .wa3_e(wa3_e) 181 | ); 182 | 183 | // EXECUTE STAGE 184 | // Hazard Unit assignments 185 | assign rs1_addr_e = ra1_e; 186 | assign rs2_addr_e = ra2_e; 187 | assign rd_addr_e = wa3_e; 188 | 189 | // PC Target calculation 190 | logic [31:0] pc_target_sum_e; 191 | assign pc_target_sum_e = (pc_target_src_e + imm_ext_e); // PC target for branch/jump instructions 192 | assign pc_target_e = {pc_target_sum_e[31:1], 1'b0 }; // PC target for branch/jump instructions, zeroing the LSB 193 | // 194 | mux2 #( 195 | .WIDTH(32) 196 | ) pc_target_adder_src ( 197 | .s(pc_target_src_sig_e), 198 | .a(pc_e), 199 | .b(rd1_e), 200 | .out(pc_target_src_e) 201 | ); 202 | 203 | assign w_data_e = rd2_fwd_e; // write data for the data memory, after forwarding 204 | 205 | // forwarding logic 206 | mux4 #( 207 | .WIDTH(32) 208 | ) rd1_fwd_mux ( 209 | .s(rd1_fwd_sel_e), 210 | .a(rd1_e), 211 | .b(result_w), 212 | .c(forwarded_value_m), 213 | .d(32'hDEADBEEF), 214 | .out(rd1_fwd_e) 215 | ); 216 | mux4 #( 217 | .WIDTH(32) 218 | ) rd2_fwd_mux ( 219 | .s(rd2_fwd_sel_e), 220 | .a(rd2_e), 221 | .b(result_w), 222 | .c(forwarded_value_m), 223 | .d(32'hDEADBEEF), 224 | .out(rd2_fwd_e) 225 | ); 226 | // forwarding logic 227 | 228 | mux2 #( 229 | .WIDTH(32) 230 | ) alu_src_a_mux ( 231 | .s(alu_src_a_sig_e), 232 | .a(rd1_fwd_e), 233 | .b(pc_e), 234 | .out(alu_src_a_e) 235 | ); 236 | 237 | mux2 #( 238 | .WIDTH(32) 239 | ) alu_src_b_mux ( 240 | .s(alu_src_b_sig_e), 241 | .a(rd2_fwd_e), 242 | .b(imm_ext_e), 243 | .out(alu_src_b_e) 244 | ); 245 | 246 | // ALU 247 | alu alu_instance ( 248 | .a(alu_src_a_e), 249 | .b(alu_src_b_e), 250 | .alu_op(alu_op), 251 | .result(alu_result_e), 252 | .zero(zero_e) // zero flag for branch/jump instructions 253 | ); 254 | 255 | mux4 #( 256 | .WIDTH(1) 257 | ) branch_valid_mux ( 258 | .s(branch_valid_src_e), 259 | .a(zero_e), 260 | .b(~zero_e), 261 | .c(alu_result_e[0]), 262 | .d(1'b0), 263 | .out(branch_valid_e) 264 | ); 265 | 266 | // EXECUTE_MEMORY REGISTER 267 | e_m_register e_m_register_instance ( 268 | .clk(clk), 269 | .rst(rst), 270 | .en(~stall_m), // enable the register only if not stalled 271 | .clr(1'b0), // no clear signal for the execute memory register 272 | .alu_result_e(alu_result_e), 273 | .w_data_e(w_data_e), 274 | .pc_plus_4_e(pc_plus_4_e), 275 | .imm_ext_e(imm_ext_e), 276 | .wa3_e(wa3_e), 277 | .alu_result_m(alu_result_m), 278 | .w_data_m(mem_data_w_m_raw), // Before shifting logic 279 | .pc_plus_4_m(pc_plus_4_m), 280 | .imm_ext_m(imm_ext_m), 281 | .wa3_m(wa3_m) 282 | ); 283 | 284 | // MEMORY STAGE 285 | // Hazard unit assignments 286 | assign rd_addr_m = wa3_m; 287 | // Memory stage is simpler, as the bulk of the work is done outside of the datapath, eveything is already declared 288 | assign mem_addr_m = alu_result_m; // write address for the data memory 289 | assign forwarded_value_m = (result_src_m == RESULT_SRC_IMM) ? imm_ext_m : alu_result_m; // ALU result if result_src is not IMM 290 | 291 | // Byte store unit 292 | byte_store_unit byte_store_unit_instance ( 293 | .data_in(mem_data_w_m_raw), 294 | .byte_half_sel_m(byte_half_sel_m), 295 | .data_out(mem_data_w_m) 296 | ); 297 | 298 | byte_load_unit byte_load_unit_instance ( 299 | .data_in(mem_data_r_m), 300 | .byte_half_sel_m(byte_half_sel_m), 301 | .word_ext_m(word_ext_m), 302 | .data_out(mem_data_r_m_ext) 303 | ); 304 | 305 | // MEMORY_WRITEBACK REGISTER 306 | m_w_register m_w_register_instance ( 307 | .clk(clk), 308 | .rst(rst), 309 | .en(~stall_wb), // enable the register only if not stalled 310 | .clr(1'b0), // no clear signal for the memory writeback register 311 | .alu_result_m(alu_result_m), 312 | .r_data_m(mem_data_r_m_ext), 313 | .pc_plus_4_m(pc_plus_4_m), 314 | .imm_ext_m(imm_ext_m), 315 | .wa3_m(wa3_m), 316 | .alu_result_w(alu_result_w), // ALU result to be written back to the register file 317 | .r_data_w(r_data_w), // data read from memory 318 | .pc_plus_4_w(pc_plus_4_w), 319 | .imm_ext_w(imm_ext_w), // immediate value to be written back to the register file 320 | .wa3_w(wa3_w) // write address for the register file, 321 | ); 322 | 323 | // WRITE BACK STAGE 324 | // Hazard unit assignments 325 | assign rd_addr_wb = wa3_w; 326 | 327 | mux4 #( 328 | .WIDTH(32) 329 | ) wb_mux ( 330 | .s(result_src_w), 331 | .a(alu_result_w), 332 | .b(r_data_w), 333 | .c(pc_plus_4_w), 334 | .d(imm_ext_w), 335 | .out(result_w) 336 | ); 337 | 338 | endmodule 339 | -------------------------------------------------------------------------------- /simulation/dokifive_p50.cr.mti: -------------------------------------------------------------------------------- 1 | C:/Users/julien/Documents/fpga/dokifive_p50/tests/tb_soc.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/tests/tb_soc.sv 2 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 3 | -- Compiling package tb_soc_sv_unit 4 | -- Importing package io 5 | -- Compiling module tb_soc 6 | 7 | Top level modules: 8 | tb_soc 9 | 10 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/dokifive_soc.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/dokifive_soc.sv 11 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 12 | -- Compiling package dokifive_soc_sv_unit 13 | -- Importing package types 14 | -- Importing package io 15 | -- Compiling module dokifive_soc 16 | 17 | Top level modules: 18 | dokifive_soc 19 | 20 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/control_unit/control_m_w_register.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/control_unit/control_m_w_register.sv 21 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 22 | -- Compiling package control_m_w_register_sv_unit 23 | -- Importing package types 24 | -- Compiling module control_m_w_register 25 | 26 | Top level modules: 27 | control_m_w_register 28 | 29 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/control_unit/alu_decoder.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/control_unit/alu_decoder.sv 30 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 31 | -- Compiling package alu_decoder_sv_unit 32 | -- Importing package types 33 | -- Compiling module alu_decoder 34 | 35 | Top level modules: 36 | alu_decoder 37 | 38 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/datapath/f_iw_register.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/datapath/f_iw_register.sv 39 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 40 | -- Compiling module f_iw_register 41 | 42 | Top level modules: 43 | f_iw_register 44 | 45 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/datapath/byte_load_unit.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/datapath/byte_load_unit.sv 46 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 47 | -- Compiling package byte_load_unit_sv_unit 48 | -- Importing package types 49 | -- Compiling module byte_load_unit 50 | 51 | Top level modules: 52 | byte_load_unit 53 | 54 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/hazard_unit/lw_fsm.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/hazard_unit/lw_fsm.sv 55 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 56 | -- Compiling package lw_fsm_sv_unit 57 | -- Importing package types 58 | -- Compiling module lw_fsm 59 | 60 | Top level modules: 61 | lw_fsm 62 | 63 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/hazard_unit/hazard_unit.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/hazard_unit/hazard_unit.sv 64 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 65 | -- Compiling package hazard_unit_sv_unit 66 | -- Importing package types 67 | -- Compiling module hazard_unit 68 | 69 | Top level modules: 70 | hazard_unit 71 | 72 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/memory/data_bram.v {1 {vlog -work work -vopt -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/memory/data_bram.v 73 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 74 | -- Compiling module data_bram 75 | 76 | Top level modules: 77 | data_bram 78 | 79 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/memory/instruction_memory.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/memory/instruction_memory.sv 80 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 81 | -- Compiling package instruction_memory_sv_unit 82 | -- Importing package types 83 | -- Compiling module instruction_memory 84 | 85 | Top level modules: 86 | instruction_memory 87 | 88 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/control_unit/control_d_e_register.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/control_unit/control_d_e_register.sv 89 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 90 | -- Compiling package control_d_e_register_sv_unit 91 | -- Importing package types 92 | -- Compiling module control_d_e_register 93 | 94 | Top level modules: 95 | control_d_e_register 96 | 97 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/memory/gprmm_registers.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/memory/gprmm_registers.sv 98 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 99 | -- Compiling package gprmm_registers_sv_unit 100 | -- Importing package io 101 | -- Compiling module gprmm_registers 102 | 103 | Top level modules: 104 | gprmm_registers 105 | 106 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/datapath/e_m_register.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/datapath/e_m_register.sv 107 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 108 | -- Compiling module e_m_register 109 | 110 | Top level modules: 111 | e_m_register 112 | 113 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/packages/types.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/packages/types.sv 114 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 115 | -- Compiling package types 116 | 117 | Top level modules: 118 | --none-- 119 | 120 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/datapath/byte_store_unit.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/datapath/byte_store_unit.sv 121 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 122 | -- Compiling package byte_store_unit_sv_unit 123 | -- Importing package types 124 | -- Compiling module byte_store_unit 125 | 126 | Top level modules: 127 | byte_store_unit 128 | 129 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/datapath/iw_d_register.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/datapath/iw_d_register.sv 130 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 131 | -- Compiling module iw_d_register 132 | 133 | Top level modules: 134 | iw_d_register 135 | 136 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/datapath/m_w_register.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/datapath/m_w_register.sv 137 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 138 | -- Compiling module m_w_register 139 | 140 | Top level modules: 141 | m_w_register 142 | 143 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/sync/en_clr_arst_register.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/sync/en_clr_arst_register.sv 144 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 145 | -- Compiling module en_clr_arst_register 146 | 147 | Top level modules: 148 | en_clr_arst_register 149 | 150 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/muxes/mux2.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/muxes/mux2.sv 151 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 152 | -- Compiling module mux2 153 | 154 | Top level modules: 155 | mux2 156 | 157 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/packages/io.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/packages/io.sv 158 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 159 | -- Compiling package io 160 | 161 | Top level modules: 162 | --none-- 163 | 164 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/control_unit/control_unit.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/control_unit/control_unit.sv 165 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 166 | -- Compiling package control_unit_sv_unit 167 | -- Importing package types 168 | -- Compiling module control_unit 169 | 170 | Top level modules: 171 | control_unit 172 | 173 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/datapath/imm_extender.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/datapath/imm_extender.sv 174 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 175 | -- Compiling package imm_extender_sv_unit 176 | -- Importing package signals 177 | -- Importing package types 178 | -- Compiling module imm_extender 179 | 180 | Top level modules: 181 | imm_extender 182 | 183 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/cpu.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/cpu.sv 184 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 185 | -- Compiling package cpu_sv_unit 186 | -- Importing package types 187 | -- Compiling module cpu 188 | 189 | Top level modules: 190 | cpu 191 | 192 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/packages/signals.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/packages/signals.sv 193 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 194 | -- Compiling package signals 195 | 196 | Top level modules: 197 | --none-- 198 | 199 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/muxes/mux4.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/muxes/mux4.sv 200 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 201 | -- Compiling module mux4 202 | 203 | Top level modules: 204 | mux4 205 | 206 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/datapath/alu.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/datapath/alu.sv 207 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 208 | -- Compiling package alu_sv_unit 209 | -- Importing package types 210 | -- Compiling module alu 211 | 212 | Top level modules: 213 | alu 214 | 215 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/control_unit/main_decoder.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/control_unit/main_decoder.sv 216 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 217 | -- Compiling package main_decoder_sv_unit 218 | -- Importing package types 219 | -- Compiling module main_decoder 220 | 221 | Top level modules: 222 | main_decoder 223 | 224 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/control_unit/byte_half_decoder.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/control_unit/byte_half_decoder.sv 225 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 226 | -- Compiling package byte_half_decoder_sv_unit 227 | -- Importing package types 228 | -- Compiling module byte_half_decoder 229 | 230 | Top level modules: 231 | byte_half_decoder 232 | 233 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/datapath/register_file.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/datapath/register_file.sv 234 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 235 | -- Compiling module register_file 236 | 237 | Top level modules: 238 | register_file 239 | 240 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/datapath/d_e_register.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/datapath/d_e_register.sv 241 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 242 | -- Compiling module d_e_register 243 | 244 | Top level modules: 245 | d_e_register 246 | 247 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/control_unit/control_e_m_register.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/control_unit/control_e_m_register.sv 248 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 249 | -- Compiling package control_e_m_register_sv_unit 250 | -- Importing package types 251 | -- Compiling module control_e_m_register 252 | 253 | Top level modules: 254 | control_e_m_register 255 | 256 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/datapath/datapath.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/cpu/datapath/datapath.sv 257 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 258 | -- Compiling package datapath_sv_unit 259 | -- Importing package types 260 | -- Compiling module datapath 261 | 262 | Top level modules: 263 | datapath 264 | 265 | } {} {}} C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/memory/memory_controller.sv {1 {vlog -work work -vopt -sv -stats=none C:/Users/julien/Documents/fpga/dokifive_p50/src/modules/memory/memory_controller.sv 266 | Questa Intel Starter FPGA Edition-64 vlog 2024.3 Compiler 2024.09 Sep 10 2024 267 | -- Compiling package memory_controller_sv_unit 268 | -- Importing package types 269 | -- Importing package io 270 | -- Compiling module memory_controller 271 | 272 | Top level modules: 273 | memory_controller 274 | 275 | } {} {}} 276 | -------------------------------------------------------------------------------- /src/dokifive_p50_top.qsf: -------------------------------------------------------------------------------- 1 | #============================================================ 2 | # Build by Terasic System Builder 3 | #============================================================ 4 | 5 | set_global_assignment -name FAMILY "MAX 10" 6 | set_global_assignment -name DEVICE 10M50DAF484C7G 7 | set_global_assignment -name TOP_LEVEL_ENTITY "dokifive_p50_top" 8 | set_global_assignment -name ORIGINAL_QUARTUS_VERSION "16.0.0" 9 | set_global_assignment -name LAST_QUARTUS_VERSION "24.1std.0 Lite Edition" 10 | set_global_assignment -name PROJECT_CREATION_TIME_DATE "19:14:34 APRIL 28,2025" 11 | set_global_assignment -name DEVICE_FILTER_PACKAGE FBGA 12 | set_global_assignment -name DEVICE_FILTER_PIN_COUNT 484 13 | set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 7 14 | 15 | #============================================================ 16 | # CLOCK 17 | #============================================================ 18 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ADC_CLK_10 19 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to MAX10_CLK1_50 20 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to MAX10_CLK2_50 21 | set_location_assignment PIN_N5 -to ADC_CLK_10 22 | set_location_assignment PIN_P11 -to MAX10_CLK1_50 23 | set_location_assignment PIN_N14 -to MAX10_CLK2_50 24 | 25 | #============================================================ 26 | # SDRAM 27 | #============================================================ 28 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[0] 29 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[1] 30 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[2] 31 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[3] 32 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[4] 33 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[5] 34 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[6] 35 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[7] 36 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[8] 37 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[9] 38 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[10] 39 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[11] 40 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[12] 41 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_BA[0] 42 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_BA[1] 43 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_CAS_N 44 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_CKE 45 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_CLK 46 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_CS_N 47 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[0] 48 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[1] 49 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[2] 50 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[3] 51 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[4] 52 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[5] 53 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[6] 54 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[7] 55 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[8] 56 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[9] 57 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[10] 58 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[11] 59 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[12] 60 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[13] 61 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[14] 62 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[15] 63 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_LDQM 64 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_RAS_N 65 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_UDQM 66 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_WE_N 67 | set_location_assignment PIN_U17 -to DRAM_ADDR[0] 68 | set_location_assignment PIN_W19 -to DRAM_ADDR[1] 69 | set_location_assignment PIN_V18 -to DRAM_ADDR[2] 70 | set_location_assignment PIN_U18 -to DRAM_ADDR[3] 71 | set_location_assignment PIN_U19 -to DRAM_ADDR[4] 72 | set_location_assignment PIN_T18 -to DRAM_ADDR[5] 73 | set_location_assignment PIN_T19 -to DRAM_ADDR[6] 74 | set_location_assignment PIN_R18 -to DRAM_ADDR[7] 75 | set_location_assignment PIN_P18 -to DRAM_ADDR[8] 76 | set_location_assignment PIN_P19 -to DRAM_ADDR[9] 77 | set_location_assignment PIN_T20 -to DRAM_ADDR[10] 78 | set_location_assignment PIN_P20 -to DRAM_ADDR[11] 79 | set_location_assignment PIN_R20 -to DRAM_ADDR[12] 80 | set_location_assignment PIN_T21 -to DRAM_BA[0] 81 | set_location_assignment PIN_T22 -to DRAM_BA[1] 82 | set_location_assignment PIN_U21 -to DRAM_CAS_N 83 | set_location_assignment PIN_N22 -to DRAM_CKE 84 | set_location_assignment PIN_L14 -to DRAM_CLK 85 | set_location_assignment PIN_U20 -to DRAM_CS_N 86 | set_location_assignment PIN_Y21 -to DRAM_DQ[0] 87 | set_location_assignment PIN_Y20 -to DRAM_DQ[1] 88 | set_location_assignment PIN_AA22 -to DRAM_DQ[2] 89 | set_location_assignment PIN_AA21 -to DRAM_DQ[3] 90 | set_location_assignment PIN_Y22 -to DRAM_DQ[4] 91 | set_location_assignment PIN_W22 -to DRAM_DQ[5] 92 | set_location_assignment PIN_W20 -to DRAM_DQ[6] 93 | set_location_assignment PIN_V21 -to DRAM_DQ[7] 94 | set_location_assignment PIN_P21 -to DRAM_DQ[8] 95 | set_location_assignment PIN_J22 -to DRAM_DQ[9] 96 | set_location_assignment PIN_H21 -to DRAM_DQ[10] 97 | set_location_assignment PIN_H22 -to DRAM_DQ[11] 98 | set_location_assignment PIN_G22 -to DRAM_DQ[12] 99 | set_location_assignment PIN_G20 -to DRAM_DQ[13] 100 | set_location_assignment PIN_G19 -to DRAM_DQ[14] 101 | set_location_assignment PIN_F22 -to DRAM_DQ[15] 102 | set_location_assignment PIN_V22 -to DRAM_LDQM 103 | set_location_assignment PIN_U22 -to DRAM_RAS_N 104 | set_location_assignment PIN_J21 -to DRAM_UDQM 105 | set_location_assignment PIN_V20 -to DRAM_WE_N 106 | 107 | #============================================================ 108 | # SEG7 109 | #============================================================ 110 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX0[0] 111 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX0[1] 112 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX0[2] 113 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX0[3] 114 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX0[4] 115 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX0[5] 116 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX0[6] 117 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX0[7] 118 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX1[0] 119 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX1[1] 120 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX1[2] 121 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX1[3] 122 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX1[4] 123 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX1[5] 124 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX1[6] 125 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX1[7] 126 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX2[0] 127 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX2[1] 128 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX2[2] 129 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX2[3] 130 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX2[4] 131 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX2[5] 132 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX2[6] 133 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX2[7] 134 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[0] 135 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[1] 136 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[2] 137 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[3] 138 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[4] 139 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[5] 140 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[6] 141 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[7] 142 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[0] 143 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[1] 144 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[2] 145 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[3] 146 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[4] 147 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[5] 148 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[6] 149 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[7] 150 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[0] 151 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[1] 152 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[2] 153 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[3] 154 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[4] 155 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[5] 156 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[6] 157 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[7] 158 | set_location_assignment PIN_C14 -to HEX0[0] 159 | set_location_assignment PIN_E15 -to HEX0[1] 160 | set_location_assignment PIN_C15 -to HEX0[2] 161 | set_location_assignment PIN_C16 -to HEX0[3] 162 | set_location_assignment PIN_E16 -to HEX0[4] 163 | set_location_assignment PIN_D17 -to HEX0[5] 164 | set_location_assignment PIN_C17 -to HEX0[6] 165 | set_location_assignment PIN_D15 -to HEX0[7] 166 | set_location_assignment PIN_C18 -to HEX1[0] 167 | set_location_assignment PIN_D18 -to HEX1[1] 168 | set_location_assignment PIN_E18 -to HEX1[2] 169 | set_location_assignment PIN_B16 -to HEX1[3] 170 | set_location_assignment PIN_A17 -to HEX1[4] 171 | set_location_assignment PIN_A18 -to HEX1[5] 172 | set_location_assignment PIN_B17 -to HEX1[6] 173 | set_location_assignment PIN_A16 -to HEX1[7] 174 | set_location_assignment PIN_B20 -to HEX2[0] 175 | set_location_assignment PIN_A20 -to HEX2[1] 176 | set_location_assignment PIN_B19 -to HEX2[2] 177 | set_location_assignment PIN_A21 -to HEX2[3] 178 | set_location_assignment PIN_B21 -to HEX2[4] 179 | set_location_assignment PIN_C22 -to HEX2[5] 180 | set_location_assignment PIN_B22 -to HEX2[6] 181 | set_location_assignment PIN_A19 -to HEX2[7] 182 | set_location_assignment PIN_F21 -to HEX3[0] 183 | set_location_assignment PIN_E22 -to HEX3[1] 184 | set_location_assignment PIN_E21 -to HEX3[2] 185 | set_location_assignment PIN_C19 -to HEX3[3] 186 | set_location_assignment PIN_C20 -to HEX3[4] 187 | set_location_assignment PIN_D19 -to HEX3[5] 188 | set_location_assignment PIN_E17 -to HEX3[6] 189 | set_location_assignment PIN_D22 -to HEX3[7] 190 | set_location_assignment PIN_F18 -to HEX4[0] 191 | set_location_assignment PIN_E20 -to HEX4[1] 192 | set_location_assignment PIN_E19 -to HEX4[2] 193 | set_location_assignment PIN_J18 -to HEX4[3] 194 | set_location_assignment PIN_H19 -to HEX4[4] 195 | set_location_assignment PIN_F19 -to HEX4[5] 196 | set_location_assignment PIN_F20 -to HEX4[6] 197 | set_location_assignment PIN_F17 -to HEX4[7] 198 | set_location_assignment PIN_J20 -to HEX5[0] 199 | set_location_assignment PIN_K20 -to HEX5[1] 200 | set_location_assignment PIN_L18 -to HEX5[2] 201 | set_location_assignment PIN_N18 -to HEX5[3] 202 | set_location_assignment PIN_M20 -to HEX5[4] 203 | set_location_assignment PIN_N19 -to HEX5[5] 204 | set_location_assignment PIN_N20 -to HEX5[6] 205 | set_location_assignment PIN_L19 -to HEX5[7] 206 | 207 | #============================================================ 208 | # KEY 209 | #============================================================ 210 | set_instance_assignment -name IO_STANDARD "3.3 V Schmitt Trigger" -to KEY[0] 211 | set_instance_assignment -name IO_STANDARD "3.3 V Schmitt Trigger" -to KEY[1] 212 | set_location_assignment PIN_B8 -to KEY[0] 213 | set_location_assignment PIN_A7 -to KEY[1] 214 | 215 | #============================================================ 216 | # LED 217 | #============================================================ 218 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LEDR[0] 219 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LEDR[1] 220 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LEDR[2] 221 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LEDR[3] 222 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LEDR[4] 223 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LEDR[5] 224 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LEDR[6] 225 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LEDR[7] 226 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LEDR[8] 227 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LEDR[9] 228 | set_location_assignment PIN_A8 -to LEDR[0] 229 | set_location_assignment PIN_A9 -to LEDR[1] 230 | set_location_assignment PIN_A10 -to LEDR[2] 231 | set_location_assignment PIN_B10 -to LEDR[3] 232 | set_location_assignment PIN_D13 -to LEDR[4] 233 | set_location_assignment PIN_C13 -to LEDR[5] 234 | set_location_assignment PIN_E14 -to LEDR[6] 235 | set_location_assignment PIN_D14 -to LEDR[7] 236 | set_location_assignment PIN_A11 -to LEDR[8] 237 | set_location_assignment PIN_B11 -to LEDR[9] 238 | 239 | #============================================================ 240 | # SW 241 | #============================================================ 242 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[0] 243 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[1] 244 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[2] 245 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[3] 246 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[4] 247 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[5] 248 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[6] 249 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[7] 250 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[8] 251 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[9] 252 | set_location_assignment PIN_C10 -to SW[0] 253 | set_location_assignment PIN_C11 -to SW[1] 254 | set_location_assignment PIN_D12 -to SW[2] 255 | set_location_assignment PIN_C12 -to SW[3] 256 | set_location_assignment PIN_A12 -to SW[4] 257 | set_location_assignment PIN_B12 -to SW[5] 258 | set_location_assignment PIN_A13 -to SW[6] 259 | set_location_assignment PIN_A14 -to SW[7] 260 | set_location_assignment PIN_B14 -to SW[8] 261 | set_location_assignment PIN_F15 -to SW[9] 262 | 263 | #============================================================ 264 | # VGA 265 | #============================================================ 266 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[0] 267 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[1] 268 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[2] 269 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[3] 270 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[0] 271 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[1] 272 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[2] 273 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[3] 274 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_HS 275 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[0] 276 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[1] 277 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[2] 278 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[3] 279 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_VS 280 | set_location_assignment PIN_P1 -to VGA_B[0] 281 | set_location_assignment PIN_T1 -to VGA_B[1] 282 | set_location_assignment PIN_P4 -to VGA_B[2] 283 | set_location_assignment PIN_N2 -to VGA_B[3] 284 | set_location_assignment PIN_W1 -to VGA_G[0] 285 | set_location_assignment PIN_T2 -to VGA_G[1] 286 | set_location_assignment PIN_R2 -to VGA_G[2] 287 | set_location_assignment PIN_R1 -to VGA_G[3] 288 | set_location_assignment PIN_N3 -to VGA_HS 289 | set_location_assignment PIN_AA1 -to VGA_R[0] 290 | set_location_assignment PIN_V1 -to VGA_R[1] 291 | set_location_assignment PIN_Y2 -to VGA_R[2] 292 | set_location_assignment PIN_Y1 -to VGA_R[3] 293 | set_location_assignment PIN_N1 -to VGA_VS 294 | 295 | #============================================================ 296 | # Arduino 297 | #============================================================ 298 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[0] 299 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[1] 300 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[2] 301 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[3] 302 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[4] 303 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[5] 304 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[6] 305 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[7] 306 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[8] 307 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[9] 308 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[10] 309 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[11] 310 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[12] 311 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[13] 312 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[14] 313 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[15] 314 | set_instance_assignment -name IO_STANDARD "3.3 V Schmitt Trigger" -to ARDUINO_RESET_N 315 | set_location_assignment PIN_AB5 -to ARDUINO_IO[0] 316 | set_location_assignment PIN_AB6 -to ARDUINO_IO[1] 317 | set_location_assignment PIN_AB7 -to ARDUINO_IO[2] 318 | set_location_assignment PIN_AB8 -to ARDUINO_IO[3] 319 | set_location_assignment PIN_AB9 -to ARDUINO_IO[4] 320 | set_location_assignment PIN_Y10 -to ARDUINO_IO[5] 321 | set_location_assignment PIN_AA11 -to ARDUINO_IO[6] 322 | set_location_assignment PIN_AA12 -to ARDUINO_IO[7] 323 | set_location_assignment PIN_AB17 -to ARDUINO_IO[8] 324 | set_location_assignment PIN_AA17 -to ARDUINO_IO[9] 325 | set_location_assignment PIN_AB19 -to ARDUINO_IO[10] 326 | set_location_assignment PIN_AA19 -to ARDUINO_IO[11] 327 | set_location_assignment PIN_Y19 -to ARDUINO_IO[12] 328 | set_location_assignment PIN_AB20 -to ARDUINO_IO[13] 329 | set_location_assignment PIN_AB21 -to ARDUINO_IO[14] 330 | set_location_assignment PIN_AA20 -to ARDUINO_IO[15] 331 | set_location_assignment PIN_F16 -to ARDUINO_RESET_N 332 | 333 | #============================================================ 334 | # End of pin assignments by Terasic System Builder 335 | #============================================================ 336 | 337 | 338 | set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top 339 | set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top 340 | set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top 341 | set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 342 | set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 343 | set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" 344 | set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" 345 | set_global_assignment -name ENABLE_OCT_DONE OFF 346 | set_global_assignment -name EXTERNAL_FLASH_FALLBACK_ADDRESS 00000000 347 | set_global_assignment -name USE_CONFIGURATION_DEVICE OFF 348 | set_global_assignment -name INTERNAL_FLASH_UPDATE_MODE "SINGLE IMAGE WITH ERAM" 349 | set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF 350 | set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise 351 | set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall 352 | set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise 353 | set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall 354 | set_global_assignment -name SYSTEMVERILOG_FILE modules/packages/io.sv 355 | set_global_assignment -name SYSTEMVERILOG_FILE modules/packages/types.sv 356 | set_global_assignment -name SYSTEMVERILOG_FILE modules/cpu/datapath/byte_store_unit.sv 357 | set_global_assignment -name SYSTEMVERILOG_FILE modules/cpu/datapath/byte_load_unit.sv 358 | set_global_assignment -name SYSTEMVERILOG_FILE modules/cpu/control_unit/byte_half_decoder.sv 359 | set_global_assignment -name SYSTEMVERILOG_FILE modules/cpu/hazard_unit/hazard_unit.sv 360 | set_global_assignment -name SYSTEMVERILOG_FILE modules/cpu/hazard_unit/lw_fsm.sv 361 | set_global_assignment -name SYSTEMVERILOG_FILE peripherals/sevenseg.sv 362 | set_global_assignment -name SYSTEMVERILOG_FILE peripherals/clock_divider.sv 363 | set_global_assignment -name SYSTEMVERILOG_FILE modules/packages/signals.sv 364 | set_global_assignment -name SYSTEMVERILOG_FILE modules/cpu/control_unit/main_decoder.sv 365 | set_global_assignment -name SYSTEMVERILOG_FILE modules/cpu/control_unit/control_unit.sv 366 | set_global_assignment -name SYSTEMVERILOG_FILE modules/cpu/control_unit/control_m_w_register.sv 367 | set_global_assignment -name SYSTEMVERILOG_FILE modules/cpu/control_unit/control_e_m_register.sv 368 | set_global_assignment -name SYSTEMVERILOG_FILE modules/cpu/control_unit/control_d_e_register.sv 369 | set_global_assignment -name SYSTEMVERILOG_FILE modules/cpu/control_unit/alu_decoder.sv 370 | set_global_assignment -name SYSTEMVERILOG_FILE modules/cpu/datapath/register_file.sv 371 | set_global_assignment -name SYSTEMVERILOG_FILE modules/cpu/datapath/m_w_register.sv 372 | set_global_assignment -name SYSTEMVERILOG_FILE modules/cpu/datapath/iw_d_register.sv 373 | set_global_assignment -name SYSTEMVERILOG_FILE modules/memory/instruction_memory.sv 374 | set_global_assignment -name SYSTEMVERILOG_FILE modules/memory/gprmm_registers.sv 375 | set_global_assignment -name SYSTEMVERILOG_FILE modules/memory/data_memory.sv 376 | set_global_assignment -name SYSTEMVERILOG_FILE modules/cpu/datapath/imm_extender.sv 377 | set_global_assignment -name SYSTEMVERILOG_FILE modules/cpu/datapath/f_iw_register.sv 378 | set_global_assignment -name SYSTEMVERILOG_FILE modules/cpu/datapath/e_m_register.sv 379 | set_global_assignment -name SYSTEMVERILOG_FILE modules/cpu/datapath/datapath.sv 380 | set_global_assignment -name SYSTEMVERILOG_FILE modules/cpu/datapath/d_e_register.sv 381 | set_global_assignment -name SYSTEMVERILOG_FILE modules/cpu/datapath/alu.sv 382 | set_global_assignment -name SYSTEMVERILOG_FILE modules/cpu/cpu.sv 383 | set_global_assignment -name SYSTEMVERILOG_FILE modules/memory/memory_controller.sv 384 | set_global_assignment -name SYSTEMVERILOG_FILE modules/muxes/mux8.sv 385 | set_global_assignment -name SYSTEMVERILOG_FILE modules/muxes/mux4.sv 386 | set_global_assignment -name SYSTEMVERILOG_FILE modules/muxes/mux2.sv 387 | set_global_assignment -name SYSTEMVERILOG_FILE modules/sync/en_clr_arst_register.sv 388 | set_global_assignment -name SYSTEMVERILOG_FILE modules/dokifive_soc.sv 389 | set_global_assignment -name SDC_FILE dokifive_p50_top.SDC 390 | set_global_assignment -name SYSTEMVERILOG_FILE dokifive_p50_top.sv 391 | set_global_assignment -name QIP_FILE modules/memory/data_bram.qip 392 | set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top --------------------------------------------------------------------------------