我们已经了解RISC-V指令集
本次课内容:
回顾指令周期: 执行一条指令的步骤
单周期处理器的思想: 一个周期内完成上述步骤
import chisel3._
import chisel3.util._
import chisel3.util.experimental.loadMemoryFromFileInline
class YPC extends Module {
val io = IO(new Bundle{ val halt = Output(Bool()) })
val R = Mem(32, UInt(32.W))
val PC = RegInit(0.U(32.W))
val M = Mem(1024 / 4, UInt(32.W))
def Rread(idx: UInt) = Mux(idx === 0.U, 0.U(32.W), R(idx))
loadMemoryFromFileInline(M, "prog.hex")
val Ibundle = new Bundle {
val imm11_0 = UInt(12.W)
val rs1 = UInt( 5.W)
val funct3 = UInt( 3.W)
val rd = UInt( 5.W)
val opcode = UInt( 7.W)
}
def SignEXT(imm11_0: UInt) = Cat(Fill(20, imm11_0(11)), imm11_0)
val inst = M(PC(31, 2)).asTypeOf(Ibundle)
val isAddi = (inst.opcode === "b0010011".U) && (inst.funct3 === "b000".U)
val isEbreak = inst.asUInt === "x00100073".U
assert(isAddi || isEbreak, "Invalid instruction 0x%x", inst.asUInt)
val rs1Val = Rread(Mux(isEbreak, 10.U(5.W), inst.rs1))
val rs2Val = Rread(Mux(isEbreak, 11.U(5.W), 0.U(5.W)))
when (isAddi) { R(inst.rd) := rs1Val + SignEXT(inst.imm11_0) }
when (isEbreak && (rs1Val === 0.U)) { printf("%c", rs2Val(7,0)) }
io.halt := isEbreak && (rs1Val === 1.U)
PC := PC + 4.U
}
在类似YEMU的模拟器中也存在数据通路和控制信号的概念
inst_cycle()
可以看作是数据通路if
,
switch-case
充当了控制信号的作用
以上是通用的设计方法, 可用于设计任意模块, 例如总线, cache
功能需求=指令行为
, 就得到单周期处理器设计流程
这对大家提出更高的要求
很多书籍把图画好, 甚至把代码写好, 直接阅读这类书籍并不能帮助大家锻炼上述能力
如果你之前从未了解过单周期处理器设计, 强烈建议先不要看书
回顾: 行波进位加法器(Ripple-Carry Adder, RCA)
新的解读
对于4位加法器
C1 = G0 | (C0 & P0)
C2 = G1 | (C1 & P1) = G1 | ((G0 | (C0 & P0)) & P1) = G1 | (G0 & P1) | (C0 & P0 & P1)
C3 = G2 | (C2 & P2) = G2 | (G1 & P2) | (G0 & P1 & P2) | (C0 & P0 & P1 & P2)
C4 = G3 | (G2 & P3) | (G1 & P2 & P3) | (G0 & P1 & P2 & P3) | (C0 & P0 & P1 & P2 & P3)
G和P只依赖加法器的输入, 不依赖每一位的进位!
设\(D(s)\)为传播信号\(s\)所需的门延迟级数, 设\(d\)为1级门延迟
这就是先行进位加法器(Carry-Lookahead Adder, CLA)
C4 = (A3 & B3) | (C3 & (A3 ^ B3))
= (A3 & B3) | (((A2 & B2) | (C2 & (A2 ^ B2))) & (A3 ^ B3)) = ...
= (A3 & B3) | (((A2 & B2) | (((A1 & B1) | (((A0 & B0) | (C0 & (A0 ^ B0)))
& (A1 & B1))) & (A2 ^ B2))) & (A3 ^ B3))
4位RCA中4个FA级联, 每经过一个FA计算\(C_i\)需额外\(2d\)
C4 = G3 | (G2 & P3) | (G1 & P2 & P3) | (G0 & P1 & P2 & P3) | (C0 & P0 & P1 & P2 & P3)
C64 = G63 | (G62 & P63) | (G61 & P62 & P63) | (G60 & P61 & P62 & P63) | ...
原则上来说, 位宽更大的CLA也可以通过上述方式搭建
A3B3 A2B2 A1B1 A0B0
|| || || ||
+---------------------------------------------+
S0<--|------||--------||--------||------+ || |
S1<--|------||--------||------+ || | || |
S2<--|------||------+ || | || | || |
S3<--|-+ VV | VV | VV | VV |
| | +----+ +----+ +----+ +----+ |
| +-| FA |<-+ | FA |<-+ | FA |<-+ | FA |<--+--|--C0
| +----+ | +----+ | +----+ | +----+ | |
| || | || | || | || | |
| VV | VV | VV | VV | |
| +------------------------------------+ | |
| | P3G3 C3 P2G2 C2 P1G1 C1 P0G0| | |
C4<--|--|C4 Carry Lookahead Unit(CLU) |<-+ |
| | PG GG | |
| +------------------------------------+ |
| 4-bit Carry-Lookahead Adder | | |
+---------------------------------------------+
| |
V V
A/B12~15 A/B8~11 A/B4~7 A/B0~3
|| || || ||
+---------------------------------------------+
S0~3 <--|------||--------||--------||------+ || |
S4~7 <--|------||--------||------+ || | || |
S8~11 <--|------||------+ || | || | || |
S12~15<--|-+ VV | VV | VV | VV |
| | +----+ +----+ +----+ +----+ |
| +-|4CLA|<-+ |4CLA|<-+ |4CLA|<-+ |4CLA|<--+--|--C0
| +----+ | +----+ | +----+ | +----+ | |
| || | || | || | || | |
| VV | VV | VV | VV | |
| +------------------------------------+ | |
| | P3G3 C12 P2G2 C8 P1G1 C4 P0G0| | |
C16 <--|--|C16 Carry Lookahead Unit(CLU) |<-+ |
| | PG GG | |
| +------------------------------------+ |
| 16-bit Carry-Lookahead Adder | | |
+---------------------------------------------+
| |
V V
同理, 64位CLA可以通过4个16位CLA和1个CLU组合搭建
A/B12~15 A/B8~11 A/B4~7 A/B0~3
|| || || ||
+---------------------------------------------+
S0~3 <--|------||--------||--------||------+ || |
S4~7 <--|------||--------||------+ || | || |
S8~11 <--|------||------+ || | || | || |
S12~15<--|-+ VV | VV | VV | VV |
| | +----+ +----+ +----+ +----+ |
| +-|4CLA|<-+ |4CLA|<-+ |4CLA|<-+ |4CLA|<--+--|--C0
| +----+ | +----+ | +----+ | +----+ | |
| || | || | || | || | |
| VV | VV | VV | VV | |
| +------------------------------------+ | |
| | P3G3 C12 P2G2 C8 P1G1 C4 P0G0| | |
C16 <--|--|C16 Carry Lookahead Unit(CLU) |<-+ |
| | PG GG | |
| +------------------------------------+ |
| 16-bit Carry-Lookahead Adder | | |
+---------------------------------------------+
| |
V V
16位RCA
将1
输入到加法器的\(C_0\), 可通过加法器实现减法器
若无需同时完成加法和减法操作, 可让两者共享同一个加法器
\(A_{n-1}\) | \(B_{n-1}\) | \(C_{n-1}\) | \(C_n\) | \(S_{n-1}\) | 溢出 |
---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 1 | 0 | 1 | 1 |
0 | 1 | 0 | 0 | 1 | 0 |
0 | 1 | 1 | 1 | 0 | 0 |
1 | 0 | 0 | 0 | 1 | 0 |
1 | 0 | 1 | 1 | 0 | 0 |
1 | 1 | 0 | 1 | 0 | 1 |
1 | 1 | 1 | 1 | 1 | 0 |
跳转指令还需要在条件满足时修改PC
用电路实现a << b
和a >> b
b
为常数, 则可用位拼接/位抽取实现
a << 4 = {a[27:0], 4'b0000}
b
无法提前确定,
则需根据b
的值动态生成移位结果
交叉开关式桶形移位器: 根据\(A\)直接选择\(Y\)的每一位
级联式桶形移位器: 采用(\(\log_2{n}\)级\(\times\)\(n\)个/级)的2-1选择器阵列, 第\(i\)级根据\(S_i\)选择是否移动\(2^i\)位, 并将选择结果作为下一级的输入
可以增加逻辑右移和算术右移功能
大部分情况下, 综合器能将各种运算符综合成高质量的电路
+
/-
/<
等,
综合器通常都综合出CLA
所以, 我们只需要从学习的层面了解前文设计的基本原理即可
+
/-
/<
等运算符综合成何种电路
lui
auipc
-> 加法器
jal
, jalr
通常把加法器, 移位器, 以及用于逻辑运算的逻辑门统称为ALU
负责从指令生成控制信号, 从而控制数据通路上的数据流向
都是同一个设计, 但怎么写代码又是另一回事
assign SB = (IR[31] & ~IR[30] & IR[29] & ~IR[28] & ~IR[27] & ~IR[26]);
assign SH = (IR[31] & ~IR[30] & IR[29] & ~IR[28] & ~IR[27] & IR[26]);
assign SWR = (IR[31] & ~IR[30] & IR[29] & IR[28] & IR[27] & ~IR[26]);
assign SWL = (IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & ~IR[26]);
assign SRL = (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & ~IR[3] & ~IR[2] & IR[1] & ~IR[0]);
assign SRA = (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & ~IR[3] & ~IR[2] & IR[1] & IR[0]);
assign Ext0 = (~IR[31] & ~IR[30] & IR[29] & IR[28] & ~IR[27] & IR[26]) | (~IR[31] & ~IR[30] & IR[29] & IR[28] & ~IR[27] & ~IR[26]) | (~IR[31] & ~IR[30] & IR[29] & IR[28] & IR[27] & ~IR[26]);
assign Wtrs = ((Zero == 1'b0) & (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & IR[3] & ~IR[2] & IR[1] & IR[0])) | ((Zero == 1'b1) & (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & IR[3] & ~IR[2] & IR[1] & ~IR[0]));
assign LWLR1 = (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & IR[28] & IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & IR[29] & IR[28] & IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & IR[28] & ~IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & IR[28] & ~IR[27] & IR[26]) | (IR[31] & ~IR[30] & IR[29] & ~IR[28] & ~IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & IR[29] & ~IR[28] & ~IR[27] & IR[26]);
assign LWLR2 = (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & IR[27] & ~IR[26]);
assign LWLR3 = (IR[31] & ~IR[30] & ~IR[29] & IR[28] & IR[27] & ~IR[26]);
assign LHU = (IR[31] & ~IR[30] & ~IR[29] & IR[28] & ~IR[27] & IR[26]);
assign LH = (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & IR[26]);
assign LBU = (IR[31] & ~IR[30] & ~IR[29] & IR[28] & ~IR[27] & ~IR[26]);
assign LB = (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26]);
assign ZeroJg = (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & IR[26] & ~IR[20] & ~IR[19] & ~IR[18] & ~IR[17] & IR[16]) | (~IR[31] & ~IR[30] & ~IR[29] & IR[28] & IR[27] & ~IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & IR[26] & ~IR[20] & ~IR[19] & ~IR[18] & ~IR[17] & ~IR[16]) | (IR[31:26] == 6'b000111);
assign RegDst = (~IR[31] & ~IR[30] & IR[29] & ~IR[28] & ~IR[27] & IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & IR[27] & IR[26]) | (~IR[31] & ~IR[30] & IR[29] & IR[28] & IR[27] & IR[26]) | (~IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & ~IR[26]) | (~IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & IR[26]) | (~IR[31] & ~IR[30] & IR[29] & IR[28] & ~IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & IR[28] & ~IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & IR[28] & ~IR[27] & IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & IR[28] & IR[27] & ~IR[26]) | (~IR[31] & ~IR[30] & IR[29] & IR[28] & ~IR[27] & IR[26]) | (~IR[31] & ~IR[30] & IR[29] & IR[28] & IR[27] & ~IR[26]);
assign ALUSrc = (~IR[31] & ~IR[30] & ~IR[29] & IR[28] & ~IR[27] & IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & ~IR[3] & ~IR[2] & ~IR[1] & IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & IR[28] & ~IR[27] & ~IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & ~IR[3] & IR[2] & ~IR[1] & IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & IR[3] & ~IR[2] & IR[1] & ~IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & ~IR[3] & ~IR[2] & IR[1] & IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & ~IR[3] & IR[2] & ~IR[1] & ~IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & IR[3] & ~IR[2] & IR[1] & IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & IR[3] & ~IR[2] & IR[1] & ~IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & ~IR[3] & IR[2] & IR[1] & IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & ~IR[3] & IR[2] & ~IR[1] & ~IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & IR[3] & ~IR[2] & IR[1] & IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & ~IR[3] & IR[2] & IR[1] & IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & ~IR[3] & IR[2] & IR[1] & ~IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & ~IR[3] & IR[2] & IR[1] & ~IR[0]);
assign PCSrc = ((~(Zero == 1)) & (~IR[31] & ~IR[30] & ~IR[29] & IR[28] & ~IR[27] & IR[26])) | ((Zero == 1) & (~IR[31] & ~IR[30] & ~IR[29] & IR[28] & ~IR[27] & ~IR[26])) | ((Address == 32'h00000000) & (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & IR[26] & ~IR[20] & ~IR[19] & ~IR[18] & ~IR[17] & IR[16])) | (((Address == 32'h00000001) | (Read1 == 32'h00000000)) & (~IR[31] & ~IR[30] & ~IR[29] & IR[28] & IR[27] & ~IR[26])) | ((Address == 32'h00000001) & (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & IR[26] & ~IR[20] & ~IR[19] & ~IR[18] & ~IR[17] & ~IR[16])) | (Address == 32'h0 & ~(Read1 == 32'h0) & IR[31:26] == 6'b000111);
assign RegWrite = (~IR[31] & ~IR[30] & IR[29] & ~IR[28] & ~IR[27] & IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & IR[27] & IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & ~IR[3] & ~IR[2] & ~IR[1] & IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & ~IR[3] & IR[2] & ~IR[1] & IR[0]) | (~IR[31] & ~IR[30] & IR[29] & IR[28] & IR[27] & IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & ~IR[3] & ~IR[2] & ~IR[1] & ~IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & IR[3] & ~IR[2] & IR[1] & ~IR[0]) | (~IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & ~IR[26]) | (~IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & ~IR[3] & ~IR[2] & IR[1] & IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & IR[27] & IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & ~IR[3] & IR[2] & ~IR[1] & ~IR[0]) | (~IR[31] & ~IR[30] & IR[29] & IR[28] & ~IR[27] & ~IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & IR[3] & ~IR[2] & ~IR[1] & IR[0]) | (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & IR[28] & ~IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & IR[28] & ~IR[27] & IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & IR[28] & IR[27] & ~IR[26]) | ((Zero == 1'b0) & (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & IR[3] & ~IR[2] & IR[1] & IR[0])) | ((Zero == 1'b1) & (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & IR[3] & ~IR[2] & IR[1] & ~IR[0])) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & ~IR[3] & IR[2] & IR[1] & IR[0]) | (~IR[31] & ~IR[30] & IR[29] & IR[28] & ~IR[27] & IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & ~IR[3] & IR[2] & ~IR[1] & ~IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & IR[3] & ~IR[2] & IR[1] & IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & ~IR[3] & ~IR[2] & IR[1] & IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & ~IR[3] & IR[2] & IR[1] & IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & ~IR[3] & ~IR[2] & IR[1] & ~IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & ~IR[3] & IR[2] & IR[1] & ~IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & ~IR[3] & IR[2] & IR[1] & ~IR[0]) | (~IR[31] & ~IR[30] & IR[29] & IR[28] & IR[27] & ~IR[26]);
assign Jmp = (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & IR[27] & ~IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & IR[27] & IR[26]);
assign MemWrite = (IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & IR[26]) | (IR[31] & ~IR[30] & IR[29] & ~IR[28] & ~IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & IR[29] & ~IR[28] & ~IR[27] & IR[26]) | (IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & IR[29] & IR[28] & IR[27] & ~IR[26]);
assign MemRead = (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & IR[27] & IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & IR[28] & ~IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & IR[28] & ~IR[27] & IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & IR[28] & IR[27] & ~IR[26]);
assign MemtoReg = (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & IR[27] & IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & IR[28] & ~IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & IR[28] & ~IR[27] & IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & IR[28] & IR[27] & ~IR[26]);
assign SLL = (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & ~IR[3] & ~IR[2] & ~IR[1] & ~IR[0]);
assign JAL1 = (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & IR[27] & IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & IR[3] & ~IR[2] & ~IR[1] & IR[0]);
assign JAL2 = (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & IR[27] & IR[26]);
assign JR = (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & IR[3] & ~IR[2] & ~IR[1] & ~IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & IR[3] & ~IR[2] & ~IR[1] & IR[0]);
assign Write_strb[3] = (IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & IR[26]) | (ALUResult[1] & ALUResult[0] & IR[31] & ~IR[30] & IR[29] & ~IR[28] & ~IR[27] & ~IR[26]) | (ALUResult[1] & IR[31] & ~IR[30] & IR[29] & ~IR[28] & ~IR[27] & IR[26]) | (ALUResult[1] & ALUResult[0] & IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & IR[29] & IR[28] & IR[27] & ~IR[26]);
assign Write_strb[2] = (IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & IR[26]) | (ALUResult[1] & ~ALUResult[0] & IR[31] & ~IR[30] & IR[29] & ~IR[28] & ~IR[27] & ~IR[26]) | (ALUResult[1] & IR[31] & ~IR[30] & IR[29] & ~IR[28] & ~IR[27] & IR[26]) | (ALUResult[1] & IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & ~IR[26]) | (~ALUResult[1] & IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & ~IR[26]) | (ALUResult[1] & ~ALUResult[0] & IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & ~IR[26]);
assign Write_strb[1] = (IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & IR[26]) | (~ALUResult[1] & ALUResult[0] & IR[31] & ~IR[30] & IR[29] & ~IR[28] & ~IR[27] & ~IR[26]) | (~ALUResult[1] & IR[31] & ~IR[30] & IR[29] & ~IR[28] & ~IR[27] & IR[26]) | (ALUResult[1] & IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & ~IR[26]) | (~ALUResult[1] & ALUResult[0] & IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & ~IR[26]) | (~ALUResult[1] & IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & ~IR[26]);
assign Write_strb[0] = (IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & IR[26]) | (~ALUResult[1] & ~ALUResult[0] & IR[31] & ~IR[30] & IR[29] & ~IR[28] & ~IR[27] & ~IR[26]) | (~ALUResult[1] & IR[31] & ~IR[30] & IR[29] & ~IR[28] & ~IR[27] & IR[26]) | (IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & ~IR[26]) | (~ALUResult[1] & ~ALUResult[0] & IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & ~IR[26]);
assign ALUctr[3] = (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & ~IR[3] & IR[2] & IR[1] & IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & ~IR[3] & IR[2] & ~IR[1] & ~IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & ~IR[3] & IR[2] & IR[1] & IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & ~IR[3] & IR[2] & IR[1] & ~IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & ~IR[3] & IR[2] & IR[1] & ~IR[0]) | (~IR[31] & ~IR[30] & IR[29] & IR[28] & IR[27] & ~IR[26]);
assign ALUctr[2] = (~IR[31] & ~IR[30] & ~IR[29] & IR[28] & ~IR[27] & IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & IR[28] & ~IR[27] & ~IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & IR[3] & ~IR[2] & IR[1] & ~IR[0]) | (~IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & ~IR[26]) | (~IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & ~IR[3] & ~IR[2] & IR[1] & IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & IR[26] & ~IR[20] & ~IR[19] & ~IR[18] & ~IR[17] & IR[16]) | (~IR[31] & ~IR[30] & ~IR[29] & IR[28] & IR[27] & ~IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & IR[26] & ~IR[20] & ~IR[19] & ~IR[18] & ~IR[17] & ~IR[16]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & IR[3] & ~IR[2] & IR[1] & IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & IR[3] & ~IR[2] & IR[1] & ~IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & IR[3] & ~IR[2] & IR[1] & IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & ~IR[3] & IR[2] & IR[1] & IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & ~IR[3] & IR[2] & IR[1] & ~IR[0]) | (~IR[31] & ~IR[30] & IR[29] & IR[28] & IR[27] & ~IR[26]) | (IR[31:26] == 6'b000111);
assign ALUctr[1] = (~IR[31] & ~IR[30] & IR[29] & ~IR[28] & ~IR[27] & IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & IR[27] & IR[26]) | (IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & IR[28] & ~IR[27] & IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & ~IR[3] & ~IR[2] & ~IR[1] & IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & IR[28] & ~IR[27] & ~IR[26]) | (~IR[31] & ~IR[30] & IR[29] & IR[28] & IR[27] & IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & IR[3] & ~IR[2] & IR[1] & ~IR[0]) | (~IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & ~IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & ~IR[3] & ~IR[2] & IR[1] & IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & IR[26] & ~IR[20] & ~IR[19] & ~IR[18] & ~IR[17] & IR[16]) | (~IR[31] & ~IR[30] & ~IR[29] & IR[28] & IR[27] & ~IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & IR[26] & ~IR[20] & ~IR[19] & ~IR[18] & ~IR[17] & ~IR[16]) | (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & IR[28] & ~IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & IR[28] & ~IR[27] & IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & ~IR[29] & IR[28] & IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & IR[29] & ~IR[28] & ~IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & IR[29] & ~IR[28] & ~IR[27] & IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & ~IR[3] & IR[2] & IR[1] & ~IR[0]) | (IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & ~IR[26]) | (IR[31] & ~IR[30] & IR[29] & IR[28] & IR[27] & ~IR[26]) | (IR[31:26] == 6'b000111);
assign ALUctr[0] = (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & ~IR[3] & IR[2] & ~IR[1] & IR[0]) | (~IR[31] & ~IR[30] & IR[29] & IR[28] & IR[27] & IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & IR[3] & ~IR[2] & IR[1] & ~IR[0]) | (~IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & ~IR[26]) | (~IR[31] & ~IR[30] & IR[29] & ~IR[28] & IR[27] & IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & IR[26] & ~IR[20] & ~IR[19] & ~IR[18] & ~IR[17] & IR[16]) | (~IR[31] & ~IR[30] & ~IR[29] & IR[28] & IR[27] & ~IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & IR[26] & ~IR[20] & ~IR[19] & ~IR[18] & ~IR[17] & ~IR[16]) | (~IR[31] & ~IR[30] & IR[29] & IR[28] & ~IR[27] & IR[26]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & ~IR[5] & ~IR[4] & ~IR[3] & IR[2] & ~IR[1] & ~IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & IR[3] & ~IR[2] & IR[1] & IR[0]) | (~IR[31] & ~IR[30] & ~IR[29] & ~IR[28] & ~IR[27] & ~IR[26] & IR[5] & ~IR[4] & ~IR[3] & IR[2] & IR[1] & ~IR[0]) | (~IR[31] & ~IR[30] & IR[29] & IR[28] & IR[27] & ~IR[26]) | (IR[31:26] == 6'b000111);
6'b001010://slti
begin
RegDst <= 0;
ALUSrc <= 1;
Branch <= 0;
RegWrite <= 0;
RegRead <= 1;
MemtoReg <= 0;
//MemRead <= 0;
//MemWrite <= 0;
Write_strb <= 4'd0;
ALUcon_in <= 3'b010;
Jump <= 0;
JumpReg <= 0;
JAL <= 0;
LUI <= 0;
SL <= 0;
s <= 0;
Sign <= 1;
BEQ <= 0;
BGEZ <= 0;
BGTZ <= 0;
BLEZ <= 0;
BLTZ <= 0;
Logic <= 0;
Left <= 0;
JALR <= 0;
Align <= 0;
Part_data <= 32'd0;
end
6'b001011://sltiu
begin
RegDst <= 0;
ALUSrc <= 1;
Branch <= 0;
RegWrite <= 0;
RegRead <= 1;
MemtoReg <= 0;
//MemRead <= 0;
//MemWrite <= 0;
Write_strb <= 4'd0;
ALUcon_in <= 3'b011;
Jump <= 0;
JumpReg <= 0;
JAL <= 0;
LUI <= 0;
SL <= 0;
s <= 0;
Sign <= 0;
BEQ <= 0;
BGEZ <= 0;
BGTZ <= 0;
BLEZ <= 0;
BLTZ <= 0;
Logic <= 0;
Left <= 0;
JALR <= 0;
Align <= 0;
Part_data <= 32'd0;
end
类似的代码有1500行
如何拥抱变化
灵魂拷问
正确的代码 != 好代码
好代码的两条重要准则
使用正确的编程模式写出好代码
assert
检查非预期行为分析: 译码器的本质是查找表
需求: 如何 “低熵”地实现一张表?
我们需要寻找合适的语言特性来实现一张表
太难了 😂
我们提供一个键值选择模板muxkey-template.v, 可以像真值表一样查询
module mux41(a,s,y);
input [3:0] a;
input [1:0] s;
output y;
// 通过MuxKeyWithDefault实现如下always代码
// always @(*) begin
// case (s)
// 2'b00: y = a[0];
// 2'b01: y = a[1];
// 2'b10: y = a[2];
// 2'b11: y = a[3];
// default: y = 1'b0;
// endcase
// end
MuxKeyWithDefault #(4, 2, 1) i0 (y, s, 1'b0, {
2'b00, a[0],
2'b01, a[1],
2'b10, a[2],
2'b11, a[3]
});
endmodule
但还是有很多不完善的地方
casex
和casez
在行为建模语义上支持模糊匹配
案例: 第一届龙芯杯(2017), 南京大学一队通过excel和python脚本, 实现译码器的敏捷开发和低熵维护
借助scala的强大类型系统, 把表格嵌入到Chisel代码中
object RV64IInstr extends HasInstrType {
def ADDIW = BitPat("b???????_?????_?????_000_?????_0011011")
def SLLIW = BitPat("b0000000_?????_?????_001_?????_0011011")
def SRLIW = BitPat("b0000000_?????_?????_101_?????_0011011")
def SRAIW = BitPat("b0100000_?????_?????_101_?????_0011011")
def SLLW = BitPat("b0000000_?????_?????_001_?????_0111011")
def SRLW = BitPat("b0000000_?????_?????_101_?????_0111011")
def SRAW = BitPat("b0100000_?????_?????_101_?????_0111011")
def ADDW = BitPat("b0000000_?????_?????_000_?????_0111011")
def SUBW = BitPat("b0100000_?????_?????_000_?????_0111011")
def LWU = BitPat("b???????_?????_?????_110_?????_0000011")
def LD = BitPat("b???????_?????_?????_011_?????_0000011")
def SD = BitPat("b???????_?????_?????_011_?????_0100011")
val table = Array(
ADDIW -> List(InstrI, FuType.alu, ALUOpType.addw),
SLLIW -> List(InstrI, FuType.alu, ALUOpType.sllw),
SRLIW -> List(InstrI, FuType.alu, ALUOpType.srlw),
SRAIW -> List(InstrI, FuType.alu, ALUOpType.sraw),
SLLW -> List(InstrR, FuType.alu, ALUOpType.sllw),
SRLW -> List(InstrR, FuType.alu, ALUOpType.srlw),
SRAW -> List(InstrR, FuType.alu, ALUOpType.sraw),
ADDW -> List(InstrR, FuType.alu, ALUOpType.addw),
SUBW -> List(InstrR, FuType.alu, ALUOpType.subw),
LWU -> List(InstrI, FuType.lsu, LSUOpType.lwu),
LD -> List(InstrI, FuType.lsu, LSUOpType.ld ),
SD -> List(InstrS, FuType.lsu, LSUOpType.sd)
)
}
用法和ListLookup几乎相同, 但有额外好处
核心思想: 借助工具生成精准的电路描述, 将不确定的综合器行为前移到设计阶段
方案 | 容易维护 | 综合精确 |
---|---|---|
逻辑表达式 | ✖️✖️ | ✔️✔️ |
case语句 | ✖️ | ✖️ |
excel + python | ✔️✔️ | ✖️ |
Chisel ListLookup | ✔️✔️ | ✔️ |
Chisel Decoder | ✔️✔️ | ✔️✔️ |
一份参考代码
module barrelShifter(Ip, Op, shift_mag);
input [7:0] Ip; //The 8-bit Input line
output [7:0] Op; //The 8-bit Output line
input [2:0] shift_mag; //The 3-bit shift magnitude selection Input
wire [7:0] ST1,ST2; //Two 8-bit intermediate lines
//the barrel shifter implemented as array of MUX shown in the figure
mux_2to1 m0 (1'b0, Ip[0], ST1[0], shift_mag[0]);
mux_2to1 m1 (Ip[0], Ip[1], ST1[1], shift_mag[0]);
mux_2to1 m2 (Ip[1], Ip[2], ST1[2], shift_mag[0]);
mux_2to1 m3 (Ip[2], Ip[3], ST1[3], shift_mag[0]);
mux_2to1 m4 (Ip[3], Ip[4], ST1[4], shift_mag[0]);
mux_2to1 m5 (Ip[4], Ip[5], ST1[5], shift_mag[0]);
mux_2to1 m6 (Ip[5], Ip[6], ST1[6], shift_mag[0]);
mux_2to1 m7 (Ip[6], Ip[7], ST1[7], shift_mag[0]);
mux_2to1 m00 (1'b0 , ST1[0], ST2[0], shift_mag[1]);
mux_2to1 m11 (1'b0 , ST1[1], ST2[1], shift_mag[1]);
mux_2to1 m22 (ST1[0], ST1[2], ST2[2], shift_mag[1]);
mux_2to1 m33 (ST1[1], ST1[3], ST2[3], shift_mag[1]);
mux_2to1 m44 (ST1[2], ST1[4], ST2[4], shift_mag[1]);
mux_2to1 m55 (ST1[3], ST1[5], ST2[5], shift_mag[1]);
mux_2to1 m66 (ST1[4], ST1[6], ST2[6], shift_mag[1]);
mux_2to1 m77 (ST1[5], ST1[7], ST2[7], shift_mag[1]);
mux_2to1 m000 (1'b0 , ST2[0], Op[0], shift_mag[2]);
mux_2to1 m111 (1'b0 , ST2[1], Op[1], shift_mag[2]);
mux_2to1 m222 (1'b0 , ST2[2], Op[2], shift_mag[2]);
mux_2to1 m333 (1'b0 , ST2[3], Op[3], shift_mag[2]);
mux_2to1 m444 (ST2[0], ST2[4], Op[4], shift_mag[2]);
mux_2to1 m555 (ST2[1], ST2[5], Op[5], shift_mag[2]);
mux_2to1 m666 (ST2[2], ST2[6], Op[6], shift_mag[2]);
mux_2to1 m777 (ST2[3], ST2[7], Op[7], shift_mag[2]);
endmodule
RV32的字长是32位, 怎么办?
通过递归10行核心代码实现参数化桶形移位器
class BarrelShift(w: Int) extends Module {
val io = new Bundle {
val in = Input(UInt(w.W))
val shamt = Input(UInt(log2Up(w).W))
val isLeft = Input(Bool())
val isArith = Input(Bool())
val out = Output(UInt(w.W))
}
val leftIn = Mux(io.isArith, io.in(w-1), false.B) // 右移时从左边移入的位
def layer(din: Seq[Bool], n: Int): Seq[Bool] = { // 描述第n级选择器如何排布
val s = 1 << n // 需要移动的位数
def shiftRight(i: Int) = if (i + s >= w) leftIn else din(i + s) // 描述右移时第i位输出
def shiftLeft (i: Int) = if (i < s) false.B else din(i - s) // 描述左移时第i位输出
val sel = Cat(io.isLeft, io.shamt(n)) // 将移位方向和移位量作为选择器的选择信号
din.zipWithIndex.map{ case (b, i) => // 对于每一位输入b,
VecInit(b, shiftRight(i), b, shiftLeft(i))(sel) } // 都从4种输入中选择一种作为输出
}
def barrelshift(din: Seq[Bool], k: Int): Seq[Bool] = // 描述有k级的桶形移位器如何排布
if (k == 0) din // 若移位器只有0级, 则结果和输入相同
// 否则实例化一个有k-1级的桶形移位器和第k-1级选择器, 并将后者的输出作为前者的输入
else barrelshift(layer(din, k - 1), k - 1)
io.out := Cat(barrelshift(io.in.asBools, log2Up(w)).reverse) // 实例化一个有log2(w)级的桶形移位器
}
只需传入不同的w
参数,
即可生成不同数据位宽的桶形移位器
核心思想: 将桶形移位器如何排布和连接的规律抽象成算法
核心思想: 将桶形移位器如何排布和连接的规律抽象成算法
关键是谁来执行这个算法
传统流程也可以使用perl/tcl等脚本编写这个算法来生成RTL代码