This commit is contained in:
2025-11-18 00:55:46 +08:00
parent 464d19d647
commit aa1a73202c
18 changed files with 2051 additions and 0 deletions

View File

@@ -0,0 +1,70 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import chisel3.experimental.ChiselEnum
import chisel3.util._
import riscv.Parameters
object ALUFunctions extends ChiselEnum {
val zero, add, sub, sll, slt, xor, or, and, srl, sra, sltu = Value
}
class ALU extends Module {
val io = IO(new Bundle {
val func = Input(ALUFunctions())
val op1 = Input(UInt(Parameters.DataWidth))
val op2 = Input(UInt(Parameters.DataWidth))
val result = Output(UInt(Parameters.DataWidth))
})
io.result := 0.U
switch(io.func) {
is(ALUFunctions.add) {
io.result := io.op1 + io.op2
}
is(ALUFunctions.sub) {
io.result := io.op1 - io.op2
}
is(ALUFunctions.sll) {
io.result := io.op1 << io.op2(4, 0)
}
is(ALUFunctions.slt) {
io.result := io.op1.asSInt < io.op2.asSInt
}
is(ALUFunctions.xor) {
io.result := io.op1 ^ io.op2
}
is(ALUFunctions.or) {
io.result := io.op1 | io.op2
}
is(ALUFunctions.and) {
io.result := io.op1 & io.op2
}
is(ALUFunctions.srl) {
io.result := io.op1 >> io.op2(4, 0)
}
is(ALUFunctions.sra) {
io.result := (io.op1.asSInt >> io.op2(4, 0)).asUInt
}
is(ALUFunctions.sltu) {
io.result := io.op1 < io.op2
}
}
}

View File

@@ -0,0 +1,86 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import chisel3.util._
class ALUControl extends Module {
val io = IO(new Bundle {
val opcode = Input(UInt(7.W))
val funct3 = Input(UInt(3.W))
val funct7 = Input(UInt(7.W))
val alu_funct = Output(ALUFunctions())
})
io.alu_funct := ALUFunctions.zero
switch(io.opcode) {
is(InstructionTypes.I) {
io.alu_funct := MuxLookup(
io.funct3,
ALUFunctions.zero,
IndexedSeq(
InstructionsTypeI.addi -> ALUFunctions.add,
InstructionsTypeI.slli -> ALUFunctions.sll,
InstructionsTypeI.slti -> ALUFunctions.slt,
InstructionsTypeI.sltiu -> ALUFunctions.sltu,
InstructionsTypeI.xori -> ALUFunctions.xor,
InstructionsTypeI.ori -> ALUFunctions.or,
InstructionsTypeI.andi -> ALUFunctions.and,
InstructionsTypeI.sri -> Mux(io.funct7(5), ALUFunctions.sra, ALUFunctions.srl)
),
)
}
is(InstructionTypes.RM) {
io.alu_funct := MuxLookup(
io.funct3,
ALUFunctions.zero,
IndexedSeq(
InstructionsTypeR.add_sub -> Mux(io.funct7(5), ALUFunctions.sub, ALUFunctions.add),
InstructionsTypeR.sll -> ALUFunctions.sll,
InstructionsTypeR.slt -> ALUFunctions.slt,
InstructionsTypeR.sltu -> ALUFunctions.sltu,
InstructionsTypeR.xor -> ALUFunctions.xor,
InstructionsTypeR.or -> ALUFunctions.or,
InstructionsTypeR.and -> ALUFunctions.and,
InstructionsTypeR.sr -> Mux(io.funct7(5), ALUFunctions.sra, ALUFunctions.srl)
),
)
}
is(InstructionTypes.B) {
io.alu_funct := ALUFunctions.add
}
is(InstructionTypes.L) {
io.alu_funct := ALUFunctions.add
}
is(InstructionTypes.S) {
io.alu_funct := ALUFunctions.add
}
is(Instructions.jal) {
io.alu_funct := ALUFunctions.add
}
is(Instructions.jalr) {
io.alu_funct := ALUFunctions.add
}
is(Instructions.lui) {
io.alu_funct := ALUFunctions.add
}
is(Instructions.auipc) {
io.alu_funct := ALUFunctions.add
}
}
}

View File

