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

这篇具有很好参考价值的文章主要介绍了【计算机组成与设计】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)时,对应的输出波形

【计算机组成与设计】Chisel取指和指令译码设计,计算机系统3,c#,开发语言

Decode.scala

import chisel3._

class Decoder extends Module {
  val io = IO(new Bundle {
    val Instr_word = Input(UInt(32.W))
    val add_op = Output(Bool())
    val sub_op = Output(Bool())
    val lw_op = Output(Bool())
    val sw_op = Output(Bool())
    val nop_op = Output(Bool())
  })
  // 定义操作码
  val OPCODE_ADD = "b000000".U
  val OPCODE_SUB = "b000000".U
  val OPCODE_LW = "b100011".U
  val OPCODE_SW = "b101011".U
  //定义功能码
  val FUNCT_ADD = "b100000".U
  val FUNCT_SUB = "b100010".U
  // 提取MIPS指令的操作码
  val opcode = io.Instr_word(31, 26)
  //提取MIPS指令的功能码
  val funct = io.Instr_word(5, 0)
  // 译码
  io.add_op := opcode === OPCODE_ADD && funct === FUNCT_ADD
  io.sub_op := opcode === OPCODE_SUB && funct === FUNCT_SUB
  io.lw_op := opcode === OPCODE_LW
  io.sw_op := opcode === OPCODE_SW
  io.nop_op := !(io.add_op || io.sub_op || io.lw_op || io.sw_op)
}

object Decoder extends App {
  (new chisel3.stage.ChiselStage).emitVerilog(new Decoder())
}

 DecoderTest.scala

import chiseltest._
import org.scalatest.flatspec.AnyFlatSpec
import chisel3._

class DecoderTest extends AnyFlatSpec with ChiselScalatestTester {
  behavior of "Decoder"
  it should "correctly decode instructions" in {
    test(new Decoder).withAnnotations(Seq(WriteVcdAnnotation)) { c =>
      // Test instructions
      val addInstruction = "b000000_00010_00011_00001_00000_100000".U
      val subInstruction = "b000000_00101_00110_00000_00000_100010".U
      val lwInstruction = "b100011_00010_00101_0000000001100100".U
      val swInstruction = "b101011_00010_00101_0000000001101000".U
      val jalInstruction = "b000011_00000_00000000000000000000".U
      // Set the input instruction and evaluate the decoder
      c.io.Instr_word.poke(addInstruction)
      c.clock.step()
      c.io.add_op.expect(true)
      c.io.sub_op.expect(false)
      c.io.lw_op.expect(false)
      c.io.sw_op.expect(false)
      c.io.nop_op.expect(false)

      c.io.Instr_word.poke(subInstruction)
      c.clock.step()
      c.io.add_op.expect(false)
      c.io.sub_op.expect(true)
      c.io.lw_op.expect(false)
      c.io.sw_op.expect(false)
      c.io.nop_op.expect(false)

      c.io.Instr_word.poke(lwInstruction)
      c.clock.step()
      c.io.add_op.expect(false)
      c.io.sub_op.expect(false)
      c.io.lw_op.expect(true)
      c.io.sw_op.expect(false)
      c.io.nop_op.expect(false)

      c.io.Instr_word.poke(swInstruction)
      c.clock.step()
      c.io.add_op.expect(false)
      c.io.sub_op.expect(false)
      c.io.lw_op.expect(false)
      c.io.sw_op.expect(true)
      c.io.nop_op.expect(false)

      c.io.Instr_word.poke(jalInstruction)
      c.clock.step()
      c.io.add_op.expect(false)
      c.io.sub_op.expect(false)
      c.io.lw_op.expect(false)
      c.io.sw_op.expect(false)
      c.io.nop_op.expect(true)
    }
  }
}

设计寄存器文件

共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的输出波形和受影响寄存器的值。

【计算机组成与设计】Chisel取指和指令译码设计,计算机系统3,c#,开发语言

Register.scala

import chisel3._
import chisel3.util._

