chisel¶
Hardware compiler framework and hardware design language developed at UC Berkeley
现状¶
- 官方实现了Rocket Chip 及 BOOM 两款 CPU
- SiFive的芯片使用Chisel编写
- 中科院计算所的香山处理器使用shisel编写
特点¶
- Open-Source
- Highly parameterized
- Based on Scala
- Re-usable components and libraries
- FIRRTL (Flexible Intermediate Representation for RTL)
- The ability to create generators
- Design verification support iotesters(peek, poke, expect) and testers2(fork, join)
- Can in-line verilog
从chisel官方网站名称是不是能够看出来它更像是一个硬件编译器框架? lang让人联想到clang,进而想到llvm,FIRRTL从设计上和LLVM很像。
与verilog的对比¶
对比项 | verilog | chisel |
---|---|---|
HDL | 是 | HDL,非HLS 1 |
代码简洁性 | 非常啰嗦,可读性和可维护性都比较差 | 代码简洁,符合软件思维 |
编译检查 | 从不进行检查,编译器没有基本的逻辑判断能力 | 功能强大的错误检查和自动推断能力 |
是否可综合 | 可综合,具有唯一性 | 可综合,具有唯一性 |
重用性 | 较差的可重用性,很难拿来直接怼 | 高度的参数化支持,很容易复用 |
成熟度 | 非常成熟 | 仍需要较长时间的发展 |
模块测试难度 | 测试代码可能要比设计代码还要复杂 | 自带的tester编写方便,语法高级 |
前景¶
Verilog,SystemVerilog,SystemC,Chisel,HLS 谁们才是未来?
学习路线¶
官方教程 官方网站 chisel工程模板 API手册 速记手册下载链接
根据官方训练营,一步步的学习,自己动手敲一敲,做一些简单测试,然后就可以在读Rocket Chip代码的同时不断的进行提高
环境搭建¶
chisel官方提供了chisel-bootcamp, 一个chisel教程。这是一个很好的参考,它为了专注于chisel本身,把环境搭建给做好了,这里建议采取:自己搭建环境 + bootcamp例程的学习方法
环境搭建要点:
- chisel依赖于sbt和scala,因此,提前搭建好scala运行环境
- chisel不需要单独进行安装,sbt能够自动获取托管依赖
- 下载一个chisel的repo模板会是非常省事的环境搭建方法
下面是shisel-template的简要目录结构,sbt要求放置文件必须按照一定的目录结构放置,很多现代构建工具都有这样类似的要求 其中:
- build.sbt :存放了绝大多数构建规则(主流用法),主要是构建对象以及依赖的包,chisel包就在这里面进行说明
- build.sc :目前还未完全弄清
- src : 根据sbt规则,默认构建对象存放的目录就是src,src目录下必须有一个mian/scala目录,源文件放在这个目录下
- src/test : test目录,测试代码应该放在这个目录的scala子目录下,这样就可以使用iotester和tester2进行单元测试了
- test_run_dir : 运行时可能生成此目录,生成的VCD波形文件就在这个目录下,这是tester的功能
- project : sbt 使用
.
├── build.sbt
├── build.sc
├── LICENSE
├── project
├── src
│ ├── main
│ │ └── scala
│ │ └── demo.scala
│ └── test
│ └── scala
│ └── BaseTest.scala
├── target
└── test_run_dir
chisel语法要点¶
时刻注意,chisel是强类型语言,类型不匹配在编译时会报错,要熟知使用的对象的类型。 下面的语法要点是对官方教程进行了总结,但**熟悉chisel基础语法最好的方式是按照官方教程进行学习**
数据类型¶
chisel有着严格的数据类型,它用于构建逻辑电路的数据类型和scala是严格区分的。同时,因为是生成硬件电路,因此,所有的数据都应该是val而不是var
如下是常用数据类型,其中.U .S .B是常见的三种数据类型
1.U // decimal 1-bit lit from Scala Int.
"ha".U // hexadecimal 4-bit lit from string.
"o12".U // octal 4-bit lit from string.
"b1010".U // binary 4-bit lit from string.
5.S // signed decimal 4-bit lit from Scala Int.
-8.S // negative decimal 4-bit lit from Scala Int.
5.U // unsigned decimal 3-bit lit from Scala Int.
8.U(4.W) // 4-bit unsigned decimal, value 8.
-152.S(32.W) // 32-bit signed decimal, value -152.
true.B // Bool lits from Scala lits.
false.B
下划线可以用来增加可读性,并没有实际意义
"h_dead_beef".U // 32-bit lit of type UInt
.W用来指定宽度。如果不指定,那么自动的会用最少的bits。如果指定的位宽大于实际需要的位宽,UInt会进行0扩展,SInt会进行符号扩展;如果小于,编译会报错。
Vecs 也是数据类型(这样就能理解为什么写做Reg(Vec(4, UInt(4.W))))
Analog 就等于inout,双向线
chisel中有很多class都可以不用new来实例化,因为有些使用了case class, 有一些已经实现了object的apply方法
Bundles¶
bundle是一个值的集合,可以认为是struct
Flipped()可以用来翻转Bundle,这样就非常方便的构建双向接口
class ABBundle extends Bundle {
val a = Input(Bool())
val b = Output(Bool())
}
class MyFlippedModule extends RawModule {
// Normal instantiation of the bundle
// 'a' is an Input and 'b' is an Output
val normalBundle = IO(new ABBundle)
normalBundle.b := normalBundle.a
// Flipped recursively flips the direction of all Bundle fields
// Now 'a' is an Output and 'b' is an Input
val flippedBundle = IO(Flipped(new ABBundle))
flippedBundle.a := flippedBundle.b
}
rocket-chip中的flip的使用,其中flip就是Flipped(target),这样就能定义接口就好了,对于输出模块和输出模块,他们的信号就是完全可以Flip。 其中Valid是在信号的基础上增加了Valid信号。通过这种机制,chisel编写的模块可读性更好。
class BTB(implicit p: Parameters) extends BtbModule {
val io = new Bundle {
val req = Valid(new BTBReq).flip
val resp = Valid(new BTBResp)
val btb_update = Valid(new BTBUpdate).flip
val bht_update = Valid(new BHTUpdate).flip
val bht_advance = Valid(new BTBResp).flip
val ras_update = Valid(new RASUpdate).flip
val ras_head = Valid(UInt(width = vaddrBits))
val flush = Bool().asInput
}
组合逻辑和时序逻辑¶
chisel提供了Mux,Cat,Wire等基础类型用于实现组合逻辑,提供了Reg,when, elsewhen, otherwise等来实现时序逻辑。
必须使用:=
来对Wire和Reg进行赋值, 这里使用一个没有任何意义的ALU单元来体现chisel如何实现组合逻辑和时序逻辑
class MyAlu extends Module {
val io = IO(new Bundle {
val in_src1 = Input(UInt(32.W))
val in_src2 = Input(UInt(32.W))
val in_imm2 = Input(UInt(2.W))
val output_add = Output(UInt(32.W))
val output_add_expand = Output(UInt(64.W))
val output_sub = Output(UInt(32.W))
val output_max = Output(UInt(32.W))
val output_ext = Output(UInt(32.W))
})
io.output_add := io.in_src1 + io.in_src2
io.output_sub := io.in_src1 - io.in_src2
io.output_add_expand := io.in_src1 +& io.in_src2
val to_max = Wire(UInt(32.W))
when (io.in_src1 < io.in_src2) {
to_max := io.in_src2
} .otherwise {
to_max := io.in_src1
}
io.output_max := to_max
val ext_reg = RegInit(UInt(32.W), 0.U)
switch (io.in_imm2) {
is(0.U) {
ext_reg := io.in_src1
}
is(1.U) {
ext_reg := Cat(io.in_src1(31, 1), 0.U(1.W))
}
is(2.U) {
ext_reg := Cat(io.in_src1(31, 2), 0.U(2.W))
}
is(3.U) {
ext_reg := Cat(io.in_src1(31, 3), 0.U(3.W))
}
}
io.output_ext := ext_reg
}
生成的verilog代码如下
module MyAlu(
input clock,
input reset,
input [31:0] io_in_src1,
input [31:0] io_in_src2,
input [1:0] io_in_imm2,
output [31:0] io_output_add,
output [63:0] io_output_add_expand,
output [31:0] io_output_sub,
output [31:0] io_output_max,
output [31:0] io_output_ext
);
wire [32:0] _io_output_add_T = io_in_src1 + io_in_src2; // @[demo.scala 17:31]
reg [31:0] ext_reg; // @[demo.scala 29:24]
wire _T_1 = 2'h0 == io_in_imm2; // @[Conditional.scala 37:30]
wire _T_2 = 2'h1 == io_in_imm2; // @[Conditional.scala 37:30]
wire [30:0] ext_reg_hi = io_in_src1[31:1]; // @[demo.scala 35:32]
wire [31:0] _ext_reg_T = {ext_reg_hi,1'h0}; // @[Cat.scala 30:58]
wire _T_3 = 2'h2 == io_in_imm2; // @[Conditional.scala 37:30]
wire [29:0] ext_reg_hi_1 = io_in_src1[31:2]; // @[demo.scala 38:32]
wire [31:0] _ext_reg_T_1 = {ext_reg_hi_1,2'h0}; // @[Cat.scala 30:58]
wire _T_4 = 2'h3 == io_in_imm2; // @[Conditional.scala 37:30]
wire [28:0] ext_reg_hi_2 = io_in_src1[31:3]; // @[demo.scala 41:32]
wire [31:0] _ext_reg_T_2 = {ext_reg_hi_2,3'h0}; // @[Cat.scala 30:58]
wire [31:0] _GEN_1 = _T_4 ? _ext_reg_T_2 : ext_reg; // @[Conditional.scala 39:67 demo.scala 41:15 demo.scala 29:24]
assign io_output_add = io_in_src1 + io_in_src2; // @[demo.scala 17:31]
assign io_output_add_expand = {{31'd0}, _io_output_add_T}; // @[demo.scala 19:38]
assign io_output_sub = io_in_src1 - io_in_src2; // @[demo.scala 18:31]
assign io_output_max = io_in_src1 < io_in_src2 ? io_in_src2 : io_in_src1; // @[demo.scala 22:34 demo.scala 23:12 demo.scala 25:12]
assign io_output_ext = ext_reg; // @[demo.scala 44:17]
always @(posedge clock) begin
if (reset) begin // @[demo.scala 29:24]
ext_reg <= 32'h0; // @[demo.scala 29:24]
end else if (_T_1) begin // @[Conditional.scala 40:58]
ext_reg <= io_in_src1; // @[demo.scala 32:15]
end else if (_T_2) begin // @[Conditional.scala 39:67]
ext_reg <= _ext_reg_T; // @[demo.scala 35:15]
end else if (_T_3) begin // @[Conditional.scala 39:67]
ext_reg <= _ext_reg_T_1; // @[demo.scala 38:15]
end else begin
ext_reg <= _GEN_1;
end
end
endmodule
tester¶
一个Fir数字滤波器的简单测试方法,并支持生成VCD波形
import chisel3._
import chiseltest._
import org.scalatest._
import chiseltest.experimental.TestOptionBuilder._
import chiseltest.internal.WriteVcdAnnotation
class MySpec extends FlatSpec with ChiselScalatestTester with Matchers {
it should "get a fir" in {
test(new My4ElementFir(0, 0, 0, 0)).withAnnotations(Seq(WriteVcdAnnotation)) { c =>
c.io.in.poke(0.U)
c.io.out.expect(0.U)
c.clock.step(1)
c.io.in.poke(4.U)
c.io.out.expect(0.U)
c.clock.step(1)
c.io.in.poke(5.U)
c.io.out.expect(0.U)
c.clock.step(1)
c.io.in.poke(2.U)
c.io.out.expect(0.U)
}
}
}
chisel 支持scala的tester测试框架,同时也正在改进测试框架,名为testers2。 我们在verilog开发过程中,一些单元测试需要自己写激励文件,往往对于稍微复杂的模块,激励文件的复杂度很高,往往这部分工作有专门的RTL验证人员负责。chisel提供了一种简单的方法,适用于单元测试和系统集成测试,并尽可能使得单元测试简单方便有用
讨论:至少在单元自测试方面,Testers提供了一个非常方便的方法来进行简单自验证。Testers2在使用chisel进行IC开发的过程中扮演着怎样的角色?Testes是否能够替代现有的测试手段?
生成器¶
所谓的生成器就是指模块的参数化,这是chisel真正强大的地方,也是精髓所在。单看上面时序逻辑和组合逻辑的例子,你不会感觉到chisel的强大,只有在接触了生成器之后,才能真正的体会到的它的高效。这也是为什么chisel开发过程中讲究敏捷。
语法要点:
- Option
- match,case
- Implicits隐含参数,隐式转换(这种方法比较难读,不建议使用)
- 容器
- mutable.ArrayBuffer
- Vec(仅在普通Scala容器用不了的情况下使用)
举例:如下是一个简单的寄存器文件实现,可以通过参数指定读端口的数量
class RegisterFile(readPorts: Int) extends Module {
require(readPorts >= 0)
val io = IO(new Bundle {
val wen = Input(Bool())
val waddr = Input(UInt(5.W))
val wdata = Input(UInt(32.W))
val raddr = Input(Vec(readPorts, UInt(5.W)))
val rdata = Output(Vec(readPorts, UInt(32.W)))
})
val reg = RegInit(VecInit(Seq.fill(32)(0.U(32.W))))
when (io.wen) {
reg(io.waddr) := io.wdata
}
for (i <- 0 until readPorts) {
when (io.raddr(i) === 0.U) {
io.rdata(i) := 0.U
} .otherwise {
io.rdata(i) := reg(io.raddr(i))
}
}
}
生成的verilog如下,例化的readPorts数量为3
module RegisterFile(
input clock,
input reset,
input io_wen,
input [4:0] io_waddr,
input [31:0] io_wdata,
input [4:0] io_raddr_0,
input [4:0] io_raddr_1,
input [4:0] io_raddr_2,
output [31:0] io_rdata_0,
output [31:0] io_rdata_1,
output [31:0] io_rdata_2
);
reg [31:0] reg_0; // @[demo.scala 165:22]
reg [31:0] reg_1; // @[demo.scala 165:22]
reg [31:0] reg_2; // @[demo.scala 165:22]
reg [31:0] reg_3; // @[demo.scala 165:22]
reg [31:0] reg_4; // @[demo.scala 165:22]
reg [31:0] reg_5; // @[demo.scala 165:22]
reg [31:0] reg_6; // @[demo.scala 165:22]
reg [31:0] reg_7; // @[demo.scala 165:22]
reg [31:0] reg_8; // @[demo.scala 165:22]
reg [31:0] reg_9; // @[demo.scala 165:22]
reg [31:0] reg_10; // @[demo.scala 165:22]
reg [31:0] reg_11; // @[demo.scala 165:22]
reg [31:0] reg_12; // @[demo.scala 165:22]
reg [31:0] reg_13; // @[demo.scala 165:22]
reg [31:0] reg_14; // @[demo.scala 165:22]
reg [31:0] reg_15; // @[demo.scala 165:22]
reg [31:0] reg_16; // @[demo.scala 165:22]
reg [31:0] reg_17; // @[demo.scala 165:22]
reg [31:0] reg_18; // @[demo.scala 165:22]
reg [31:0] reg_19; // @[demo.scala 165:22]
reg [31:0] reg_20; // @[demo.scala 165:22]
reg [31:0] reg_21; // @[demo.scala 165:22]
reg [31:0] reg_22; // @[demo.scala 165:22]
reg [31:0] reg_23; // @[demo.scala 165:22]
reg [31:0] reg_24; // @[demo.scala 165:22]
reg [31:0] reg_25; // @[demo.scala 165:22]
reg [31:0] reg_26; // @[demo.scala 165:22]
reg [31:0] reg_27; // @[demo.scala 165:22]
reg [31:0] reg_28; // @[demo.scala 165:22]
reg [31:0] reg_29; // @[demo.scala 165:22]
reg [31:0] reg_30; // @[demo.scala 165:22]
reg [31:0] reg_31; // @[demo.scala 165:22]
wire [31:0] _GEN_65 = 5'h1 == io_raddr_0 ? reg_1 : reg_0; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_66 = 5'h2 == io_raddr_0 ? reg_2 : _GEN_65; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_67 = 5'h3 == io_raddr_0 ? reg_3 : _GEN_66; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_68 = 5'h4 == io_raddr_0 ? reg_4 : _GEN_67; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_69 = 5'h5 == io_raddr_0 ? reg_5 : _GEN_68; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_70 = 5'h6 == io_raddr_0 ? reg_6 : _GEN_69; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_71 = 5'h7 == io_raddr_0 ? reg_7 : _GEN_70; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_72 = 5'h8 == io_raddr_0 ? reg_8 : _GEN_71; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_73 = 5'h9 == io_raddr_0 ? reg_9 : _GEN_72; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_74 = 5'ha == io_raddr_0 ? reg_10 : _GEN_73; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_75 = 5'hb == io_raddr_0 ? reg_11 : _GEN_74; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_76 = 5'hc == io_raddr_0 ? reg_12 : _GEN_75; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_77 = 5'hd == io_raddr_0 ? reg_13 : _GEN_76; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_78 = 5'he == io_raddr_0 ? reg_14 : _GEN_77; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_79 = 5'hf == io_raddr_0 ? reg_15 : _GEN_78; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_80 = 5'h10 == io_raddr_0 ? reg_16 : _GEN_79; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_81 = 5'h11 == io_raddr_0 ? reg_17 : _GEN_80; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_82 = 5'h12 == io_raddr_0 ? reg_18 : _GEN_81; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_83 = 5'h13 == io_raddr_0 ? reg_19 : _GEN_82; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_84 = 5'h14 == io_raddr_0 ? reg_20 : _GEN_83; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_85 = 5'h15 == io_raddr_0 ? reg_21 : _GEN_84; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_86 = 5'h16 == io_raddr_0 ? reg_22 : _GEN_85; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_87 = 5'h17 == io_raddr_0 ? reg_23 : _GEN_86; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_88 = 5'h18 == io_raddr_0 ? reg_24 : _GEN_87; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_89 = 5'h19 == io_raddr_0 ? reg_25 : _GEN_88; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_90 = 5'h1a == io_raddr_0 ? reg_26 : _GEN_89; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_91 = 5'h1b == io_raddr_0 ? reg_27 : _GEN_90; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_92 = 5'h1c == io_raddr_0 ? reg_28 : _GEN_91; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_93 = 5'h1d == io_raddr_0 ? reg_29 : _GEN_92; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_94 = 5'h1e == io_raddr_0 ? reg_30 : _GEN_93; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_95 = 5'h1f == io_raddr_0 ? reg_31 : _GEN_94; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_98 = 5'h1 == io_raddr_1 ? reg_1 : reg_0; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_99 = 5'h2 == io_raddr_1 ? reg_2 : _GEN_98; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_100 = 5'h3 == io_raddr_1 ? reg_3 : _GEN_99; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_101 = 5'h4 == io_raddr_1 ? reg_4 : _GEN_100; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_102 = 5'h5 == io_raddr_1 ? reg_5 : _GEN_101; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_103 = 5'h6 == io_raddr_1 ? reg_6 : _GEN_102; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_104 = 5'h7 == io_raddr_1 ? reg_7 : _GEN_103; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_105 = 5'h8 == io_raddr_1 ? reg_8 : _GEN_104; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_106 = 5'h9 == io_raddr_1 ? reg_9 : _GEN_105; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_107 = 5'ha == io_raddr_1 ? reg_10 : _GEN_106; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_108 = 5'hb == io_raddr_1 ? reg_11 : _GEN_107; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_109 = 5'hc == io_raddr_1 ? reg_12 : _GEN_108; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_110 = 5'hd == io_raddr_1 ? reg_13 : _GEN_109; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_111 = 5'he == io_raddr_1 ? reg_14 : _GEN_110; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_112 = 5'hf == io_raddr_1 ? reg_15 : _GEN_111; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_113 = 5'h10 == io_raddr_1 ? reg_16 : _GEN_112; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_114 = 5'h11 == io_raddr_1 ? reg_17 : _GEN_113; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_115 = 5'h12 == io_raddr_1 ? reg_18 : _GEN_114; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_116 = 5'h13 == io_raddr_1 ? reg_19 : _GEN_115; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_117 = 5'h14 == io_raddr_1 ? reg_20 : _GEN_116; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_118 = 5'h15 == io_raddr_1 ? reg_21 : _GEN_117; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_119 = 5'h16 == io_raddr_1 ? reg_22 : _GEN_118; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_120 = 5'h17 == io_raddr_1 ? reg_23 : _GEN_119; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_121 = 5'h18 == io_raddr_1 ? reg_24 : _GEN_120; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_122 = 5'h19 == io_raddr_1 ? reg_25 : _GEN_121; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_123 = 5'h1a == io_raddr_1 ? reg_26 : _GEN_122; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_124 = 5'h1b == io_raddr_1 ? reg_27 : _GEN_123; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_125 = 5'h1c == io_raddr_1 ? reg_28 : _GEN_124; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_126 = 5'h1d == io_raddr_1 ? reg_29 : _GEN_125; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_127 = 5'h1e == io_raddr_1 ? reg_30 : _GEN_126; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_128 = 5'h1f == io_raddr_1 ? reg_31 : _GEN_127; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_131 = 5'h1 == io_raddr_2 ? reg_1 : reg_0; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_132 = 5'h2 == io_raddr_2 ? reg_2 : _GEN_131; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_133 = 5'h3 == io_raddr_2 ? reg_3 : _GEN_132; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_134 = 5'h4 == io_raddr_2 ? reg_4 : _GEN_133; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_135 = 5'h5 == io_raddr_2 ? reg_5 : _GEN_134; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_136 = 5'h6 == io_raddr_2 ? reg_6 : _GEN_135; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_137 = 5'h7 == io_raddr_2 ? reg_7 : _GEN_136; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_138 = 5'h8 == io_raddr_2 ? reg_8 : _GEN_137; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_139 = 5'h9 == io_raddr_2 ? reg_9 : _GEN_138; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_140 = 5'ha == io_raddr_2 ? reg_10 : _GEN_139; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_141 = 5'hb == io_raddr_2 ? reg_11 : _GEN_140; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_142 = 5'hc == io_raddr_2 ? reg_12 : _GEN_141; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_143 = 5'hd == io_raddr_2 ? reg_13 : _GEN_142; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_144 = 5'he == io_raddr_2 ? reg_14 : _GEN_143; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_145 = 5'hf == io_raddr_2 ? reg_15 : _GEN_144; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_146 = 5'h10 == io_raddr_2 ? reg_16 : _GEN_145; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_147 = 5'h11 == io_raddr_2 ? reg_17 : _GEN_146; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_148 = 5'h12 == io_raddr_2 ? reg_18 : _GEN_147; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_149 = 5'h13 == io_raddr_2 ? reg_19 : _GEN_148; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_150 = 5'h14 == io_raddr_2 ? reg_20 : _GEN_149; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_151 = 5'h15 == io_raddr_2 ? reg_21 : _GEN_150; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_152 = 5'h16 == io_raddr_2 ? reg_22 : _GEN_151; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_153 = 5'h17 == io_raddr_2 ? reg_23 : _GEN_152; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_154 = 5'h18 == io_raddr_2 ? reg_24 : _GEN_153; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_155 = 5'h19 == io_raddr_2 ? reg_25 : _GEN_154; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_156 = 5'h1a == io_raddr_2 ? reg_26 : _GEN_155; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_157 = 5'h1b == io_raddr_2 ? reg_27 : _GEN_156; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_158 = 5'h1c == io_raddr_2 ? reg_28 : _GEN_157; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_159 = 5'h1d == io_raddr_2 ? reg_29 : _GEN_158; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_160 = 5'h1e == io_raddr_2 ? reg_30 : _GEN_159; // @[demo.scala 175:25 demo.scala 175:25]
wire [31:0] _GEN_161 = 5'h1f == io_raddr_2 ? reg_31 : _GEN_160; // @[demo.scala 175:25 demo.scala 175:25]
assign io_rdata_0 = io_raddr_0 == 5'h0 ? 32'h0 : _GEN_95; // @[demo.scala 172:36 demo.scala 173:25 demo.scala 175:25]
assign io_rdata_1 = io_raddr_1 == 5'h0 ? 32'h0 : _GEN_128; // @[demo.scala 172:36 demo.scala 173:25 demo.scala 175:25]
assign io_rdata_2 = io_raddr_2 == 5'h0 ? 32'h0 : _GEN_161; // @[demo.scala 172:36 demo.scala 173:25 demo.scala 175:25]
always @(posedge clock) begin
if (reset) begin // @[demo.scala 165:22]
reg_0 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h0 == io_waddr) begin // @[demo.scala 168:23]
reg_0 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_1 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h1 == io_waddr) begin // @[demo.scala 168:23]
reg_1 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_2 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h2 == io_waddr) begin // @[demo.scala 168:23]
reg_2 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_3 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h3 == io_waddr) begin // @[demo.scala 168:23]
reg_3 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_4 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h4 == io_waddr) begin // @[demo.scala 168:23]
reg_4 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_5 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h5 == io_waddr) begin // @[demo.scala 168:23]
reg_5 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_6 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h6 == io_waddr) begin // @[demo.scala 168:23]
reg_6 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_7 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h7 == io_waddr) begin // @[demo.scala 168:23]
reg_7 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_8 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h8 == io_waddr) begin // @[demo.scala 168:23]
reg_8 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_9 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h9 == io_waddr) begin // @[demo.scala 168:23]
reg_9 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_10 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'ha == io_waddr) begin // @[demo.scala 168:23]
reg_10 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_11 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'hb == io_waddr) begin // @[demo.scala 168:23]
reg_11 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_12 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'hc == io_waddr) begin // @[demo.scala 168:23]
reg_12 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_13 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'hd == io_waddr) begin // @[demo.scala 168:23]
reg_13 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_14 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'he == io_waddr) begin // @[demo.scala 168:23]
reg_14 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_15 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'hf == io_waddr) begin // @[demo.scala 168:23]
reg_15 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_16 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h10 == io_waddr) begin // @[demo.scala 168:23]
reg_16 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_17 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h11 == io_waddr) begin // @[demo.scala 168:23]
reg_17 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_18 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h12 == io_waddr) begin // @[demo.scala 168:23]
reg_18 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_19 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h13 == io_waddr) begin // @[demo.scala 168:23]
reg_19 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_20 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h14 == io_waddr) begin // @[demo.scala 168:23]
reg_20 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_21 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h15 == io_waddr) begin // @[demo.scala 168:23]
reg_21 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_22 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h16 == io_waddr) begin // @[demo.scala 168:23]
reg_22 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_23 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h17 == io_waddr) begin // @[demo.scala 168:23]
reg_23 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_24 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h18 == io_waddr) begin // @[demo.scala 168:23]
reg_24 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_25 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h19 == io_waddr) begin // @[demo.scala 168:23]
reg_25 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_26 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h1a == io_waddr) begin // @[demo.scala 168:23]
reg_26 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_27 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h1b == io_waddr) begin // @[demo.scala 168:23]
reg_27 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_28 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h1c == io_waddr) begin // @[demo.scala 168:23]
reg_28 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_29 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h1d == io_waddr) begin // @[demo.scala 168:23]
reg_29 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_30 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h1e == io_waddr) begin // @[demo.scala 168:23]
reg_30 <= io_wdata; // @[demo.scala 168:23]
end
end
if (reset) begin // @[demo.scala 165:22]
reg_31 <= 32'h0; // @[demo.scala 165:22]
end else if (io_wen) begin // @[demo.scala 167:19]
if (5'h1f == io_waddr) begin // @[demo.scala 168:23]
reg_31 <= io_wdata; // @[demo.scala 168:23]
end
end
end
endmodule
-
HLS 高级综合(high-level synthesis) 能自动把 C/C++ 之类的高级语言转化成 Verilog/VHDL 之类的底层硬件描述语言(RTL), 例如:vivado HLS, Intel HLS compiler, Mentor Catapult HLS, Cadence Stratus HLS, Synopsys C。据说2003年,一位博士生挑战了已经卡壳20年的HLS领域,成功把非时序的代码时序硬件化。他和老师一起创办了AutoESL,做C自动转换RTL。2011年被Xilinx收购,诞生了Xilinx Vivado HLS ↩