@@ -0,0 +1,82 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import chisel3.util.Cat
import riscv.{CPUBundle, Parameters}
class CPU extends Module {
val io = IO(new CPUBundle)
val regs = Module(new RegisterFile)
val inst_fetch = Module(new InstructionFetch)
val id = Module(new InstructionDecode)
val ex = Module(new Execute)
val mem = Module(new MemoryAccess)
val wb = Module(new WriteBack)
io.deviceSelect := mem.io.memory_bundle.address(Parameters.AddrBits - 1, Parameters.AddrBits - Parameters.SlaveDeviceCountBits)
inst_fetch.io.jump_address_id := ex.io.if_jump_address
inst_fetch.io.jump_flag_id := ex.io.if_jump_flag
inst_fetch.io.instruction_valid := io.instruction_valid
inst_fetch.io.instruction_read_data := io.instruction
io.instruction_address := inst_fetch.io.instruction_address
regs.io.write_enable := id.io.reg_write_enable
regs.io.write_address := id.io.reg_write_address
regs.io.write_data := wb.io.regs_write_data
regs.io.read_address1 := id.io.regs_reg1_read_address
regs.io.read_address2 := id.io.regs_reg2_read_address
regs.io.debug_read_address := io.debug_read_address
io.debug_read_data := regs.io.debug_read_data
id.io.instruction := inst_fetch.io.instruction
// lab1(cpu)
ex.io.instruction := inst_fetch.io.instruction
ex.io.instruction_address := inst_fetch.io.instruction_address
ex.io.reg1_data := regs.io.read_data1
ex.io.reg2_data := regs.io.read_data2
ex.io.immediate := id.io.ex_immediate
ex.io.aluop1_source := id.io.ex_aluop1_source
ex.io.aluop2_source := id.io.ex_aluop2_source
// lab1(cpu) end
mem.io.alu_result := ex.io.mem_alu_result
mem.io.reg2_data := regs.io.read_data2
mem.io.memory_read_enable := id.io.memory_read_enable
mem.io.memory_write_enable := id.io.memory_write_enable
mem.io.funct3 := inst_fetch.io.instruction(14, 12)
io.memory_bundle.address := Cat(0.U(Parameters.SlaveDeviceCountBits.W),mem.io.memory_bundle.address(Parameters.AddrBits - 1 - Parameters.SlaveDeviceCountBits, 0))
io.memory_bundle.write_enable := mem.io.memory_bundle.write_enable
io.memory_bundle.write_data := mem.io.memory_bundle.write_data
io.memory_bundle.write_strobe := mem.io.memory_bundle.write_strobe
mem.io.memory_bundle.read_data := io.memory_bundle.read_data
wb.io.instruction_address := inst_fetch.io.instruction_address
wb.io.alu_result := ex.io.mem_alu_result
wb.io.memory_read_data := mem.io.wb_memory_read_data
wb.io.regs_write_source := id.io.wb_reg_write_source
}

View File

@@ -0,0 +1,81 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import chisel3.util.{Cat, MuxLookup}
import riscv.Parameters
class Execute extends Module {
val io = IO(new Bundle {
val instruction = Input(UInt(Parameters.InstructionWidth))
val instruction_address = Input(UInt(Parameters.AddrWidth))
val reg1_data = Input(UInt(Parameters.DataWidth))
val reg2_data = Input(UInt(Parameters.DataWidth))
val immediate = Input(UInt(Parameters.DataWidth))
val aluop1_source = Input(UInt(1.W))
val aluop2_source = Input(UInt(1.W))
val mem_alu_result = Output(UInt(Parameters.DataWidth))
val if_jump_flag = Output(Bool())
val if_jump_address = Output(UInt(Parameters.DataWidth))
})
val opcode = io.instruction(6, 0)
val funct3 = io.instruction(14, 12)
val funct7 = io.instruction(31, 25)
val rd = io.instruction(11, 7)
val uimm = io.instruction(19, 15)
val alu = Module(new ALU)
val alu_ctrl = Module(new ALUControl)
alu_ctrl.io.opcode := opcode
alu_ctrl.io.funct3 := funct3
alu_ctrl.io.funct7 := funct7
// lab1(Execute)
alu.io.func := alu_ctrl.io.alu_funct
alu.io.op1 := Mux(
io.aluop1_source === ALUOp1Source.Register,
io.reg1_data,
io.instruction_address
)
alu.io.op2 := Mux(
io.aluop2_source === ALUOp2Source.Register,
io.reg2_data,
io.immediate
)
// lab1(Execute) end
io.mem_alu_result := alu.io.result
io.if_jump_flag := opcode === Instructions.jal ||
(opcode === Instructions.jalr) ||
(opcode === InstructionTypes.B) && MuxLookup(
funct3,
false.B,
IndexedSeq(
InstructionsTypeB.beq -> (io.reg1_data === io.reg2_data),
InstructionsTypeB.bne -> (io.reg1_data =/= io.reg2_data),
InstructionsTypeB.blt -> (io.reg1_data.asSInt < io.reg2_data.asSInt),
InstructionsTypeB.bge -> (io.reg1_data.asSInt >= io.reg2_data.asSInt),
InstructionsTypeB.bltu -> (io.reg1_data.asUInt < io.reg2_data.asUInt),
InstructionsTypeB.bgeu -> (io.reg1_data.asUInt >= io.reg2_data.asUInt)
)
)
io.if_jump_address := io.immediate + Mux(opcode === Instructions.jalr, io.reg1_data, io.instruction_address)
}