class RegisterFile extends Module {
  val io = IO(new Bundle {
    val RS1 = Input(UInt(5.W)) // RS1输入信号,用于选择要读取的寄存器
    val RS2 = Input(UInt(5.W)) // RS2输入信号,用于选择要读取的寄存器
    val WB_data = Input(UInt(32.W)) // 写入数据信号,用于写入寄存器
    val Reg_WB = Input(UInt(5.W)) // 选择写入数据的寄存器
    val RS1_out = Output(UInt(32.W)) // RS1输出数据
    val RS2_out = Output(UInt(32.W)) // RS2输出数据
  })

  val registers = RegInit(VecInit((0 until 32).map(_.U(32.W)))) // 32个32位寄存器,初始值等于寄存器编号
  registers(io.Reg_WB) := io.WB_data // 写入数据到寄存器
  io.RS1_out := Mux(io.RS1 === 0.U, 0.U, registers(io.RS1)) // RS1输出数据,0号寄存器固定读出位0
  io.RS2_out := Mux(io.RS2 === 0.U, 0.U, registers(io.RS2)) // RS2输出数据,0号寄存器固定读出位0
}

object RegisterFile extends App {
  (new chisel3.stage.ChiselStage).emitVerilog(new RegisterFile())
}

RegisterTest.scala

import chisel3._
import chiseltest._
import org.scalatest.flatspec.AnyFlatSpec
import chisel3.util._

class RegisterFileTest extends AnyFlatSpec with ChiselScalatestTester {
  behavior of "RegisterFile"
  it should "correctly update and read registers" in {
    test(new RegisterFile).withAnnotations(Seq(WriteVcdAnnotation)) { c =>
      // 设置输入信号
      c.io.RS1.poke(5.U)
      c.io.RS2.poke(8.U)
      c.io.WB_data.poke(0x1234.U)
      c.io.Reg_WB.poke(1.U)

      c.clock.step()
      c.io.RS1_out.expect(5.U)
      c.io.RS2_out.expect(8.U)
    }
  }
}

实现一个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设计代码和仿真测试波形,观察四条指令的执行过程波形,记录并解释其含义。

【计算机组成与设计】Chisel取指和指令译码设计,计算机系统3,c#,开发语言

InstructionMemory.scala

import chisel3._

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

Circuit.scala

import chisel3._
import chisel3.util._

class Circuit extends Module {
  val io = IO(new Bundle {
    // 寄存器的输入输出
    val WB_data = Input(UInt(32.W)) // 写入数据信号,用于写入寄存器
    val Reg_WB = Input(UInt(5.W)) // 选择写入数据的寄存器
    val RS1_out = Output(UInt(32.W))
    val RS2_out = Output(UInt(32.W))
    // 译码
    val add_op = Output(Bool())
    val sub_op = Output(Bool())
    val lw_op = Output(Bool())
    val sw_op = Output(Bool())
    val nop_op = Output(Bool())
  })

  val instructionMemory = Module(new InstructionMemory)
  val registerFile = Module(new RegisterFile)
  val decoder = Module(new Decoder)
  val pc = RegInit(0.U(5.W))
  // 根据pc的值取出指令寄存器相应指令
  instructionMemory.io.address := pc
  decoder.io.Instr_word := instructionMemory.io.instruction
  registerFile.io.RS1 := instructionMemory.io.instruction(25, 21)
  registerFile.io.RS2 := instructionMemory.io.instruction(20, 16)
  registerFile.io.WB_data := (0.U(32.W))
  registerFile.io.Reg_WB := (0.U(5.W))
  // 更新输出
  io.RS1_out := registerFile.io.RS1_out
  io.RS2_out := registerFile.io.RS2_out
  io.add_op := decoder.io.add_op
  io.sub_op := decoder.io.sub_op
  io.lw_op := decoder.io.lw_op
  io.sw_op := decoder.io.sw_op
  io.nop_op := decoder.io.nop_op
  // 更新PC
  pc := pc + 1.U
}

object Circuit extends App {
  (new chisel3.stage.ChiselStage).emitVerilog(new Circuit())
}

CircuitTest.scala文章来源地址https://www.toymoban.com/news/detail-744211.html

import chiseltest._
import org.scalatest.flatspec.AnyFlatSpec
import chisel3._

class CircuitTest extends AnyFlatSpec with ChiselScalatestTester {
  behavior of "Circuit"
  it should "correct circuit" in {
    test(new Circuit).withAnnotations(Seq(WriteVcdAnnotation)) { c =>
      c.clock.step()
      c.clock.step()
      c.clock.step()
      c.clock.step()
    }
  }
}

