riscv-sodor-rv32_3stage(1)

学习了1阶和2阶risc-v处理器后,现在学习3阶的,3阶的没有找到图。按照惯例,我们一个个scala文件进行说明。先进行说明的是alu.scala(算术逻辑单元(arithmetic and logic unit) 是能实现多组算术运算和逻辑运算的组合逻辑电路,简称ALU):

package Sodor

import chisel3._
import chisel3.util._

import Common._
import Constants._

//定义伴生对象,定义一些常量信号
object ALU
{
  // TODO is this the optimal encoding?
  //定义ALU函数的宽度,这里是4bits,也就是ALU最多可以有16种种类
  val SZ_ALU_FN = 4
  //ALU_X为0值
  val ALU_X    = 0.U // TODO use a more optimal decode table, which uses "???" format
  //ALU_ADD,加法为0值
  val ALU_ADD  = 0.U
  //ALU_SLL,逻辑左移为1值
  val ALU_SLL  = 1.U
  //ALU_XOR,异或为4值
  val ALU_XOR  = 4.U
  //ALU_OR,或为6值
  val ALU_OR   = 6.U
  //ALU_AND,与为7值
  val ALU_AND  = 7.U
  //ALU_AND,逻辑右移为5值
  val ALU_SRL  = 5.U
  //ALU_SUB,减为10值
  val ALU_SUB  = 10.U
  //ALU_SRA,算数右移为11值
  val ALU_SRA  = 11.U
  //ALU_SLT,小于为12值
  val ALU_SLT  = 12.U
  //ALU_SLTU,小于,无符号U-type为14值
  val ALU_SLTU = 14.U
  //ALU_COPY1,复制为8值
  val ALU_COPY1= 8.U   
    
  //定义isSub的方法,提前cmd的第三位数据
  def isSub(cmd: UInt) = cmd(3)
 //定义isSLTU的方法,提前cmd的第一位数据
  def isSLTU(cmd: UInt) = cmd(1)
}
import ALU._

//定义ALU模块的端口,输入函数(fn),in1和in2,得出out或adder_out
class ALUIO(implicit conf: SodorConfiguration) extends Bundle {
  val fn = Input(UInt(SZ_ALU_FN.W))
  val in2 = Input(UInt(conf.xprlen.W))
  val in1 = Input(UInt(conf.xprlen.W))
  val out = Output(UInt(conf.xprlen.W))
  val adder_out = Output(UInt(conf.xprlen.W))
}

//ALU模块的主题
class ALU(implicit conf: SodorConfiguration) extends Module
{
  //调用ALUIO模块,命名为io
  val io = IO(new ALUIO)

  //msb是Most Significant Bit的缩写,指最高有效位,这里是32-1,也就是31
  val msb = conf.xprlen-1

  // ADD, SUB
  //加法和减法的操作,如果输入的fn信号第三位为1,则运行减法,in1-in2,
  //如果为0,则运行加法,将in1+in2
  val sum = io.in1 + Mux(isSub(io.fn), -io.in2, io.in2)

  // SLT, SLTU
  //先做Mux(isSLTU(io.fn), io.in2(msb), io.in1(msb)),利用isSLTU(io.fn)判断fn信号的第一位,若是1,则//输出in2的最高位,否则输出in1的最高位
  //然后再做Mux(io.in1(msb) === io.in2(msb), sum(msb), X),其中X,为上面一步的结果,若in1的最高位
  //等于in2的最高位,则输出sum的最高位,如果in1最高位和in2最高位不等,则输出X的结果
  //这里要看slt指令的说明,比较rs1和rs2的值,如果rs1<rs2,则置1值rd中,rs1和rs2位有符号数,
  //sltu则用来判断无符号数,我们先看sltu的,当为无符号数时,且in1(31)==in2(31)时,用sum值来作为//less,也就是当sum为负值,则rs1<rs2,所以less置1,当sum为正,则rs1>rs2,所以less置0,如果//in1(31)不等于in2(31)时,因为是sltu指令,所以isSLTU(io.fn)为1,因此less取in2(31),因为如果in2(31)
  //为1,in1(31)必定为0,所以less=in2(31),反过来,如果in2(31)为0,则in1(31)必定为1,所以less为
  //0,也是less=in2(31),slt也是同样的方法分析
  val less  =  Mux(io.in1(msb) === io.in2(msb), sum(msb),
              Mux(isSLTU(io.fn), io.in2(msb), io.in1(msb)))

  require(conf.xprlen == 32)
  // SLL, SRL, SRA
  //提前指令中需要移动的位数,是in2的第四位置第零位
  val shamt = io.in2(4,0).toUInt
  //将in1的值赋给shin_r
  val shin_r = io.in1(31,0)
  
  //判断(io.fn === ALU_SRL  || io.fn === ALU_SRA,如果是,则将shin_r赋给shin,否则赋Reverse(shin_r)
  //Reverse是将shin_r取反
  val shin = Mux(io.fn === ALU_SRL  || io.fn === ALU_SRA, shin_r, Reverse(shin_r))
  //算数右移或者逻辑右移的操作
  val shout_r = (Cat(isSub(io.fn) & shin(msb), shin).toSInt >> shamt)(msb,0)
  //逻辑左移的结果,将shout_r取反
  val shout_l = Reverse(shout_r)

  //根据in.fn函数来输出bitwise_logic信号,分别有与,或,异或,copy
  val bitwise_logic =
    Mux(io.fn === ALU_AND, io.in1 & io.in2,
    Mux(io.fn === ALU_OR,  io.in1 | io.in2,
    Mux(io.fn === ALU_XOR, io.in1 ^ io.in2,
                           io.in1))) // ALU_COPY1

  //根据in.fn函数来输出out_xpr_length信号,分别有加,减,小于,小于(无符号数),逻辑右移,算术右//移,逻辑左移和bitwise_logic
  val out_xpr_length =
    Mux(io.fn === ALU_ADD || io.fn === ALU_SUB,  sum,
    Mux(io.fn === ALU_SLT || io.fn === ALU_SLTU, less,
    Mux(io.fn === ALU_SRL || io.fn === ALU_SRA,  shout_r,
    Mux(io.fn === ALU_SLL,                       shout_l,
        bitwise_logic))))

  //将out_xpr_length的值赋给ALU端口io.out
  io.out := out_xpr_length(31,0).toUInt
  //将sum的值赋给ALU端口io.adder_out
  io.adder_out := sum
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值