View File

@@ -0,0 +1,205 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import chisel3.util._
import riscv.Parameters
object InstructionTypes {
val L = "b0000011".U
val I = "b0010011".U
val S = "b0100011".U
val RM = "b0110011".U
val B = "b1100011".U
}
object Instructions {
val lui = "b0110111".U
val nop = "b0000001".U
val jal = "b1101111".U
val jalr = "b1100111".U
val auipc = "b0010111".U
val csr = "b1110011".U
val fence = "b0001111".U
}
object InstructionsTypeL {
val lb = "b000".U
val lh = "b001".U
val lw = "b010".U
val lbu = "b100".U
val lhu = "b101".U
}
object InstructionsTypeI {
val addi = 0.U
val slli = 1.U
val slti = 2.U
val sltiu = 3.U
val xori = 4.U
val sri = 5.U
val ori = 6.U
val andi = 7.U
}
object InstructionsTypeS {
val sb = "b000".U
val sh = "b001".U
val sw = "b010".U
}
object InstructionsTypeR {
val add_sub = 0.U
val sll = 1.U
val slt = 2.U
val sltu = 3.U
val xor = 4.U
val sr = 5.U
val or = 6.U
val and = 7.U
}
object InstructionsTypeM {
val mul = 0.U
val mulh = 1.U
val mulhsu = 2.U
val mulhum = 3.U
val div = 4.U
val divu = 5.U
val rem = 6.U
val remu = 7.U
}
object InstructionsTypeB {
val beq = "b000".U
val bne = "b001".U
val blt = "b100".U
val bge = "b101".U
val bltu = "b110".U
val bgeu = "b111".U
}
object InstructionsTypeCSR {
val csrrw = "b001".U
val csrrs = "b010".U
val csrrc = "b011".U
val csrrwi = "b101".U
val csrrsi = "b110".U
val csrrci = "b111".U
}
object InstructionsNop {
val nop = 0x00000013L.U(Parameters.DataWidth)
}
object InstructionsRet {
val mret = 0x30200073L.U(Parameters.DataWidth)
val ret = 0x00008067L.U(Parameters.DataWidth)
}
object InstructionsEnv {
val ecall = 0x00000073L.U(Parameters.DataWidth)
val ebreak = 0x00100073L.U(Parameters.DataWidth)
}
object ALUOp1Source {
val Register = 0.U(1.W)
val InstructionAddress = 1.U(1.W)
}
object ALUOp2Source {
val Register = 0.U(1.W)
val Immediate = 1.U(1.W)
}
object RegWriteSource {
val ALUResult = 0.U(2.W)
val Memory = 1.U(2.W)
//val CSR = 2.U(2.W)
val NextInstructionAddress = 3.U(2.W)
}
class InstructionDecode extends Module {
val io = IO(new Bundle {
val instruction = Input(UInt(Parameters.InstructionWidth))
val regs_reg1_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val regs_reg2_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val ex_immediate = Output(UInt(Parameters.DataWidth))
val ex_aluop1_source = Output(UInt(1.W))
val ex_aluop2_source = Output(UInt(1.W))
val memory_read_enable = Output(Bool())
val memory_write_enable = Output(Bool())
val wb_reg_write_source = Output(UInt(2.W))
val reg_write_enable = Output(Bool())
val reg_write_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
})
val opcode = io.instruction(6, 0)
val funct3 = io.instruction(14, 12)
val funct7 = io.instruction(31, 25)
val rd = io.instruction(11, 7)
val rs1 = io.instruction(19, 15)
val rs2 = io.instruction(24, 20)
io.regs_reg1_read_address := Mux(opcode === Instructions.lui, 0.U(Parameters.PhysicalRegisterAddrWidth), rs1)
io.regs_reg2_read_address := rs2
val immediate = MuxLookup(
opcode,
Cat(Fill(20, io.instruction(31)), io.instruction(31, 20)),
IndexedSeq(
InstructionTypes.I -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
InstructionTypes.L -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
Instructions.jalr -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
InstructionTypes.S -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 25), io.instruction(11, 7)),
InstructionTypes.B -> Cat(Fill(20, io.instruction(31)), io.instruction(7), io.instruction(30, 25), io.instruction(11, 8), 0.U(1.W)),
Instructions.lui -> Cat(io.instruction(31, 12), 0.U(12.W)),
Instructions.auipc -> Cat(io.instruction(31, 12), 0.U(12.W)),
Instructions.jal -> Cat(Fill(12, io.instruction(31)), io.instruction(19, 12), io.instruction(20), io.instruction(30, 21), 0.U(1.W))
)
)
io.ex_immediate := immediate
io.ex_aluop1_source := Mux(
opcode === Instructions.auipc || opcode === InstructionTypes.B || opcode === Instructions.jal,
ALUOp1Source.InstructionAddress,
ALUOp1Source.Register
)
// lab1(InstructionDecode)
io.ex_aluop2_source := Mux(opcode === InstructionTypes.RM,
ALUOp2Source.Register,
ALUOp2Source.Immediate
)
// 仅当指令是 Load 类型时,才使能内存读。
io.memory_read_enable := opcode === InstructionTypes.L
// 仅当指令是 Store 类型时,才使能内存写。
io.memory_write_enable := opcode === InstructionTypes.S
// 根据指令类型,选择写回寄存器的数据来源。
io.wb_reg_write_source := MuxLookup(
opcode,
RegWriteSource.ALUResult // 默认来源是ALU计算结果
)( // 使用新的 MuxLookup 语法
IndexedSeq(
InstructionTypes.L -> RegWriteSource.Memory, // Load 指令来源是内存
Instructions.jal -> RegWriteSource.NextInstructionAddress, // jal/jalr 来源是下一条指令地址 (PC+4)
Instructions.jalr -> RegWriteSource.NextInstructionAddress
)
)
// lab1(InstructionDecode) end
io.reg_write_enable := (opcode === InstructionTypes.RM) || (opcode === InstructionTypes.I) ||
(opcode === InstructionTypes.L) || (opcode === Instructions.auipc) || (opcode === Instructions.lui) ||
(opcode === Instructions.jal) || (opcode === Instructions.jalr)
io.reg_write_address := io.instruction(11, 7)
}