到了这里,关于【计算机组成与设计】Chisel取指和指令译码设计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Chisel程序设计-取指译码模块实现

    bilibili: chisel入门程序设计-取指译码模块的简单实现 设计一个连续取指+译指的电路 入门简单数据通路 运用chisel语法编写模块 完成add, sub, lw, sw指令译码。其他指令一律译为nop 译码器如图所示: IO端口 实现代码,完成波形仿真测试。 指令测试样例: 32-bit的寄存器 x 32 允许两读

    2024年03月23日
    浏览(43)
  • 计算机组成原理——课程设计

      深入了解计算机各种指令的执行过程,以及控制器的组成,指令系统微程序设计的具体知识,进一步理解和掌握动态微程序设计的概念;完成微程序控制的特定功能计算机的指令系统设计和调试。 1.    TEC-2机一台 2.    电脑一台 3.    TEC-2模拟软件一套 1.分析TEC-2机的功

    2024年02月08日
    浏览(58)
  • 【计算机组成原理实验】CPU设计

    设计并实现一个简单处理器模型完成功能验证。 ASUS VivoBook + Windows10 + Vivado2019.2,语言为 Verilog HDL。 1. 处理器应基于 6.5 指令集或 MIPS 指令集或 RISCV 指令集进行设计或自行设计指令集。 2. 处理器的控制器结构应为微程序控制器或集硬布线控制器。 3. 处理器需支持算术运算、

    2024年02月08日
    浏览(47)
  • 计算机组成原理 存储器设计

    目录 一、把8×8 位的RAM存储器模块扩展为 8×32 位RAM存储空间; 二、把8×8 位的RAM存储器模块扩展为32×8位RAM存储空间; 三、把256×4 位的RAM存储器模块扩展为1K×8b的RAM存储空间。 PS:先说说存储器是什么样的小玩意:                         A x B 位XXX(RAM或者ROM)存储器的

    2024年02月07日
    浏览(52)
  • 计算机组成与设计04——处理器

    目录 系列文章目录 一、引言 1.计算机性能因素 2.基本的MIPS实现(指令部分) 3.CPU 抽象视图 4.MIPS子集的基本实现 二、逻辑设计基础 1.组合单元 2.时钟方法 三、数据通路的建立 1.R型指令 2.存取指令 3.分支指令  4.简单的数据通路(R型/存取) 5.完整的数据通路(单周期) 四、

    2024年02月04日
    浏览(43)
  • 系统架构设计专业技能 · 计算机组成与结构

    现在的一切都是为将来的梦想编织翅膀,让梦想在现实中展翅高飞。 Now everything is for the future of dream weaving wings, let the dream fly in reality. 点击进入系列文章目录 运算器 ① 算术逻辑单元ALU:数据的算术运算和逻辑运算 ② 累加寄存器AC:通用寄存器, 为ALU提供一个工作区, 用于

    2024年02月09日
    浏览(54)
  • 计算机组成原理实验 MIPS RAM设计

    一、设计要求     Logisim中RAM组件只能提供固定的地址位宽,数据输出也只能提供固定的数据位宽,访问时无法同时支持字节/半字/字三种访问模式,实验要求利用4个4K * 8 位的 RAM 组件进行扩展,设计完成既能按照8位、也能按照16位、也能按照32位进行读写访问的32位存储器

    2024年02月04日
    浏览(43)
  • 西南交通大学 计算机组成原理实验课程设计

     代码部分: 波形图部分: (上图Load为2节拍,我之前写错了。。。这里忘了改了)

    2024年02月13日
    浏览(49)
  • 计算机组成原理实验——五、单周期CPU设计

    掌握指令执行过程的5个阶段 掌握每条指令的数据通路选择 掌握译码器和控制器的功能和实现 掌握数据输入输出处理的方法 实现risc-v中RV32I指令的单周期CPU 利用实现的risc-v CPU实现平方数 实现risc-v中37条RV32I指令的单周期 cpu; 完成1后在该cpu上实现斐波那契数。 rom dataRAM ins文

    2024年02月11日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包