├── .gitignore ├── sources_1 └── new │ ├── Adder.sv │ ├── IMemory.sv │ ├── imemfile.dat │ ├── FlopR.sv │ ├── RegisterFile.sv │ ├── IODriver.sv │ ├── SlowClock.sv │ ├── DMemory.sv │ ├── SevenSegmentTop.sv │ ├── Alu.sv │ ├── SevenSegment.sv │ ├── Decoder.sv │ ├── SevenSegmentCtrl.sv │ ├── AluDecoder.sv │ ├── RiscVTop.sv │ ├── RiscV.sv │ └── Datapath.sv ├── sim_1 └── new │ ├── decoder.tv │ ├── FlopR_TB.sv │ ├── aluDecoder.tv │ ├── Datapath_TB.sv │ ├── AluDecoder_TB.sv │ ├── RiscV_TB.sv │ └── Decoder_TB.sv ├── program └── ex1 │ ├── bram.ld │ └── testProgram.S ├── README.md └── constrs_1 └── new └── constraints.xdc /.gitignore: -------------------------------------------------------------------------------- 1 | utils_1/ -------------------------------------------------------------------------------- /sources_1/new/Adder.sv: -------------------------------------------------------------------------------- 1 | 2 | module Adder( 3 | input logic [31:0] a, b, 4 | output logic [31:0] y 5 | ); 6 | 7 | assign y = a + b; 8 | 9 | endmodule -------------------------------------------------------------------------------- /sim_1/new/decoder.tv: -------------------------------------------------------------------------------- 1 | 00000033_300 2 | 00000013_104 3 | 00000063_020 4 | 00000067_140 5 | 0000006F_180 6 | 00000017_108 7 | 00000037_110 8 | 00000003_102 9 | 00000023_001 -------------------------------------------------------------------------------- /sources_1/new/IMemory.sv: -------------------------------------------------------------------------------- 1 | 2 | module IMemory( 3 | input logic [8:0] a, 4 | output logic [31:0] rd 5 | ); 6 | 7 | logic [31:0] ROM[511:0]; 8 | 9 | initial 10 | $readmemh("imemfile.dat", ROM); 11 | 12 | assign rd = ROM[a]; 13 | 14 | endmodule 15 | -------------------------------------------------------------------------------- /sources_1/new/imemfile.dat: -------------------------------------------------------------------------------- 1 | 004001b7 20000113 00e00293 02502023 2 | 02002303 000303b3 00730463 000003b3 3 | 00731463 00239e13 0051a223 010000ef 4 | 03697f13 00000013 ffdff06f 00200f93 5 | 41fe0933 00008067 00001941 73697200 6 | 01007663 0000000f 33767205 70326932 7 | 00000030 00000000 00000000 00000000 8 | -------------------------------------------------------------------------------- /sources_1/new/FlopR.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module FlopR( 4 | input logic clk, reset, 5 | input logic [31:0] d, 6 | output logic [31:0] q); 7 | 8 | always_ff @(posedge clk) 9 | if (reset) 10 | q <= 32'b0; 11 | else 12 | q <= d; 13 | 14 | endmodule 15 | -------------------------------------------------------------------------------- /program/ex1/bram.ld: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | IMEM (RX) : ORIGIN = 0x00000000, LENGTH = 0x0800 /* 2 KB */ 4 | DMEM (RW) : ORIGIN = 0x00001000, LENGTH = 0x1000 /* 4 KB */ 5 | } 6 | 7 | SECTIONS 8 | { 9 | .text : 10 | { 11 | . = ALIGN(4); 12 | testProgram.o (.text) 13 | *(.text*) 14 | } >IMEM 15 | 16 | .data : 17 | { 18 | *(.data*) 19 | *(.rodata*) 20 | *(.bss*) 21 | } >DMEM 22 | } 23 | -------------------------------------------------------------------------------- /sources_1/new/RegisterFile.sv: -------------------------------------------------------------------------------- 1 | 2 | module RegisterFile( 3 | input logic clk, we3, 4 | input logic [4:0] ra1, ra2, wa3, 5 | input logic [31:0] wd3, 6 | output logic [31:0] rd1, rd2 7 | ); 8 | logic [31:0] rf[31:0]; 9 | 10 | always_ff @(posedge clk) 11 | if (we3) rf[wa3] <= wd3; 12 | 13 | assign rd1 = (ra1 != 5'b0) ? rf[ra1] : 32'b0; 14 | assign rd2 = (ra2 != 5'b0) ? rf[ra2] : 32'b0; 15 | 16 | endmodule 17 | -------------------------------------------------------------------------------- /sources_1/new/IODriver.sv: -------------------------------------------------------------------------------- 1 | 2 | module IODriver( 3 | input logic clk, reset, enable, 4 | input logic [31:0] addr, memWdata, 5 | output logic [4:0] leds 6 | ); 7 | localparam IO_LEDS_bit = 0; 8 | logic [29:0] wordAddr; 9 | 10 | always_ff @(posedge clk) 11 | if (reset) 12 | leds <= 5'b0; 13 | else if(enable & wordAddr[IO_LEDS_bit]) 14 | leds <= memWdata[4:0]; 15 | 16 | assign wordAddr = addr[31:2]; 17 | 18 | endmodule 19 | -------------------------------------------------------------------------------- /sources_1/new/SlowClock.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | // counts 1 second 4 | module SlowClock( 5 | input logic clk_in, 6 | input logic enable, 7 | output logic clk_out); 8 | 9 | logic [25:0] counter = 0; 10 | logic state = 0; 11 | 12 | always_ff @(posedge clk_in) begin 13 | counter <= counter + 1; 14 | if (counter == 50_000_000 - 1) 15 | begin 16 | counter <= 0; 17 | if (enable) state <= ~state; 18 | end 19 | end 20 | 21 | assign clk_out = state; 22 | 23 | endmodule 24 | -------------------------------------------------------------------------------- /sim_1/new/FlopR_TB.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module FlopR_TB; 4 | 5 | logic clk, reset; 6 | logic [31:0] d, q; 7 | 8 | FlopR dut(clk, reset, d, q); 9 | 10 | initial begin 11 | reset = 1; #15; 12 | reset = 0; #2; 13 | end 14 | 15 | always begin 16 | clk <= 1; #5; 17 | clk <= 0; #5; 18 | end 19 | 20 | always @(posedge clk) begin 21 | #1; d <= 32'b100; 22 | end 23 | 24 | always @(negedge clk) begin 25 | if (q == 32'b100) begin 26 | $finish; 27 | end 28 | end 29 | 30 | endmodule 31 | -------------------------------------------------------------------------------- /sources_1/new/DMemory.sv: -------------------------------------------------------------------------------- 1 | 2 | module DMemory( 3 | input logic clk, 4 | input logic [3:0] memWMask, 5 | input logic [31:0] a, wd, 6 | output logic [31:0] rd 7 | ); 8 | 9 | logic [31:0] RAM[1023:0]; 10 | 11 | always_ff @(posedge clk) begin 12 | if(memWMask[0]) RAM[a[11:2]][ 7:0 ] <= wd[ 7:0 ]; 13 | if(memWMask[1]) RAM[a[11:2]][15:8 ] <= wd[15:8 ]; 14 | if(memWMask[3]) RAM[a[11:2]][31:24] <= wd[31:24]; 15 | if(memWMask[2]) RAM[a[11:2]][23:16] <= wd[23:16]; 16 | end 17 | 18 | assign rd = RAM[a[11:2]]; // it is word aligned 19 | 20 | endmodule 21 | -------------------------------------------------------------------------------- /sim_1/new/aluDecoder.tv: -------------------------------------------------------------------------------- 1 | 000_0000000_0_0_0_0_0000_0 2 | 000_0100000_0_0_0_1_0000_0 3 | 000_0000000_1_0_1_0_0000_0 4 | 000_0100000_1_0_1_0_0001_0 5 | 000_0100000_1_0_0_1_0001_0 6 | 001_0000000_0_0_0_1_0010_1 7 | 010_0000000_0_0_1_0_0011_0 8 | 011_1111111_0_0_0_1_0100_0 9 | 100_0000000_0_0_1_0_0101_0 10 | 101_0100000_0_0_0_1_0110_1 11 | 101_1011111_0_0_0_1_0111_1 12 | 110_0000000_0_0_0_1_1000_0 13 | 111_0000000_0_0_1_0_1001_0 14 | 000_0000000_0_1_0_0_1010_0 15 | 001_0000000_0_1_0_0_1011_0 16 | 100_0000000_0_1_0_0_0011_0 17 | 101_0000000_0_1_0_0_1100_0 18 | 110_0000000_0_1_0_0_0100_0 19 | 111_0000000_0_1_0_0_1101_0 20 | 111_1111111_1_0_0_0_0000_0 -------------------------------------------------------------------------------- /sources_1/new/SevenSegmentTop.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module SevenSegmentTop( 4 | input logic clk, 5 | input logic [15:0] displayed_number, 6 | output logic [6:0] led_segment, 7 | output logic [3:0] anode_activate, 8 | output logic dp); 9 | 10 | logic [3:0] led_binary; 11 | logic [6:0] negSegments; 12 | 13 | SevenSegmentCtrl sevenSegmentCtrl( 14 | .clk(clk), 15 | .displayed_number(displayed_number), 16 | .anode_activate(anode_activate), 17 | .led_binary(led_binary) 18 | ); 19 | 20 | SevenSegment sevenSegment( 21 | .binary(led_binary), 22 | .segments(negSegments) 23 | ); 24 | 25 | assign dp = 1; 26 | assign led_segment = ~negSegments; 27 | 28 | endmodule 29 | -------------------------------------------------------------------------------- /program/ex1/testProgram.S: -------------------------------------------------------------------------------- 1 | # Test program 2 | 3 | .equ IO_BASE, 0x400000 4 | .equ IO_LEDS, 4 5 | 6 | .section .text 7 | 8 | .globl start 9 | 10 | start: 11 | li gp, IO_BASE 12 | li sp, 0x2000 13 | addi t0, zero, 0xE # t0 = 14 14 | sw t0, (0x20)(zero) # word 8 in memory 15 | lw t1, (0x20)(zero) 16 | add t2, t1, zero 17 | beq t1, t2, continue 18 | add t2, zero, zero # shouldn't happen 19 | 20 | continue: 21 | bne t1, t2, dont 22 | slli t3, t2, 0x2 # t3 = 56 23 | 24 | dont: 25 | sw t0, IO_LEDS(gp) 26 | jal sub2 # address pc + Jimm 27 | andi t5, s2, 0x36 # t5 = 54 & 54 28 | 29 | freeze: 30 | nop 31 | j freeze 32 | 33 | sub2: 34 | addi t6, zero, 0x2 # t6 = 2 35 | sub s2, t3, t6 # s2 = 56 - 2 36 | ret 37 | -------------------------------------------------------------------------------- /sources_1/new/Alu.sv: -------------------------------------------------------------------------------- 1 | 2 | module Alu( 3 | input logic [3:0] aluControl, 4 | input logic [31:0] op1, op2, 5 | output logic [31:0] aluOut, 6 | output logic isZero 7 | ); 8 | 9 | always_comb 10 | case (aluControl) 11 | 4'h0: aluOut <= op1 + op2; 12 | 4'h1: aluOut <= op1 - op2; 13 | 4'h2: aluOut <= op1 << op2; 14 | 4'h3: aluOut <= $signed(op1) < $signed(op2); 15 | 4'h4: aluOut <= op1 < op2; 16 | 4'h5: aluOut <= op1 ^ op2; 17 | 4'h6: aluOut <= $signed(op1) >>> op2; 18 | 4'h7: aluOut <= op1 >> op2; 19 | 4'h8: aluOut <= op1 | op2; 20 | 4'h9: aluOut <= op1 & op2; 21 | 4'ha: aluOut <= op1 == op2; 22 | 4'hb: aluOut <= op1 != op2; 23 | 4'hc: aluOut <= $signed(op1) >= $signed(op2); 24 | 4'hd: aluOut <= op1 >= op2; 25 | default: aluOut <= 31'b0; 26 | endcase 27 | 28 | assign isZero = ~|aluOut; 29 | 30 | endmodule 31 | -------------------------------------------------------------------------------- /sources_1/new/SevenSegment.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module SevenSegment( 4 | input logic [3:0] binary, 5 | output logic [6:0] segments); 6 | 7 | always_comb 8 | case(binary) 9 | // abc_defg 10 | 0: segments = 7'b111_1110; 11 | 1: segments = 7'b011_0000; 12 | 2: segments = 7'b110_1101; 13 | 3: segments = 7'b111_1001; 14 | 4: segments = 7'b011_0011; 15 | 5: segments = 7'b101_1011; 16 | 6: segments = 7'b101_1111; 17 | 7: segments = 7'b111_0000; 18 | 8: segments = 7'b111_1111; 19 | 9: segments = 7'b111_0011; 20 | 10: segments = 7'b111_0111; 21 | 11: segments = 7'b001_1111; 22 | 12: segments = 7'b100_1110; 23 | 13: segments = 7'b011_1101; 24 | 14: segments = 7'b100_1111; 25 | 15: segments = 7'b100_0111; 26 | default: segments = 7'bxxx_xxxx; 27 | endcase 28 | endmodule 29 | -------------------------------------------------------------------------------- /sources_1/new/Decoder.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module Decoder( 4 | input logic [31:0] instr, 5 | output logic isALUreg, regWrite, isJAL, isJALR, isBranch, isLUI, isAUIPC, isALUimm, 6 | output logic isLoad, isStore 7 | ); 8 | 9 | localparam len = 6; 10 | 11 | assign isALUreg = (instr[len:0] == 7'b0110011); // rd <- rs1 OP rs2 12 | assign isALUimm = (instr[len:0] == 7'b0010011); // rd <- rs1 OP Iimm 13 | assign isBranch = (instr[len:0] == 7'b1100011); // if(rs1 OP rs2) PC<-PC+Bimm 14 | assign isJALR = (instr[len:0] == 7'b1100111); // rd <- PC+4; PC<-rs1+Iimm 15 | assign isJAL = (instr[len:0] == 7'b1101111); // rd <- PC+4; PC<-PC+Jimm 16 | assign isAUIPC = (instr[len:0] == 7'b0010111); // rd <- PC + Uimm 17 | assign isLUI = (instr[len:0] == 7'b0110111); // rd <- Uimm 18 | assign isLoad = (instr[len:0] == 7'b0000011); // rd <- mem[rs1+Iimm] 19 | assign isStore = (instr[len:0] == 7'b0100011); // mem[rs1+Simm] <- rs2 20 | assign isSYSTEM = (instr[len:0] == 7'b1110011); // special 21 | 22 | assign regWrite = isALUreg || isALUimm || isLoad || isLUI || isAUIPC || isJAL || isJALR; 23 | 24 | endmodule 25 | -------------------------------------------------------------------------------- /sim_1/new/Datapath_TB.sv: -------------------------------------------------------------------------------- 1 | 2 | module Datapath_TB; 3 | 4 | logic clk, reset, 5 | memtoreg, isALUreg, regWrite, 6 | isJAL, isJALR, isBranch, isLUI, 7 | isAUIPC, isLoad, isStore, isShamt; 8 | 9 | logic [2:0] funct3; 10 | logic [3:0] aluControl; 11 | logic [31:0] instr, memRdata; 12 | logic [31:0] pc, aluOut, memWdata, aluIn1, aluIn2; 13 | logic [3:0] memWMask; 14 | logic isZero; 15 | 16 | logic [31:0] counter; 17 | 18 | Datapath dut(clk, reset, 19 | isALUreg, regWrite, isJAL, 20 | isJALR, isBranch, isLUI, isAUIPC, 21 | isLoad, isStore, isShamt, 22 | funct3, aluControl, instr, memRdata, 23 | pc, aluOut, memWdata, aluIn1, aluIn2, memWMask, isZero); 24 | 25 | initial begin 26 | counter = 0; 27 | reset = 1; #15; 28 | reset = 0; #2; 29 | end 30 | 31 | always begin 32 | clk <= 1; #5; 33 | clk <= 0; #5; 34 | end 35 | 36 | always @(posedge clk) begin 37 | #1; counter = counter + 1; 38 | end 39 | 40 | always @(negedge clk) begin 41 | if (counter == 4'h5) begin 42 | $finish; 43 | end 44 | end 45 | 46 | endmodule 47 | -------------------------------------------------------------------------------- /sources_1/new/SevenSegmentCtrl.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module SevenSegmentCtrl( 4 | input logic clk, 5 | input logic [15:0] displayed_number, 6 | output logic [3:0] anode_activate, 7 | output logic [3:0] led_binary 8 | ); 9 | logic [19:0] refresh_counter; 10 | logic [1:0] led_activating_counter; 11 | 12 | always_ff @(posedge clk) 13 | refresh_counter <= refresh_counter + 1; 14 | 15 | assign led_activating_counter = refresh_counter[19:18]; 16 | 17 | always_comb 18 | case (led_activating_counter) 19 | 2'b00: begin 20 | anode_activate <= 4'b0111; 21 | led_binary <= displayed_number[15:12]; 22 | end 23 | 2'b01: begin 24 | anode_activate <= 4'b1011; 25 | led_binary <= displayed_number[11:8]; 26 | end 27 | 2'b10: begin 28 | anode_activate <= 4'b1101; 29 | led_binary <= displayed_number[7:4]; 30 | end 31 | 2'b11: begin 32 | anode_activate <= 4'b1110; 33 | led_binary <= displayed_number[3:0]; 34 | end 35 | endcase 36 | 37 | endmodule 38 | -------------------------------------------------------------------------------- /sources_1/new/AluDecoder.sv: -------------------------------------------------------------------------------- 1 | 2 | module AluDecoder( 3 | input logic [2:0] funct3, 4 | input logic [6:0] funct7, 5 | input logic instr_5, isBranch, isALUreg, isALUimm, 6 | output logic [3:0] aluControl, 7 | output logic isShamt 8 | ); 9 | 10 | always_comb begin 11 | case({isBranch, isALUreg || isALUimm, funct3}) 12 | 5'b01000: aluControl <= (funct7[5] & instr_5) ? (4'h1) : (4'h0); 13 | 5'b01001: aluControl <= 4'h2; 14 | 5'b01010: aluControl <= 4'h3; 15 | 5'b01011: aluControl <= 4'h4; 16 | 5'b01100: aluControl <= 4'h5; 17 | 5'b01101: aluControl <= funct7[5]? 4'h6 : 4'h7; 18 | 5'b01110: aluControl <= 4'h8; 19 | 5'b01111: aluControl <= 4'h9; 20 | 5'b10000: aluControl <= 4'ha; 21 | 5'b10001: aluControl <= 4'hb; 22 | 5'b10100: aluControl <= 4'h3; 23 | 5'b10101: aluControl <= 4'hc; 24 | 5'b10110: aluControl <= 4'h4; 25 | 5'b10111: aluControl <= 4'hd; 26 | default: aluControl <= 4'h0; // adder by default 27 | endcase 28 | case({isALUreg || isALUimm, funct3}) 29 | 4'b1001, 4'b1101: isShamt <= 1'b1; 30 | default: isShamt <= 1'b0; 31 | endcase 32 | end 33 | endmodule 34 | -------------------------------------------------------------------------------- /sources_1/new/RiscVTop.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module RiscVTop( 4 | input logic clk, reset, clkEnable, 5 | output logic [6:0] led_segment, 6 | output logic [3:0] anode_activate, 7 | output logic [4:0] leds, 8 | output logic slow_clk, dp 9 | ); 10 | 11 | logic [31:0] pc, instr, memWdata, addr, aluIn1, aluIn2, Simm, Jimm, Bimm, Iimm, memRdata; 12 | logic [4:0] rs1Id, rs2Id, rdId; 13 | logic [3:0] memWMask, aluControl; 14 | logic isALUreg, 15 | regWrite, 16 | isJAL, 17 | isJALR, 18 | isBranch, 19 | isLUI, 20 | isAUIPC, 21 | isALUimm, 22 | isLoad, 23 | isStore, 24 | isShamt; 25 | 26 | logic [15:0] displayed_number; 27 | 28 | SlowClock slowClock(clk, clkEnable, slow_clk); 29 | 30 | SevenSegmentTop sevenSegmentTop( 31 | .clk(clk), 32 | .displayed_number(displayed_number), 33 | .led_segment(led_segment), 34 | .anode_activate(anode_activate), 35 | .dp(dp)); 36 | 37 | RiscV riscv(slow_clk, reset, pc, instr, memWdata, addr, aluIn1, aluIn2, Simm, Jimm, Bimm, Iimm, memRdata, rs1Id, rs2Id, rdId, memWMask, aluControl, 38 | isALUreg, 39 | regWrite, 40 | isJAL, 41 | isJALR, 42 | isBranch, 43 | isLUI, 44 | isAUIPC, 45 | isALUimm, 46 | isLoad, 47 | isStore, 48 | isShamt, 49 | leds 50 | ); 51 | 52 | assign displayed_number = addr[15:0]; 53 | 54 | endmodule 55 | -------------------------------------------------------------------------------- /sim_1/new/AluDecoder_TB.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module AluDecoder_TB; 4 | 5 | logic clk; 6 | logic [2:0] funct3; 7 | logic [6:0] funct7; 8 | logic instr_5, isBranch, isALUreg, isALUimm; 9 | logic [3:0] aluControl, aluControlT; 10 | logic isShamt, isShamtT; 11 | 12 | logic [18:0] testvectors [1000:0]; 13 | logic [31:0] vectornum, errors; 14 | 15 | AluDecoder dut( 16 | funct3, funct7, instr_5, isBranch, isALUreg, 17 | isALUimm, aluControl, isShamt 18 | ); 19 | 20 | initial begin 21 | $readmemb("aluDecoder.tv", testvectors); 22 | vectornum = 0; errors = 0; 23 | #2; 24 | end 25 | 26 | always begin 27 | clk <= 1; #5; 28 | clk <= 0; #5; 29 | end 30 | 31 | always @(posedge clk) begin 32 | #1; {funct3, funct7, instr_5, isBranch, isALUreg, 33 | isALUimm, aluControlT, isShamtT} = testvectors[vectornum]; 34 | end 35 | 36 | always @(negedge clk) 37 | begin 38 | if ({aluControl, isShamt} !== {aluControlT, isShamtT}) begin 39 | $display("Error: output = %b (%b expected)", {aluControl, isShamt}, {aluControlT, isShamtT}); 40 | $display("vectornum %b", vectornum); 41 | errors = errors + 1; 42 | end 43 | vectornum = vectornum + 1; 44 | if (testvectors[vectornum] === 'x) begin 45 | $display("%d tests completed with %d errors", vectornum, errors); 46 | $finish; 47 | end 48 | end 49 | 50 | endmodule 51 | -------------------------------------------------------------------------------- /sim_1/new/RiscV_TB.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module RiscV_TB; 4 | 5 | logic clk, reset; 6 | logic [1:0] flag; 7 | logic [31:0] instr, memWdata, addr, pc, aluIn1, aluIn2, Simm, Jimm, Bimm, Iimm, memRdata; 8 | logic [4:0] rs1Id, rs2Id, rdId, leds; 9 | logic [3:0] memWMask, aluControl; 10 | logic isALUreg, 11 | regWrite, 12 | isJAL, 13 | isJALR, 14 | isBranch, 15 | isLUI, 16 | isAUIPC, 17 | isALUimm, 18 | isLoad, 19 | isStore, 20 | isShamt; 21 | 22 | RiscV dut( 23 | clk, reset, 24 | pc, instr, memWdata, addr, 25 | aluIn1, 26 | aluIn2, 27 | Simm, 28 | Jimm, 29 | Bimm, 30 | Iimm, 31 | memRdata, 32 | rs1Id, rs2Id, rdId, 33 | memWMask, 34 | aluControl, 35 | isALUreg, 36 | regWrite, 37 | isJAL, 38 | isJALR, 39 | isBranch, 40 | isLUI, 41 | isAUIPC, 42 | isALUimm, 43 | isLoad, 44 | isStore, 45 | isShamt, 46 | leds 47 | ); 48 | 49 | initial begin 50 | flag = 0; 51 | reset = 1; #15; 52 | reset = 0; #2; 53 | end 54 | 55 | always begin 56 | clk <= 1; #5; 57 | clk <= 0; #5; 58 | end 59 | 60 | always @(negedge clk) begin 61 | if (pc == 8'h2c && leds == 5'he) 62 | flag = 1; 63 | if (rdId == 8'h1e && addr == 8'h36 && flag) 64 | flag = flag + 1; 65 | if (rdId == 8'h0 && flag == 2'b10) 66 | $finish; 67 | end 68 | 69 | endmodule 70 | -------------------------------------------------------------------------------- /sim_1/new/Decoder_TB.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module Decoder_TB; 4 | 5 | logic clk; 6 | logic [1:0] notUsed; 7 | logic [31:0] instr; 8 | logic isALUreg, regWrite, isJAL, 9 | isJALR, isBranch, isLUI, 10 | isAUIPC, isALUimm, isLoad, isStore; 11 | 12 | logic isALUregT, regWriteT, isJALT, 13 | isJALRT, isBranchT, isLUIT, 14 | isAUIPCT, isALUimmT, isLoadT, isStoreT; 15 | 16 | logic [43:0] testvectors [1000:0]; 17 | logic [31:0] vectornum, errors; 18 | 19 | Decoder dut( 20 | instr, 21 | isALUreg, regWrite, isJAL, 22 | isJALR, isBranch, isLUI, 23 | isAUIPC, isALUimm, isLoad, 24 | isStore 25 | ); 26 | 27 | initial begin 28 | $readmemh("decoder.tv", testvectors); 29 | vectornum = 0; errors = 0; 30 | #2; 31 | end 32 | 33 | always begin 34 | clk <= 1; #5; 35 | clk <= 0; #5; 36 | end 37 | 38 | always @(posedge clk) begin 39 | #1; {instr, notUsed, isALUregT, regWriteT, isJALT, 40 | isJALRT, isBranchT, isLUIT, 41 | isAUIPCT, isALUimmT, isLoadT, isStoreT} = testvectors[vectornum]; 42 | end 43 | 44 | always @(negedge clk) 45 | begin 46 | if ({isALUreg, regWrite, isJAL, 47 | isJALR, isBranch, isLUI, 48 | isAUIPC, isALUimm, isLoad, isStore} !== 49 | {isALUregT, regWriteT, isJALT, 50 | isJALRT, isBranchT, isLUIT, 51 | isAUIPCT, isALUimmT, isLoadT, isStoreT}) begin 52 | $display("Error: output = %b (%b expected)", 53 | {isALUreg, regWrite, isJAL, 54 | isJALR, isBranch, isLUI, 55 | isAUIPC, isALUimm, isLoad, isStore}, 56 | {isALUregT, regWriteT, isJALT, 57 | isJALRT, isBranchT, isLUIT, 58 | isAUIPCT, isALUimmT, isLoadT, isStoreT}); 59 | $display("vectornum %b", vectornum); 60 | errors = errors + 1; 61 | end 62 | vectornum = vectornum + 1; 63 | if (testvectors[vectornum] === 'x) begin 64 | $display("%d tests completed with %d errors", vectornum, errors); 65 | $finish; 66 | end 67 | end 68 | 69 | endmodule 70 | -------------------------------------------------------------------------------- /sources_1/new/RiscV.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module RiscV( 4 | input logic clk, reset, 5 | output logic [31:0] pc, instr, memWdata, addr, aluIn1, aluIn2, Simm, Jimm, Bimm, Iimm, memRdata, 6 | output logic [4:0] rs1Id, rs2Id, rdId, 7 | output logic [3:0] memWMask, aluControl, 8 | output logic isALUreg, 9 | regWrite, 10 | isJAL, 11 | isJALR, 12 | isBranch, 13 | isLUI, 14 | isAUIPC, 15 | isALUimm, 16 | isLoad, 17 | isStore, 18 | isShamt, 19 | output logic [4:0] leds 20 | ); 21 | 22 | logic isALUreg, regWrite, isZero, isIO, isRAM; 23 | 24 | logic [2:0] funct3; 25 | logic [6:0] funct7; 26 | 27 | Decoder decoder( 28 | instr, 29 | isALUreg, 30 | regWrite, 31 | isJAL, 32 | isJALR, 33 | isBranch, 34 | isLUI, 35 | isAUIPC, 36 | isALUimm, 37 | isLoad, 38 | isStore 39 | ); 40 | 41 | AluDecoder aluD( 42 | funct3, 43 | funct7, 44 | instr[5], 45 | isBranch, 46 | isALUreg, 47 | isALUimm, 48 | aluControl, 49 | isShamt 50 | ); 51 | 52 | Datapath dpath( 53 | clk, 54 | reset, 55 | isALUreg, 56 | regWrite, 57 | isJAL, 58 | isJALR, 59 | isBranch, 60 | isLUI, 61 | isAUIPC, 62 | isLoad, 63 | isStore, 64 | isShamt, 65 | funct3, 66 | aluControl, 67 | instr, 68 | memRdata, 69 | pc, 70 | addr, 71 | memWdata, 72 | aluIn1, 73 | aluIn2, 74 | Simm, 75 | Jimm, 76 | Bimm, Iimm, 77 | rs1Id, rs2Id, rdId, 78 | memWMask, 79 | isZero 80 | ); 81 | 82 | IMemory imem(pc[10:2], instr); 83 | DMemory dmem( 84 | clk, 85 | {{4{isStore & isRAM}} & memWMask}, 86 | addr, 87 | memWdata, 88 | memRdata 89 | ); 90 | 91 | IODriver io(clk, reset, {isStore & isIO}, addr, memWdata, leds); 92 | 93 | assign funct3 = instr[14:12]; 94 | assign funct7 = instr[31:25]; 95 | 96 | assign isIO = addr[22]; 97 | assign isRAM = !isIO; 98 | 99 | endmodule 100 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RISC-V Single Cycle RV32I core 2 | 3 | This is a Single Cycle processor running the RV32I implementation, hence a 32-bits cpu, written in __SystemVerilog__. It was made for learning purpouses, it's not intended for production. 4 | 5 | ## Thanks to 6 | 7 | @BrunoLevy and his amazing tutorial [From Blinker to RiscV](https://github.com/BrunoLevy/learn-fpga/blob/master/FemtoRV/TUTORIALS/FROM_BLINKER_TO_RISCV/README.md). 8 | 9 | Although that design is very different from the one made in this repo (that tutorial uses a monolithic approach to build the RiscV cpu, whereas I use modular approach), I reused a lot of concepts and code from that tutorial, including the _Memory mapped devices_ idea and the GNU toolchain makefiles. 10 | 11 | ## RISC-V reference 12 | 13 | I recommend 100% to read the [RISC-V Reference Manual](https://github.com/riscv/riscv-isa-manual/releases/download/Ratified-IMAFDQC/riscv-spec-20191213.pdf), maybe not complete but those sections mentioning the RV32I implementation. 14 | 15 | ## Architecture 16 | 17 | The architecture was heavily inspired in the 32-bits [Single Cycle MIPS processor](https://media.cheggcdn.com/media/b82/b820d7ac-b4c9-4dd7-af10-e3b3fbe250ff/phpPVaajI) explained in [Digital Design and Computer Architecture book](https://www.amazon.com/Digital-Design-Computer-Architecture-Harris/dp/0123944244/ref=pd_lpo_1?pd_rd_w=SEXjq&content-id=amzn1.sym.116f529c-aa4d-4763-b2b6-4d614ec7dc00&pf_rd_p=116f529c-aa4d-4763-b2b6-4d614ec7dc00&pf_rd_r=82ZAPW9VP21TKQM08AAT&pd_rd_wg=9EFiQ&pd_rd_r=75b9df90-d341-4fb2-b6dd-8ef3d3fa4219&pd_rd_i=0123944244&psc=1). Note that instruction and data are stored in separate memories. 18 | 19 | ## FPGA Board 20 | 21 | Any board should be compatible that has enough LUT's. 22 | This is running on the __Digilent Basys 3__ board and uses 23 | a little bit less than 1,000 LUT's without considering the slow clock circuit. 24 | 25 | ## Top module and RiscV module 26 | 27 | The top module is _RiscVTop.sv_, which includes the wiring to the slow clock, the 7-segments displays and some leds. The cpu itself is the _RiscV.sv_ module which also includes the Instruction Memory and the Data Memory. 28 | 29 | ## Programming using the GNU Toolchain 30 | 31 | I documented the steps in [this repository](https://github.com/martinKindall/compile-for-risc-v-gnu). 32 | 33 | ## Running BASIC 34 | 35 | Check out this branch https://github.com/martinKindall/risc-v-single-cycle/tree/tiny_basic_plus 36 | 37 | I added VGA and Keyboard controller to emulate a BASIC Terminal, based on the code of this repository: 38 | 39 | https://github.com/martinKindall/TinyBasicPlus 40 | -------------------------------------------------------------------------------- /constrs_1/new/constraints.xdc: -------------------------------------------------------------------------------- 1 | set_property PACKAGE_PIN V15 [get_ports clkEnable] 2 | set_property IOSTANDARD LVCMOS33 [get_ports clkEnable] 3 | 4 | set_property PACKAGE_PIN W16 [get_ports reset] 5 | set_property IOSTANDARD LVCMOS33 [get_ports reset] 6 | 7 | # clock 8 | 9 | set_property PACKAGE_PIN W5 [get_ports clk] 10 | set_property IOSTANDARD LVCMOS33 [get_ports clk] 11 | 12 | #segments 13 | 14 | set_property PACKAGE_PIN U2 [get_ports {anode_activate[0]}] 15 | set_property IOSTANDARD LVCMOS33 [get_ports {anode_activate[0]}] 16 | 17 | set_property PACKAGE_PIN U4 [get_ports {anode_activate[1]}] 18 | set_property IOSTANDARD LVCMOS33 [get_ports {anode_activate[1]}] 19 | 20 | set_property PACKAGE_PIN V4 [get_ports {anode_activate[2]}] 21 | set_property IOSTANDARD LVCMOS33 [get_ports {anode_activate[2]}] 22 | 23 | set_property PACKAGE_PIN W4 [get_ports {anode_activate[3]}] 24 | set_property IOSTANDARD LVCMOS33 [get_ports {anode_activate[3]}] 25 | 26 | set_property PACKAGE_PIN W7 [get_ports {led_segment[6]}] 27 | set_property IOSTANDARD LVCMOS33 [get_ports {led_segment[6]}] 28 | 29 | set_property PACKAGE_PIN W6 [get_ports {led_segment[5]}] 30 | set_property IOSTANDARD LVCMOS33 [get_ports {led_segment[5]}] 31 | 32 | set_property PACKAGE_PIN U8 [get_ports {led_segment[4]}] 33 | set_property IOSTANDARD LVCMOS33 [get_ports {led_segment[4]}] 34 | 35 | set_property PACKAGE_PIN V8 [get_ports {led_segment[3]}] 36 | set_property IOSTANDARD LVCMOS33 [get_ports {led_segment[3]}] 37 | 38 | set_property PACKAGE_PIN U5 [get_ports {led_segment[2]}] 39 | set_property IOSTANDARD LVCMOS33 [get_ports {led_segment[2]}] 40 | 41 | set_property PACKAGE_PIN V5 [get_ports {led_segment[1]}] 42 | set_property IOSTANDARD LVCMOS33 [get_ports {led_segment[1]}] 43 | 44 | set_property PACKAGE_PIN U7 [get_ports {led_segment[0]}] 45 | set_property IOSTANDARD LVCMOS33 [get_ports {led_segment[0]}] 46 | 47 | set_property PACKAGE_PIN V7 [get_ports dp] 48 | set_property IOSTANDARD LVCMOS33 [get_ports dp] 49 | 50 | # leds 51 | 52 | set_property PACKAGE_PIN U19 [get_ports slow_clk] 53 | set_property IOSTANDARD LVCMOS33 [get_ports slow_clk] 54 | 55 | 56 | set_property PACKAGE_PIN U3 [get_ports {leds[0]}] 57 | set_property IOSTANDARD LVCMOS33 [get_ports {leds[0]}] 58 | 59 | set_property PACKAGE_PIN P3 [get_ports {leds[1]}] 60 | set_property IOSTANDARD LVCMOS33 [get_ports {leds[1]}] 61 | 62 | set_property PACKAGE_PIN N3 [get_ports {leds[2]}] 63 | set_property IOSTANDARD LVCMOS33 [get_ports {leds[2]}] 64 | 65 | set_property PACKAGE_PIN P1 [get_ports {leds[3]}] 66 | set_property IOSTANDARD LVCMOS33 [get_ports {leds[3]}] 67 | 68 | set_property PACKAGE_PIN L1 [get_ports {leds[4]}] 69 | set_property IOSTANDARD LVCMOS33 [get_ports {leds[4]}] -------------------------------------------------------------------------------- /sources_1/new/Datapath.sv: -------------------------------------------------------------------------------- 1 | 2 | module Datapath( 3 | input logic clk, reset, 4 | input logic isALUreg, regWrite, isJAL, isJALR, isBranch, isLUI, isAUIPC, isLoad, isStore, isShamt, 5 | input logic [2:0] funct3, 6 | input logic [3:0] aluControl, 7 | input logic [31:0] instr, memRdata, 8 | output logic [31:0] pc, aluOut, memWdata, aluIn1, aluIn2, Simm, Jimm, Bimm, Iimm, 9 | output logic [4:0] rs1Id, rs2Id, rdId, 10 | output logic [3:0] memWMask, 11 | output logic isZero 12 | ); 13 | logic [1:0] memByteAccess, memHalfwordAccess; 14 | logic [7:0] loadByte; 15 | logic [15:0] loadHalfword; 16 | logic [31:0] pcNext, pcplus4, pcplusImm, aluIn2Pre, rd2, wd3, loadData; 17 | 18 | logic [31:0] Uimm; 19 | logic [4:0] shamt; 20 | logic loadSign; 21 | 22 | FlopR pcreg(clk, reset, pcNext, pc); 23 | Adder pcadd1(pc, 32'b100, pcplus4); 24 | 25 | RegisterFile regF(clk, regWrite, rs1Id, rs2Id, rdId, wd3, aluIn1, rd2); 26 | 27 | Alu alu(aluControl, aluIn1, aluIn2, aluOut, isZero); 28 | 29 | assign memByteAccess = funct3[1:0] == 2'b00; 30 | assign memHalfwordAccess = funct3[1:0] == 2'b01; 31 | 32 | assign loadHalfword = 33 | aluOut[1] ? memRdata[31:16] : memRdata[15:0]; 34 | 35 | assign loadByte = 36 | aluOut[0] ? loadHalfword[15:8] : loadHalfword[7:0]; 37 | 38 | assign loadData = memByteAccess ? {{24{loadSign}}, loadByte} : 39 | memHalfwordAccess ? {{16{loadSign}}, loadHalfword} : 40 | memRdata; 41 | 42 | assign memWdata[ 7: 0] = rd2[7:0]; 43 | assign memWdata[15: 8] = aluOut[0] ? rd2[7:0] : rd2[15: 8]; 44 | assign memWdata[23:16] = aluOut[1] ? rd2[7:0] : rd2[23:16]; 45 | assign memWdata[31:24] = aluOut[0] ? rd2[7:0] : 46 | aluOut[1] ? rd2[15:8] : rd2[31:24]; 47 | 48 | assign memWMask = memByteAccess ? 49 | (aluOut[1] ? 50 | (aluOut[0] ? 4'b1000 : 4'b0100) : 51 | (aluOut[0] ? 4'b0010 : 4'b0001) 52 | ) : 53 | memHalfwordAccess ? 54 | (aluOut[1] ? 4'b1100 : 4'b0011) : 55 | 4'b1111; 56 | 57 | assign pcplusImm = pc + (instr[3] ? Jimm[31:0] : 58 | instr[4] ? Uimm[31:0] : 59 | Bimm[31:0]); 60 | 61 | assign aluIn2Pre = (isALUreg | isBranch) ? rd2 : 62 | isStore ? Simm : 63 | Iimm; 64 | assign aluIn2 = isShamt ? {{27{0}}, shamt} : aluIn2Pre; 65 | 66 | assign pcNext = (isBranch && !isZero || isJAL) ? pcplusImm : 67 | isJALR ? {aluOut[31:1],1'b0}: 68 | pcplus4; 69 | 70 | assign wd3 = (isJAL || isJALR) ? pcplus4 : 71 | isLUI ? Uimm : 72 | isAUIPC ? pcplusImm : 73 | isLoad ? loadData : 74 | aluOut; 75 | 76 | assign rs1Id = instr[19:15]; 77 | assign rs2Id = instr[24:20]; 78 | assign rdId = instr[11:7]; 79 | 80 | assign Uimm = { instr[31], instr[30:12], {12{1'b0}}}; 81 | assign Iimm = {{21{instr[31]}}, instr[30:20]}; 82 | assign Simm = {{21{instr[31]}}, instr[30:25],instr[11:7]}; 83 | assign Bimm = {{20{instr[31]}}, instr[7],instr[30:25],instr[11:8],1'b0}; 84 | assign Jimm = {{12{instr[31]}}, instr[19:12],instr[20],instr[30:21],1'b0}; 85 | 86 | assign shamt = isALUreg ? rd2[4:0] : instr[24:20]; 87 | assign loadSign = !funct3[2] & (memByteAccess ? loadByte[7] : loadHalfword[15]); 88 | 89 | endmodule 90 | --------------------------------------------------------------------------------