View File

@@ -0,0 +1,55 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import riscv.Parameters
object ProgramCounter {
val EntryAddress = Parameters.EntryAddress
}
class InstructionFetch extends Module {
val io = IO(new Bundle {
val jump_flag_id = Input(Bool())
val jump_address_id = Input(UInt(Parameters.AddrWidth))
val instruction_read_data = Input(UInt(Parameters.DataWidth))
val instruction_valid = Input(Bool())
val instruction_address = Output(UInt(Parameters.AddrWidth))
val instruction = Output(UInt(Parameters.InstructionWidth))
})
val pc = RegInit(ProgramCounter.EntryAddress)
when(io.instruction_valid) {
io.instruction := io.instruction_read_data
// lab1(InstructionFetch)
when(io.jump_flag_id) {
pc := io.jump_address_id
}.otherwise {
pc := pc + 4.U
}
// la1(InstructionFetch) end
}.otherwise{
pc := pc
io.instruction := 0x00000013.U
}
io.instruction_address := pc
}

View File

@@ -0,0 +1,106 @@
// Copyright 2022 Canbin Huang
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import chisel3.util._
import peripheral.RAMBundle
import riscv.Parameters
class MemoryAccess extends Module {
val io = IO(new Bundle() {
val alu_result = Input(UInt(Parameters.DataWidth))
val reg2_data = Input(UInt(Parameters.DataWidth))
val memory_read_enable = Input(Bool())
val memory_write_enable = Input(Bool())
val funct3 = Input(UInt(3.W))
val wb_memory_read_data = Output(UInt(Parameters.DataWidth))
val memory_bundle = Flipped(new RAMBundle)
})
val mem_address_index = io.alu_result(log2Up(Parameters.WordSize) - 1, 0).asUInt
io.memory_bundle.write_enable := false.B
io.memory_bundle.write_data := 0.U
io.memory_bundle.address := io.alu_result
io.memory_bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
io.wb_memory_read_data := 0.U
when(io.memory_read_enable) {
val data = io.memory_bundle.read_data
io.wb_memory_read_data := MuxLookup(
io.funct3,
0.U,
IndexedSeq(
InstructionsTypeL.lb -> MuxLookup(
mem_address_index,
Cat(Fill(24, data(31)), data(31, 24)),
IndexedSeq(
0.U -> Cat(Fill(24, data(7)), data(7, 0)),
1.U -> Cat(Fill(24, data(15)), data(15, 8)),
2.U -> Cat(Fill(24, data(23)), data(23, 16))
)
),
InstructionsTypeL.lbu -> MuxLookup(
mem_address_index,
Cat(Fill(24, 0.U), data(31, 24)),
IndexedSeq(
0.U -> Cat(Fill(24, 0.U), data(7, 0)),
1.U -> Cat(Fill(24, 0.U), data(15, 8)),
2.U -> Cat(Fill(24, 0.U), data(23, 16))
)
),
InstructionsTypeL.lh -> Mux(
mem_address_index === 0.U,
Cat(Fill(16, data(15)), data(15, 0)),
Cat(Fill(16, data(31)), data(31, 16))
),
InstructionsTypeL.lhu -> Mux(
mem_address_index === 0.U,
Cat(Fill(16, 0.U), data(15, 0)),
Cat(Fill(16, 0.U), data(31, 16))
),
InstructionsTypeL.lw -> data
)
)
}.elsewhen(io.memory_write_enable) {
io.memory_bundle.write_data := io.reg2_data
io.memory_bundle.write_enable := true.B
io.memory_bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
when(io.funct3 === InstructionsTypeS.sb) {
io.memory_bundle.write_strobe(mem_address_index) := true.B
io.memory_bundle.write_data := io.reg2_data(Parameters.ByteBits, 0) << (mem_address_index << log2Up(Parameters.ByteBits).U)
}.elsewhen(io.funct3 === InstructionsTypeS.sh) {
when(mem_address_index === 0.U) {
for (i <- 0 until Parameters.WordSize / 2) {
io.memory_bundle.write_strobe(i) := true.B
}
io.memory_bundle.write_data := io.reg2_data(Parameters.WordSize / 2 * Parameters.ByteBits, 0)
}.otherwise {
for (i <- Parameters.WordSize / 2 until Parameters.WordSize) {
io.memory_bundle.write_strobe(i) := true.B
}
io.memory_bundle.write_data := io.reg2_data(Parameters.WordSize / 2 * Parameters.ByteBits, 0) << (Parameters
.WordSize / 2 * Parameters.ByteBits)
}
}.elsewhen(io.funct3 === InstructionsTypeS.sw) {
for (i <- 0 until Parameters.WordSize) {
io.memory_bundle.write_strobe(i) := true.B
}
}
}
}

