├── 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
--------------------------------------------------------------------------------