• 【计算机组成与设计】Chisel取指和指令译码设计


    本次试验分为三个部分:

    目录

    设计译码电路

    设计寄存器文件

    实现一个32个字的指令存储器


    设计译码电路

    输入位32bit的一个机器字,按照课本MIPS 指令格式,完成add、sub、lw、sw指令译码,其他指令一律译码成nop指令。输入信号名为Instr_word,对上述四条指令义译码输出信号名为add_op、sub_op、lw_op和sw_op,其余指令一律译码为nop;

    给出Chisel设计代码和仿真测试波形,观察输入Instr_word为add R1,R2,R3; sub R0,R5,R6,lw R5,100(R2), sw R5,104(R2)、JAL RA,100(R2)时,对应的输出波形

    Decode.scala

    1. import chisel3._
    2. class Decoder extends Module {
    3. val io = IO(new Bundle {
    4. val Instr_word = Input(UInt(32.W))
    5. val add_op = Output(Bool())
    6. val sub_op = Output(Bool())
    7. val lw_op = Output(Bool())
    8. val sw_op = Output(Bool())
    9. val nop_op = Output(Bool())
    10. })
    11. // 定义操作码
    12. val OPCODE_ADD = "b000000".U
    13. val OPCODE_SUB = "b000000".U
    14. val OPCODE_LW = "b100011".U
    15. val OPCODE_SW = "b101011".U
    16. //定义功能码
    17. val FUNCT_ADD = "b100000".U
    18. val FUNCT_SUB = "b100010".U
    19. // 提取MIPS指令的操作码
    20. val opcode = io.Instr_word(31, 26)
    21. //提取MIPS指令的功能码
    22. val funct = io.Instr_word(5, 0)
    23. // 译码
    24. io.add_op := opcode === OPCODE_ADD && funct === FUNCT_ADD
    25. io.sub_op := opcode === OPCODE_SUB && funct === FUNCT_SUB
    26. io.lw_op := opcode === OPCODE_LW
    27. io.sw_op := opcode === OPCODE_SW
    28. io.nop_op := !(io.add_op || io.sub_op || io.lw_op || io.sw_op)
    29. }
    30. object Decoder extends App {
    31. (new chisel3.stage.ChiselStage).emitVerilog(new Decoder())
    32. }

     DecoderTest.scala

    1. import chiseltest._
    2. import org.scalatest.flatspec.AnyFlatSpec
    3. import chisel3._
    4. class DecoderTest extends AnyFlatSpec with ChiselScalatestTester {
    5. behavior of "Decoder"
    6. it should "correctly decode instructions" in {
    7. test(new Decoder).withAnnotations(Seq(WriteVcdAnnotation)) { c =>
    8. // Test instructions
    9. val addInstruction = "b000000_00010_00011_00001_00000_100000".U
    10. val subInstruction = "b000000_00101_00110_00000_00000_100010".U
    11. val lwInstruction = "b100011_00010_00101_0000000001100100".U
    12. val swInstruction = "b101011_00010_00101_0000000001101000".U
    13. val jalInstruction = "b000011_00000_00000000000000000000".U
    14. // Set the input instruction and evaluate the decoder
    15. c.io.Instr_word.poke(addInstruction)
    16. c.clock.step()
    17. c.io.add_op.expect(true)
    18. c.io.sub_op.expect(false)
    19. c.io.lw_op.expect(false)
    20. c.io.sw_op.expect(false)
    21. c.io.nop_op.expect(false)
    22. c.io.Instr_word.poke(subInstruction)
    23. c.clock.step()
    24. c.io.add_op.expect(false)
    25. c.io.sub_op.expect(true)
    26. c.io.lw_op.expect(false)
    27. c.io.sw_op.expect(false)
    28. c.io.nop_op.expect(false)
    29. c.io.Instr_word.poke(lwInstruction)
    30. c.clock.step()
    31. c.io.add_op.expect(false)
    32. c.io.sub_op.expect(false)
    33. c.io.lw_op.expect(true)
    34. c.io.sw_op.expect(false)
    35. c.io.nop_op.expect(false)
    36. c.io.Instr_word.poke(swInstruction)
    37. c.clock.step()
    38. c.io.add_op.expect(false)
    39. c.io.sub_op.expect(false)
    40. c.io.lw_op.expect(false)
    41. c.io.sw_op.expect(true)
    42. c.io.nop_op.expect(false)
    43. c.io.Instr_word.poke(jalInstruction)
    44. c.clock.step()
    45. c.io.add_op.expect(false)
    46. c.io.sub_op.expect(false)
    47. c.io.lw_op.expect(false)
    48. c.io.sw_op.expect(false)
    49. c.io.nop_op.expect(true)
    50. }
    51. }
    52. }

    设计寄存器文件

    共32个32bit寄存器,允许两读一写,且0号寄存器固定读出位0。四个输入信号为RS1、RS2、WB_data、Reg_WB,寄存器输出RS1_out和RS2_out;寄存器内部保存的初始数值等同于寄存器编号

    给出Chisel设计代码和仿真测试波形,观察RS1=5,RS2=8,WB_data=0x1234,Reg_WB=1的输出波形和受影响寄存器的值。

    Register.scala

    1. import chisel3._
    2. import chisel3.util._
    3. class RegisterFile extends Module {
    4. val io = IO(new Bundle {
    5. val RS1 = Input(UInt(5.W)) // RS1输入信号,用于选择要读取的寄存器
    6. val RS2 = Input(UInt(5.W)) // RS2输入信号,用于选择要读取的寄存器
    7. val WB_data = Input(UInt(32.W)) // 写入数据信号,用于写入寄存器
    8. val Reg_WB = Input(UInt(5.W)) // 选择写入数据的寄存器
    9. val RS1_out = Output(UInt(32.W)) // RS1输出数据
    10. val RS2_out = Output(UInt(32.W)) // RS2输出数据
    11. })
    12. val registers = RegInit(VecInit((0 until 32).map(_.U(32.W)))) // 3232位寄存器,初始值等于寄存器编号
    13. registers(io.Reg_WB) := io.WB_data // 写入数据到寄存器
    14. io.RS1_out := Mux(io.RS1 === 0.U, 0.U, registers(io.RS1)) // RS1输出数据,0号寄存器固定读出位0
    15. io.RS2_out := Mux(io.RS2 === 0.U, 0.U, registers(io.RS2)) // RS2输出数据,0号寄存器固定读出位0
    16. }
    17. object RegisterFile extends App {
    18. (new chisel3.stage.ChiselStage).emitVerilog(new RegisterFile())
    19. }

    RegisterTest.scala

    1. import chisel3._
    2. import chiseltest._
    3. import org.scalatest.flatspec.AnyFlatSpec
    4. import chisel3.util._
    5. class RegisterFileTest extends AnyFlatSpec with ChiselScalatestTester {
    6. behavior of "RegisterFile"
    7. it should "correctly update and read registers" in {
    8. test(new RegisterFile).withAnnotations(Seq(WriteVcdAnnotation)) { c =>
    9. // 设置输入信号
    10. c.io.RS1.poke(5.U)
    11. c.io.RS2.poke(8.U)
    12. c.io.WB_data.poke(0x1234.U)
    13. c.io.Reg_WB.poke(1.U)
    14. c.clock.step()
    15. c.io.RS1_out.expect(5.U)
    16. c.io.RS2_out.expect(8.U)
    17. }
    18. }
    19. }

    实现一个32个字的指令存储器

    从0地址分别存储4条指令add R1,R2,R3; sub R0,R5,R6,lw R5,100(R2), sw R5,104(R2)。然后组合指令存储器、寄存器文件、译码电路,并结合PC更新电路(PC初值为0)、WB_data和Reg_WB信号产生电路,最终让电路能逐条指令取出、译码(不需要完成指令执行)。

    给出Chisel设计代码和仿真测试波形,观察四条指令的执行过程波形,记录并解释其含义。

    InstructionMemory.scala

    1. import chisel3._
    2. class InstructionMemory extends Module {
    3. val io = IO(new Bundle {
    4. val address = Input(UInt(5.W)) // 32个字,需要5位地址
    5. val instruction = Output(UInt(32.W))
    6. })
    7. // 创建一个32个字的指令存储器
    8. val mem = Mem(32, UInt(32.W))
    9. // 初始化存储器,存储MIPS指令
    10. mem.write(0.U, "b000000_00010_00011_00001_00000_100000".U) // add R1, R2, R3
    11. mem.write(1.U, "b000000_00101_00110_00000_00000_100010".U) // sub R0, R5, R6
    12. mem.write(2.U, "b100011_00010_00101_0000000001100100".U) // lw R5, 100(R2)
    13. mem.write(3.U, "b101011_00010_00101_0000000001101000".U) // sw R5, 104(R2)
    14. // 从存储器中读取指令
    15. io.instruction := mem.read(io.address)
    16. }

    Circuit.scala

    1. import chisel3._
    2. import chisel3.util._
    3. class Circuit extends Module {
    4. val io = IO(new Bundle {
    5. // 寄存器的输入输出
    6. val WB_data = Input(UInt(32.W)) // 写入数据信号,用于写入寄存器
    7. val Reg_WB = Input(UInt(5.W)) // 选择写入数据的寄存器
    8. val RS1_out = Output(UInt(32.W))
    9. val RS2_out = Output(UInt(32.W))
    10. // 译码
    11. val add_op = Output(Bool())
    12. val sub_op = Output(Bool())
    13. val lw_op = Output(Bool())
    14. val sw_op = Output(Bool())
    15. val nop_op = Output(Bool())
    16. })
    17. val instructionMemory = Module(new InstructionMemory)
    18. val registerFile = Module(new RegisterFile)
    19. val decoder = Module(new Decoder)
    20. val pc = RegInit(0.U(5.W))
    21. // 根据pc的值取出指令寄存器相应指令
    22. instructionMemory.io.address := pc
    23. decoder.io.Instr_word := instructionMemory.io.instruction
    24. registerFile.io.RS1 := instructionMemory.io.instruction(25, 21)
    25. registerFile.io.RS2 := instructionMemory.io.instruction(20, 16)
    26. registerFile.io.WB_data := (0.U(32.W))
    27. registerFile.io.Reg_WB := (0.U(5.W))
    28. // 更新输出
    29. io.RS1_out := registerFile.io.RS1_out
    30. io.RS2_out := registerFile.io.RS2_out
    31. io.add_op := decoder.io.add_op
    32. io.sub_op := decoder.io.sub_op
    33. io.lw_op := decoder.io.lw_op
    34. io.sw_op := decoder.io.sw_op
    35. io.nop_op := decoder.io.nop_op
    36. // 更新PC
    37. pc := pc + 1.U
    38. }
    39. object Circuit extends App {
    40. (new chisel3.stage.ChiselStage).emitVerilog(new Circuit())
    41. }

    CircuitTest.scala

    1. import chiseltest._
    2. import org.scalatest.flatspec.AnyFlatSpec
    3. import chisel3._
    4. class CircuitTest extends AnyFlatSpec with ChiselScalatestTester {
    5. behavior of "Circuit"
    6. it should "correct circuit" in {
    7. test(new Circuit).withAnnotations(Seq(WriteVcdAnnotation)) { c =>
    8. c.clock.step()
    9. c.clock.step()
    10. c.clock.step()
    11. c.clock.step()
    12. }
    13. }
    14. }
  • 相关阅读:
    边际图和组合折线图
    【微信小程序】使用npm包
    k8s — Cluster Architecture
    从GAN到WGAN(01/2)
    Pulsar-Pulsar 之 Functions
    Spring Boot实现验证码功能
    Linux网络命令——tcpdump
    【基于pyAudioKits的Python音频信号处理项目(一)】实现音频频谱分析仪并进行交互式滤波器设计
    (最新版2022版)剑指offer之动态规划题解
    计算机毕业设计ssm基于SSM的砂石销售管理系统998g8系统+程序+源码+lw+远程部署
  • 原文地址:https://blog.csdn.net/weixin_62264287/article/details/134212138