View File

@@ -0,0 +1,70 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import riscv.Parameters
object Registers extends Enumeration {
type Register = Value
val zero,
ra, sp, gp, tp,
t0, t1, t2, fp,
s1,
a0, a1, a2, a3, a4, a5, a6, a7,
s2, s3, s4, s5, s6, s7, s8, s9, s10, s11,
t3, t4, t5, t6 = Value
}
class RegisterFile extends Module {
val io = IO(new Bundle {
val write_enable = Input(Bool())
val write_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val write_data = Input(UInt(Parameters.DataWidth))
val read_address1 = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val read_address2 = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val read_data1 = Output(UInt(Parameters.DataWidth))
val read_data2 = Output(UInt(Parameters.DataWidth))
val debug_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val debug_read_data = Output(UInt(Parameters.DataWidth))
})
val registers = RegInit(VecInit(Seq.fill(Parameters.PhysicalRegisters)(0.U(Parameters.DataWidth))))
when(!reset.asBool) {
when(io.write_enable && io.write_address =/= 0.U) {
registers(io.write_address) := io.write_data
}
}
io.read_data1 := Mux(
io.read_address1 === 0.U,
0.U,
registers(io.read_address1)
)
io.read_data2 := Mux(
io.read_address2 === 0.U,
0.U,
registers(io.read_address2)
)
io.debug_read_data := Mux(
io.debug_read_address === 0.U,
0.U,
registers(io.debug_read_address)
)
}

View File

@@ -0,0 +1,37 @@
// Copyright 2022 Canbin Huang
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import chisel3.util._
import riscv.Parameters
class WriteBack extends Module {
val io = IO(new Bundle() {
val instruction_address = Input(UInt(Parameters.AddrWidth))
val alu_result = Input(UInt(Parameters.DataWidth))
val memory_read_data = Input(UInt(Parameters.DataWidth))
val regs_write_source = Input(UInt(2.W))
val regs_write_data = Output(UInt(Parameters.DataWidth))
})
io.regs_write_data := MuxLookup(
io.regs_write_source,
io.alu_result,
IndexedSeq(
RegWriteSource.Memory -> io.memory_read_data,
RegWriteSource.NextInstructionAddress -> (io.instruction_address + 4.U)
)
)
}