# 【3】Generators
contributed by AgainTW
---
# 章節
* [【1】Scala 和 Chisel 語法簡記](https://hackmd.io/@nfUUgsYRTGy81y5d9AYOyg/BJdW9obUa)
* [【2】組合電路、序向電路和 Control Flow](https://hackmd.io/@nfUUgsYRTGy81y5d9AYOyg/HyWJBxmUa)
* [【3】Generators](https://hackmd.io/@nfUUgsYRTGy81y5d9AYOyg/SJZ7kz7L6)
* [【4】高階函式與設計](https://hackmd.io/@nfUUgsYRTGy81y5d9AYOyg/rk0Ckf7Lp)
* [【5】物件導向設計](https://hackmd.io/@nfUUgsYRTGy81y5d9AYOyg/B1hB1aTLT)
* [【6】Generators: Types](https://hackmd.io/@nfUUgsYRTGy81y5d9AYOyg/SJ8tka6U6)
* [【7】FIRRTL 簡介](https://hackmd.io/@nfUUgsYRTGy81y5d9AYOyg/HJOjkppIT)
* [【8】Chisel 到 Verilog 的中間表示](https://hackmd.io/@nfUUgsYRTGy81y5d9AYOyg/r1URy6aIT)
---
# Outline
1. Chisel 生成器如何取得其參數
2. Chisel 的條件分支
3. Implicits
4. Collections
5. 範例3: Mealy machine
---
# 隨筆
* 位寬為零的 IO 會從產生的 Verilog 中修剪掉
* Scala Map() 的錯誤使用法:
* 錯誤的索引呼叫
* 但使用 .get() 在錯誤呼叫時則會回傳 None
```scala=
// 錯誤
val map = Map("a" -> 1)
val a = map("a")
println(a)
val b = map("b")
println(b)
// 使用 .get()
val map = Map("a" -> 1)
val a = map.get("a")
println(a)
val b = map.get("b")
println(b)
```
```shell
1
// 報錯
Some(1)
None
```
---
# Chisel 生成器如何取得其參數
## Scala class 取得參數的語法
```scala=
class ParameterizedScalaObject(param1: Int, param2: String) {
println(s"I have parameters: param1 = $param1 and param2 = $param2")
}
val obj1 = new ParameterizedScalaObject(4, "Hello")
val obj2 = new ParameterizedScalaObject(4 + 2, "World")
```
```shell
I have parameters: param1 = 4 and param2 = Hello
I have parameters: param1 = 6 and param2 = World
```
## Chisel module 取得參數的語法
* require(): 這些是預闡述斷言,當構造的生成器僅適用於某些參數或某些參數相互排斥或無意義時,require() 非常有用。
```scala=
class ParameterizedWidthAdder(in0Width: Int, in1Width: Int, sumWidth: Int) extends Module {
require(in0Width >= 0)
require(in1Width >= 0)
require(sumWidth >= 0)
val io = IO(new Bundle {
val in0 = Input(UInt(in0Width.W))
val in1 = Input(UInt(in1Width.W))
val sum = Output(UInt(sumWidth.W))
})
// a +& b includes the carry, a + b does not
io.sum := io.in0 +& io.in1
}
println(getVerilog(new ParameterizedWidthAdder(1, 4, 6)))
```
```mips
module ParameterizedWidthAdder(
input clock,
input reset,
input io_in0,
input [3:0] io_in1,
output [5:0] io_sum
);
wire [3:0] _GEN_0 = {{3'd0}, io_in0}; // @[cmd3.sc 11:20]
wire [4:0] _T = _GEN_0 + io_in1; // @[cmd3.sc 11:20]
assign io_sum = {{1'd0}, _T}; // @[cmd3.sc 11:20]
endmodule
```
* chisel module 的輸入可以宣告預設值,或是宣告成```None```
* .isDefined 可以判斷輸入是否不為空,回傳值為 scala 的布林值
```scala=
class DelayBy1(resetValue: Option[UInt] = None) extends Module {
val io = IO(new Bundle {
val in = Input(UInt(16.W))
val out = Output(UInt(16.W))
})
val reg = if (resetValue.isDefined) { // resetValue = Some(number)
RegInit(resetValue.get)
} else { //resetValue = None
Reg(UInt())
}
reg := io.in
io.out := reg
}
println(getVerilog(new DelayBy1))
println(getVerilog(new DelayBy1(Some(3.U))))
```
```mips
module DelayBy1(
input clock,
input reset,
input [15:0] io_in,
output [15:0] io_out
);
`ifdef RANDOMIZE_REG_INIT
reg [31:0] _RAND_0;
`endif // RANDOMIZE_REG_INIT
reg [15:0] reg_; // @[cmd8.sc 9:12]
assign io_out = reg_; // @[cmd8.sc 12:12]
always @(posedge clock) begin
reg_ <= io_in; // @[cmd8.sc 11:9]
end
endmodule
```
```mips
module DelayBy1(
input clock,
input reset,
input [15:0] io_in,
output [15:0] io_out
);
`ifdef RANDOMIZE_REG_INIT
reg [31:0] _RAND_0;
`endif // RANDOMIZE_REG_INIT
reg [15:0] reg_; // @[cmd8.sc 7:16]
assign io_out = reg_; // @[cmd8.sc 12:12]
always @(posedge clock) begin
if (reset) begin // @[cmd8.sc 7:16]
reg_ <= 16'h3; // @[cmd8.sc 7:16]
end else begin
reg_ <= io_in; // @[cmd8.sc 11:9]
end
end
endmodule
```
---
# Chisel 的條件分支
## scala 的條件分支
### 單輸入分支
```scala=
// y is an integer variable defined somewhere else in the code
val y = 7
/// ...
val x = y match {
case 0 => "zero" // One common syntax, preferred if fits in one line
case 1 => // Another common syntax, preferred if does not fit in one line.
"one" // Note the code block continues until the next case
case 2 => { // Another syntax, but curly braces are not required
"two"
}
case _ => "many" // _ is a wildcard that matches all values
}
println("y is " + x)
```
```shell
y is many
```
### 多輸入分支
```scala=
def animalType(biggerThanBreadBox: Boolean, meanAsCanBe: Boolean): String = {
(biggerThanBreadBox, meanAsCanBe) match {
case (true, true) => "wolverine"
case (true, false) => "elephant"
case (false, true) => "shrew"
case (false, false) => "puppy"
}
}
println(animalType(true, true))
```
```shell
wolverine
```
### 單類型分支
```scala=
val sequence = Seq("a", 1, 0.0)
sequence.foreach { x =>
x match {
case s: String => println(s"$x is a String")
case s: Int => println(s"$x is an Int")
case s: Double => println(s"$x is a Double")
case _ => println(s"$x is an unknown type!")
}
}
```
```shell
a is a String
1 is an Int
0.0 is a Double
```
### 多類型分支
```scala=
val sequence = Seq("a", 1, 0.0)
sequence.foreach { x =>
x match {
case _: Int | _: Double => println(s"$x is a number!")
case _ => println(s"$x is an unknown type!")
}
}
```
```shell
a is an unknown type!
1 is a number!
0.0 is a number!
```
### 分支的限制: Erasure
* 因為 Scala 運行在 JVM 上,JVM 不維護多態類型,因此會發生以下狀況
* 以下範例總是符合第一個 case 語句,因為 ```[String]```、```[Int]```和```[Double]```多態類型被刪除
* 並且 case 語句實際上僅符合 Seq
```scala=
val sequence1 = Seq(Seq("a"), Seq(1), Seq(0.0))
sequence1.foreach { x =>
x match {
case s: Seq[String] => println(s"$x is a String")
case s: Seq[Int] => println(s"$x is an Int")
case s: Seq[Double] => println(s"$x is a Double")
}
}
val sequence2 = Seq(Seq(1), Seq("a"), Seq(0.0))
sequence2.foreach { x =>
x match {
case s: Seq[String] => println(s"$x is a String")
case s: Seq[Int] => println(s"$x is an Int")
case s: Seq[Double] => println(s"$x is a Double")
}
}
val sequence3 = Seq(Seq(1), Seq("a"), Seq(0.0))
sequence3.foreach { x =>
x match {
case s: Seq[Int] => println(s"$x is an Int")
case s: Seq[String] => println(s"$x is a String")
case s: Seq[Double] => println(s"$x is a Double")
}
}
val sequence4 = Seq(Seq("a"), Seq(1), Seq(0.0))
sequence3.foreach { x =>
x match {
case s: Seq[Int] => println(s"$x is an Int")
case s: Seq[String] => println(s"$x is a String")
case s: Seq[Double] => println(s"$x is a Double")
}
}
```
```shell
List(a) is a String
List(1) is a String
List(0.0) is a String
List(1) is a String
List(a) is a String
List(0.0) is a String
List(1) is an Int
List(a) is an Int
List(0.0) is an Int
List(a) is an Int
List(1) is an Int
List(0.0) is an Int
```
## Chisel 的條件分支寫法
### 使用 match
* 我們可以得到和"Chisel module 取得參數的語法"那裡相同的結果
```scala=
class DelayBy1(resetValue: Option[UInt] = None) extends Module {
val io = IO(new Bundle {
val in = Input( UInt(16.W))
val out = Output(UInt(16.W))
})
val reg = resetValue match {
case Some(r) => RegInit(r)
case None => Reg(UInt())
}
reg := io.in
io.out := reg
}
println(getVerilog(new DelayBy1))
println(getVerilog(new DelayBy1(Some(3.U))))
```
```mips
module DelayBy1(
input clock,
input reset,
input [15:0] io_in,
output [15:0] io_out
);
`ifdef RANDOMIZE_REG_INIT
reg [31:0] _RAND_0;
`endif // RANDOMIZE_REG_INIT
reg [15:0] reg_; // @[cmd18.sc 8:24]
assign io_out = reg_; // @[cmd18.sc 11:10]
always @(posedge clock) begin
reg_ <= io_in; // @[cmd18.sc 10:7]
end
endmodule
```
```mips
module DelayBy1(
input clock,
input reset,
input [15:0] io_in,
output [15:0] io_out
);
`ifdef RANDOMIZE_REG_INIT
reg [31:0] _RAND_0;
`endif // RANDOMIZE_REG_INIT
reg [15:0] reg_; // @[cmd18.sc 7:28]
assign io_out = reg_; // @[cmd18.sc 11:10]
always @(posedge clock) begin
if (reset) begin // @[cmd18.sc 7:28]
reg_ <= 16'h3; // @[cmd18.sc 7:28]
end else begin
reg_ <= io_in; // @[cmd18.sc 10:7]
end
end
endmodule
```
---
# Implicits
* 基礎語法
* 變數隱式值宣告
* 函數的隱式輸入參數宣告
* 隱式參數可能的失敗時機
* 給定類型的兩個或多個隱式值在作用域中定義
* 如果編譯器找不到函數呼叫所需的隱式值
```scala=
object CatDog {
implicit val numberOfCats: Int = 3
//implicit val numberOfDogs: Int = 5
def tooManyCats(nDogs: Int)(implicit nCats: Int): Boolean = nCats > nDogs
val imp = tooManyCats(2) // Argument passed implicitly!
val exp = tooManyCats(2)(1) // Argument passed explicitly!
}
CatDog.imp
CatDog.exp
```
```shell
res24_1 : Boolean = true
res24_2 : Boolean = false
```
## Chisel 中隱式應用: 生成生成日誌(log)
* trait: scala 的結構(struct)定義方式之一
* sealed: 密封。scala 的編譯器會去驗證並枚舉類別或是結構的繼承是否有缺失
* 因此使用 sealed trait 表示宣告一個類別,並且編譯器會去驗證他的宣告和繼承
* 2, 3 行宣告了兩個物件
* 前面有提到 require() 的使用,結合隱式可以用來生成生成日誌或是隱藏他
* log 已經提前定義了
* 加 s 則輸出"in0Width of 1 OK"
* 不加 s 則會輸出"in0Width of $in0Width OK"
```
require( 目標判斷式 )
log(s"in0Width of $in0Width OK")
```
* 範例程式碼:
```scala=
sealed trait Verbosity
implicit case object Silent extends Verbosity
case object Verbose extends Verbosity
class ParameterizedWidthAdder(in0Width: Int, in1Width: Int, sumWidth: Int)(implicit verbosity: Verbosity)
extends Module {
def log(msg: => String): Unit = verbosity match {
case Silent =>
case Verbose => println(msg)
}
require(in0Width >= 0)
log(s"in0Width of $in0Width OK")
require(in1Width >= 0)
log(s"in1Width of $in1Width OK")
require(sumWidth >= 0)
log(s"sumWidth of $sumWidth OK")
val io = IO(new Bundle {
val in0 = Input(UInt(in0Width.W))
val in1 = Input(UInt(in1Width.W))
val sum = Output(UInt(sumWidth.W))
})
log("Made IO")
io.sum := io.in0 + io.in1
log("Assigned output")
}
println(getVerilog(new ParameterizedWidthAdder(1, 4, 5)))
println(getVerilog(new ParameterizedWidthAdder(1, 4, 5)(Verbose)))
```
```mips
Elaborating design...
Done elaborating.
module ParameterizedWidthAdder(
input clock,
input reset,
input io_in0,
input [3:0] io_in1,
output [4:0] io_sum
);
wire [3:0] _GEN_0 = {{3'd0}, io_in0}; // @[cmd28.sc 23:20]
wire [3:0] _T_1 = _GEN_0 + io_in1; // @[cmd28.sc 23:20]
assign io_sum = {{1'd0}, _T_1}; // @[cmd28.sc 23:20]
endmodule
```
```mips
Elaborating design...
in0Width of 1 OK
in1Width of 4 OK
sumWidth of 5 OK
Made IO
Assigned output
Done elaborating.
module ParameterizedWidthAdder(
input clock,
input reset,
input io_in0,
input [3:0] io_in1,
output [4:0] io_sum
);
wire [3:0] _GEN_0 = {{3'd0}, io_in0}; // @[cmd28.sc 23:20]
wire [3:0] _T_1 = _GEN_0 + io_in1; // @[cmd28.sc 23:20]
assign io_sum = {{1'd0}, _T_1}; // @[cmd28.sc 23:20]
endmodule
```
## 隱式轉換
* 隱式轉換用於減少樣板程式碼。更具體地說,它們用於自動將一個 Scala 物件轉換為另一個物件。
* 通常,隱式會使您的程式碼變得混亂,因此我們建議您將它們用作最後的手段。首先嘗試繼承、特徵或方法重載
```scala=
class Animal(val name: String, val species: String)
class Human(val name: String)
implicit def human2animal(h: Human): Animal = new Animal(h.name, "Homo sapiens")
val me = new Human("Adam")
println(me.species)
```
```shell
Homo sapiens
defined class Animal
defined class Human
defined function human2animal
me: Human = ammonite.$sess.cmd30$Helper$Human@75cf0cfc
```
---
# Collections
## 核心想法與範例1 ground truth 函式設計
* 想法1: 把輸入換成可以任意長度的 ```Seq[Int]```
* 想法2: 保存先前週期的值,使用1```var pseudoRegisters = List.fill(input.length)(0)```建立一個 list
* 範例說明:
* ```::```: [第一章有提到](https://hackmd.io/@nfUUgsYRTGy81y5d9AYOyg/BJdW9obUa)
* ```list.indices```: 回傳 list 的所有下標
* 第 13 行的 accumulator 表回傳值
* ground truth 函式 因為不是 extends Module,所以僅能進行 chisel test,無法 getVerilog()
```scala=
/**
* A naive implementation of an FIR filter with an arbitrary number of taps.
*/
class ScalaFirFilter(taps: Seq[Int]) {
var pseudoRegisters = List.fill(taps.length)(0)
def poke(value: Int): Int = {
pseudoRegisters = value :: pseudoRegisters.take(taps.length - 1)
var accumulator = 0
for(i <- taps.indices) {
accumulator += taps(i) * pseudoRegisters(i)
}
accumulator
}
}
```
## 範例1: 單輸入 FIR
* 可以根據輸入生成不同的電路
* 範例說明:
* ```ArrayBuffer```: scala 的一種集合類型,允許使用 ```+=``` 運算子追加元素
* 使用時需要 ```import scala.collection.mutable.ArrayBuffer```
* 宣告方式大概是這樣
* ```val ints = ArrayBuffer[Int]()```
* ```val names = ArrayBuffer[String]()```
* 最後一個 scan 就是計算加總後的元素
```scala=
class MyManyElementFir(consts: Seq[Int], bitWidth: Int) extends Module {
val io = IO(new Bundle {
val in = Input(UInt(bitWidth.W))
val out = Output(UInt(bitWidth.W))
})
val regs = mutable.ArrayBuffer[UInt]()
for(i <- 0 until consts.length) {
if(i == 0) regs += io.in
else regs += RegNext(regs(i - 1), 0.U)
}
val muls = mutable.ArrayBuffer[UInt]()
for(i <- 0 until consts.length) {
muls += regs(i) * consts(i).U
}
val scan = mutable.ArrayBuffer[UInt]()
for(i <- 0 until consts.length) {
if(i == 0) scan += muls(i)
else scan += muls(i) + scan(i - 1)
}
io.out := scan.last
}
```
* 輸入為```Seq(1, 1),4```
* 兩個輸入所以生成一個暫存器
```scala
println(getVerilog(new MyManyElementFir(Seq(1, 1),4)))
```
```mips=
module MyManyElementFir(
input clock,
input reset,
input [3:0] io_in,
output [3:0] io_out
);
`ifdef RANDOMIZE_REG_INIT
reg [31:0] _RAND_0;
`endif // RANDOMIZE_REG_INIT
reg [3:0] regs_1; // @[cmd18.sc 10:33]
wire [4:0] muls_0 = io_in * 1'h1; // @[cmd18.sc 15:23]
wire [4:0] muls_1 = regs_1 * 1'h1; // @[cmd18.sc 15:23]
wire [4:0] scan_1 = muls_1 + muls_0; // @[cmd18.sc 21:28]
assign io_out = scan_1[3:0]; // @[cmd18.sc 24:10]
always @(posedge clock) begin
if (reset) begin // @[cmd18.sc 10:33]
regs_1 <= 4'h0; // @[cmd18.sc 10:33]
end else begin
regs_1 <= io_in; // @[cmd18.sc 10:33]
end
end
endmodule
```
* 輸入為```Seq(1, 1, 1),8```
* 三個輸入所以生成兩個暫存器
```scala
println(getVerilog(new MyManyElementFir(Seq(1, 1, 1),8)))
```
```mips=
module MyManyElementFir(
input clock,
input reset,
input [7:0] io_in,
output [7:0] io_out
);
`ifdef RANDOMIZE_REG_INIT
reg [31:0] _RAND_0;
reg [31:0] _RAND_1;
`endif // RANDOMIZE_REG_INIT
reg [7:0] regs_1; // @[cmd18.sc 10:33]
reg [7:0] regs_2; // @[cmd18.sc 10:33]
wire [8:0] muls_0 = io_in * 1'h1; // @[cmd18.sc 15:23]
wire [8:0] muls_1 = regs_1 * 1'h1; // @[cmd18.sc 15:23]
wire [8:0] muls_2 = regs_2 * 1'h1; // @[cmd18.sc 15:23]
wire [8:0] scan_1 = muls_1 + muls_0; // @[cmd18.sc 21:28]
wire [8:0] scan_2 = muls_2 + scan_1; // @[cmd18.sc 21:28]
assign io_out = scan_2[7:0]; // @[cmd18.sc 24:10]
always @(posedge clock) begin
if (reset) begin // @[cmd18.sc 10:33]
regs_1 <= 8'h0; // @[cmd18.sc 10:33]
end else begin
regs_1 <= io_in; // @[cmd18.sc 10:33]
end
if (reset) begin // @[cmd18.sc 10:33]
regs_2 <= 8'h0; // @[cmd18.sc 10:33]
end else begin
regs_2 <= regs_1; // @[cmd18.sc 10:33]
end
end
endmodule
```
## 範例2: 多輸入 FIR
* 範例說明:
* 能實現多輸入是因為第五行的```val consts = Input(Vec(length, UInt(8.W)))```,能根據生成器輸入決定電路輸入
* 單輸入的係數是在生成電路後就固定,多輸入的再生成電路後還能根據輸入改變係數
* 剩下的部分跟單輸入的差不多
```scala=
class MyManyDynamicElementVecFir(length: Int) extends Module {
val io = IO(new Bundle {
val in = Input(UInt(8.W))
val out = Output(UInt(8.W))
val consts = Input(Vec(length, UInt(8.W)))
})
// Reference solution
val regs = RegInit(VecInit(Seq.fill(length - 1)(0.U(8.W))))
for(i <- 0 until length - 1) {
if(i == 0) regs(i) := io.in
else regs(i) := regs(i - 1)
}
val muls = Wire(Vec(length, UInt(8.W)))
for(i <- 0 until length) {
if(i == 0) muls(i) := io.in * io.consts(i)
else muls(i) := regs(i - 1) * io.consts(i)
}
val scan = Wire(Vec(length, UInt(8.W)))
for(i <- 0 until length) {
if(i == 0) scan(i) := muls(i)
else scan(i) := muls(i) + scan(i - 1)
}
io.out := scan(length - 1)
}
println(getVerilog(new MyManyDynamicElementVecFir(2)))
```
```mips=
module MyManyDynamicElementVecFir(
input clock,
input reset,
input [7:0] io_in,
output [7:0] io_out,
input [7:0] io_consts_0,
input [7:0] io_consts_1
);
`ifdef RANDOMIZE_REG_INIT
reg [31:0] _RAND_0;
`endif // RANDOMIZE_REG_INIT
reg [7:0] regs_0; // @[cmd24.sc 9:21]
wire [15:0] _T = io_in * io_consts_0; // @[cmd24.sc 17:35]
wire [15:0] _T_1 = regs_0 * io_consts_1; // @[cmd24.sc 18:41]
wire [7:0] muls_1 = _T_1[7:0]; // @[cmd24.sc 15:18 cmd24.sc 18:26]
wire [7:0] muls_0 = _T[7:0]; // @[cmd24.sc 15:18 cmd24.sc 17:26]
assign io_out = muls_1 + muls_0; // @[cmd24.sc 24:31]
always @(posedge clock) begin
if (reset) begin // @[cmd24.sc 9:21]
regs_0 <= 8'h0; // @[cmd24.sc 9:21]
end else begin
regs_0 <= io_in; // @[cmd24.sc 11:26]
end
end
endmodule
```
## 範例3: 32 位元 RISC-V 暫存器
* 範例說明:
* 單一寫入,多埠讀值
* addr 位寬設為 5.W 是因為 RV32I 暫存器數量為 32
* 第 18 行是因為 **RV32 規範 $0 的值恆為 0**
* 所像是```addi $0 $18 1024```就是 nop 指令
```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)))
})
// A Register of a vector of UInts
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 code 後,就可以知道 HCL 的重要性
* 除了使用 HCL 外,晶片設計者也會使用(自製的)腳本語言完成 HDL 的基本撰寫
* 因為很長我就不調整縮排了
:::spoiler
```mips=
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,
output [31:0] io_rdata_0,
output [31:0] io_rdata_1
);
`ifdef RANDOMIZE_REG_INIT
reg [31:0] _RAND_0;
reg [31:0] _RAND_1;
reg [31:0] _RAND_2;
reg [31:0] _RAND_3;
reg [31:0] _RAND_4;
reg [31:0] _RAND_5;
reg [31:0] _RAND_6;
reg [31:0] _RAND_7;
reg [31:0] _RAND_8;
reg [31:0] _RAND_9;
reg [31:0] _RAND_10;
reg [31:0] _RAND_11;
reg [31:0] _RAND_12;
reg [31:0] _RAND_13;
reg [31:0] _RAND_14;
reg [31:0] _RAND_15;
reg [31:0] _RAND_16;
reg [31:0] _RAND_17;
reg [31:0] _RAND_18;
reg [31:0] _RAND_19;
reg [31:0] _RAND_20;
reg [31:0] _RAND_21;
reg [31:0] _RAND_22;
reg [31:0] _RAND_23;
reg [31:0] _RAND_24;
reg [31:0] _RAND_25;
reg [31:0] _RAND_26;
reg [31:0] _RAND_27;
reg [31:0] _RAND_28;
reg [31:0] _RAND_29;
reg [31:0] _RAND_30;
reg [31:0] _RAND_31;
`endif // RANDOMIZE_REG_INIT
reg [31:0] reg_0; // @[cmd27.sc 12:22]
reg [31:0] reg_1; // @[cmd27.sc 12:22]
reg [31:0] reg_2; // @[cmd27.sc 12:22]
reg [31:0] reg_3; // @[cmd27.sc 12:22]
reg [31:0] reg_4; // @[cmd27.sc 12:22]
reg [31:0] reg_5; // @[cmd27.sc 12:22]
reg [31:0] reg_6; // @[cmd27.sc 12:22]
reg [31:0] reg_7; // @[cmd27.sc 12:22]
reg [31:0] reg_8; // @[cmd27.sc 12:22]
reg [31:0] reg_9; // @[cmd27.sc 12:22]
reg [31:0] reg_10; // @[cmd27.sc 12:22]
reg [31:0] reg_11; // @[cmd27.sc 12:22]
reg [31:0] reg_12; // @[cmd27.sc 12:22]
reg [31:0] reg_13; // @[cmd27.sc 12:22]
reg [31:0] reg_14; // @[cmd27.sc 12:22]
reg [31:0] reg_15; // @[cmd27.sc 12:22]
reg [31:0] reg_16; // @[cmd27.sc 12:22]
reg [31:0] reg_17; // @[cmd27.sc 12:22]
reg [31:0] reg_18; // @[cmd27.sc 12:22]
reg [31:0] reg_19; // @[cmd27.sc 12:22]
reg [31:0] reg_20; // @[cmd27.sc 12:22]
reg [31:0] reg_21; // @[cmd27.sc 12:22]
reg [31:0] reg_22; // @[cmd27.sc 12:22]
reg [31:0] reg_23; // @[cmd27.sc 12:22]
reg [31:0] reg_24; // @[cmd27.sc 12:22]
reg [31:0] reg_25; // @[cmd27.sc 12:22]
reg [31:0] reg_26; // @[cmd27.sc 12:22]
reg [31:0] reg_27; // @[cmd27.sc 12:22]
reg [31:0] reg_28; // @[cmd27.sc 12:22]
reg [31:0] reg_29; // @[cmd27.sc 12:22]
reg [31:0] reg_30; // @[cmd27.sc 12:22]
reg [31:0] reg_31; // @[cmd27.sc 12:22]
wire [31:0] _GEN_65 = 5'h1 == io_raddr_0 ? reg_1 : reg_0; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_66 = 5'h2 == io_raddr_0 ? reg_2 : _GEN_65; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_67 = 5'h3 == io_raddr_0 ? reg_3 : _GEN_66; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_68 = 5'h4 == io_raddr_0 ? reg_4 : _GEN_67; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_69 = 5'h5 == io_raddr_0 ? reg_5 : _GEN_68; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_70 = 5'h6 == io_raddr_0 ? reg_6 : _GEN_69; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_71 = 5'h7 == io_raddr_0 ? reg_7 : _GEN_70; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_72 = 5'h8 == io_raddr_0 ? reg_8 : _GEN_71; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_73 = 5'h9 == io_raddr_0 ? reg_9 : _GEN_72; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_74 = 5'ha == io_raddr_0 ? reg_10 : _GEN_73; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_75 = 5'hb == io_raddr_0 ? reg_11 : _GEN_74; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_76 = 5'hc == io_raddr_0 ? reg_12 : _GEN_75; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_77 = 5'hd == io_raddr_0 ? reg_13 : _GEN_76; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_78 = 5'he == io_raddr_0 ? reg_14 : _GEN_77; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_79 = 5'hf == io_raddr_0 ? reg_15 : _GEN_78; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_80 = 5'h10 == io_raddr_0 ? reg_16 : _GEN_79; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_81 = 5'h11 == io_raddr_0 ? reg_17 : _GEN_80; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_82 = 5'h12 == io_raddr_0 ? reg_18 : _GEN_81; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_83 = 5'h13 == io_raddr_0 ? reg_19 : _GEN_82; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_84 = 5'h14 == io_raddr_0 ? reg_20 : _GEN_83; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_85 = 5'h15 == io_raddr_0 ? reg_21 : _GEN_84; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_86 = 5'h16 == io_raddr_0 ? reg_22 : _GEN_85; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_87 = 5'h17 == io_raddr_0 ? reg_23 : _GEN_86; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_88 = 5'h18 == io_raddr_0 ? reg_24 : _GEN_87; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_89 = 5'h19 == io_raddr_0 ? reg_25 : _GEN_88; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_90 = 5'h1a == io_raddr_0 ? reg_26 : _GEN_89; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_91 = 5'h1b == io_raddr_0 ? reg_27 : _GEN_90; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_92 = 5'h1c == io_raddr_0 ? reg_28 : _GEN_91; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_93 = 5'h1d == io_raddr_0 ? reg_29 : _GEN_92; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_94 = 5'h1e == io_raddr_0 ? reg_30 : _GEN_93; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_95 = 5'h1f == io_raddr_0 ? reg_31 : _GEN_94; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_98 = 5'h1 == io_raddr_1 ? reg_1 : reg_0; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_99 = 5'h2 == io_raddr_1 ? reg_2 : _GEN_98; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_100 = 5'h3 == io_raddr_1 ? reg_3 : _GEN_99; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_101 = 5'h4 == io_raddr_1 ? reg_4 : _GEN_100; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_102 = 5'h5 == io_raddr_1 ? reg_5 : _GEN_101; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_103 = 5'h6 == io_raddr_1 ? reg_6 : _GEN_102; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_104 = 5'h7 == io_raddr_1 ? reg_7 : _GEN_103; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_105 = 5'h8 == io_raddr_1 ? reg_8 : _GEN_104; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_106 = 5'h9 == io_raddr_1 ? reg_9 : _GEN_105; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_107 = 5'ha == io_raddr_1 ? reg_10 : _GEN_106; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_108 = 5'hb == io_raddr_1 ? reg_11 : _GEN_107; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_109 = 5'hc == io_raddr_1 ? reg_12 : _GEN_108; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_110 = 5'hd == io_raddr_1 ? reg_13 : _GEN_109; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_111 = 5'he == io_raddr_1 ? reg_14 : _GEN_110; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_112 = 5'hf == io_raddr_1 ? reg_15 : _GEN_111; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_113 = 5'h10 == io_raddr_1 ? reg_16 : _GEN_112; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_114 = 5'h11 == io_raddr_1 ? reg_17 : _GEN_113; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_115 = 5'h12 == io_raddr_1 ? reg_18 : _GEN_114; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_116 = 5'h13 == io_raddr_1 ? reg_19 : _GEN_115; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_117 = 5'h14 == io_raddr_1 ? reg_20 : _GEN_116; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_118 = 5'h15 == io_raddr_1 ? reg_21 : _GEN_117; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_119 = 5'h16 == io_raddr_1 ? reg_22 : _GEN_118; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_120 = 5'h17 == io_raddr_1 ? reg_23 : _GEN_119; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_121 = 5'h18 == io_raddr_1 ? reg_24 : _GEN_120; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_122 = 5'h19 == io_raddr_1 ? reg_25 : _GEN_121; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_123 = 5'h1a == io_raddr_1 ? reg_26 : _GEN_122; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_124 = 5'h1b == io_raddr_1 ? reg_27 : _GEN_123; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_125 = 5'h1c == io_raddr_1 ? reg_28 : _GEN_124; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_126 = 5'h1d == io_raddr_1 ? reg_29 : _GEN_125; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_127 = 5'h1e == io_raddr_1 ? reg_30 : _GEN_126; // @[cmd27.sc 21:25 cmd27.sc 21:25]
wire [31:0] _GEN_128 = 5'h1f == io_raddr_1 ? reg_31 : _GEN_127; // @[cmd27.sc 21:25 cmd27.sc 21:25]
assign io_rdata_0 = io_raddr_0 == 5'h0 ? 32'h0 : _GEN_95; // @[cmd27.sc 18:36 cmd27.sc 19:25 cmd27.sc 21:25]
assign io_rdata_1 = io_raddr_1 == 5'h0 ? 32'h0 : _GEN_128; // @[cmd27.sc 18:36 cmd27.sc 19:25 cmd27.sc 21:25]
always @(posedge clock) begin
if (reset) begin // @[cmd27.sc 12:22]
reg_0 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h0 == io_waddr) begin // @[cmd27.sc 15:23]
reg_0 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_1 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h1 == io_waddr) begin // @[cmd27.sc 15:23]
reg_1 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_2 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h2 == io_waddr) begin // @[cmd27.sc 15:23]
reg_2 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_3 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h3 == io_waddr) begin // @[cmd27.sc 15:23]
reg_3 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_4 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h4 == io_waddr) begin // @[cmd27.sc 15:23]
reg_4 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_5 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h5 == io_waddr) begin // @[cmd27.sc 15:23]
reg_5 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_6 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h6 == io_waddr) begin // @[cmd27.sc 15:23]
reg_6 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_7 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h7 == io_waddr) begin // @[cmd27.sc 15:23]
reg_7 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_8 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h8 == io_waddr) begin // @[cmd27.sc 15:23]
reg_8 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_9 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h9 == io_waddr) begin // @[cmd27.sc 15:23]
reg_9 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_10 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'ha == io_waddr) begin // @[cmd27.sc 15:23]
reg_10 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_11 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'hb == io_waddr) begin // @[cmd27.sc 15:23]
reg_11 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_12 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'hc == io_waddr) begin // @[cmd27.sc 15:23]
reg_12 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_13 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'hd == io_waddr) begin // @[cmd27.sc 15:23]
reg_13 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_14 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'he == io_waddr) begin // @[cmd27.sc 15:23]
reg_14 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_15 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'hf == io_waddr) begin // @[cmd27.sc 15:23]
reg_15 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_16 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h10 == io_waddr) begin // @[cmd27.sc 15:23]
reg_16 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_17 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h11 == io_waddr) begin // @[cmd27.sc 15:23]
reg_17 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_18 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h12 == io_waddr) begin // @[cmd27.sc 15:23]
reg_18 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_19 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h13 == io_waddr) begin // @[cmd27.sc 15:23]
reg_19 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_20 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h14 == io_waddr) begin // @[cmd27.sc 15:23]
reg_20 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_21 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h15 == io_waddr) begin // @[cmd27.sc 15:23]
reg_21 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_22 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h16 == io_waddr) begin // @[cmd27.sc 15:23]
reg_22 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_23 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h17 == io_waddr) begin // @[cmd27.sc 15:23]
reg_23 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_24 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h18 == io_waddr) begin // @[cmd27.sc 15:23]
reg_24 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_25 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h19 == io_waddr) begin // @[cmd27.sc 15:23]
reg_25 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_26 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h1a == io_waddr) begin // @[cmd27.sc 15:23]
reg_26 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_27 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h1b == io_waddr) begin // @[cmd27.sc 15:23]
reg_27 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_28 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h1c == io_waddr) begin // @[cmd27.sc 15:23]
reg_28 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_29 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h1d == io_waddr) begin // @[cmd27.sc 15:23]
reg_29 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_30 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h1e == io_waddr) begin // @[cmd27.sc 15:23]
reg_30 <= io_wdata; // @[cmd27.sc 15:23]
end
end
if (reset) begin // @[cmd27.sc 12:22]
reg_31 <= 32'h0; // @[cmd27.sc 12:22]
end else if (io_wen) begin // @[cmd27.sc 14:19]
if (5'h1f == io_waddr) begin // @[cmd27.sc 15:23]
reg_31 <= io_wdata; // @[cmd27.sc 15:23]
end
end
end
endmodule
```
:::
---
# 範例
## 範例1: Mealy machine
* 定義一個物件 BinaryMealyParams,輸入 Module
```scala=
// Mealy machine has
case class BinaryMealyParams(
// number of states
nStates: Int,
// initial state
s0: Int,
// function describing state transition
stateTransition: (Int, Boolean) => Int,
// function describing output
output: (Int, Boolean) => Int
) {
require(nStates >= 0)
require(s0 < nStates && s0 >= 0)
}
class BinaryMealy(val mp: BinaryMealyParams) extends Module {
val io = IO(new Bundle {
val in = Input(Bool())
val out = Output(UInt())
})
val state = RegInit(UInt(), mp.s0.U)
// output zero if no states
io.out := 0.U
for (i <- 0 until mp.nStates) {
when (state === i.U) {
when (io.in) {
state := mp.stateTransition(i, true).U
io.out := mp.output(i, true).U
}.otherwise {
state := mp.stateTransition(i, false).U
io.out := mp.output(i, false).U
}
}
}
}
```
```shell
Elaborating design...
Done elaborating.
module BinaryMealy(
input clock,
input reset,
input io_in,
output io_out
);
`ifdef RANDOMIZE_REG_INIT
reg [31:0] _RAND_0;
`endif // RANDOMIZE_REG_INIT
reg [1:0] state; // @[cmd32.sc 21:22]
wire _GEN_2 = state == 2'h0 & io_in; // @[cmd32.sc 26:26 cmd32.sc 24:10]
wire _GEN_3 = io_in ? 1'h0 : 1'h1; // @[cmd32.sc 27:20 cmd32.sc 29:16 cmd32.sc 32:16]
wire _GEN_5 = state == 2'h1 ? _GEN_3 : _GEN_2; // @[cmd32.sc 26:26]
assign io_out = state == 2'h2 ? 1'h0 : _GEN_5; // @[cmd32.sc 26:26]
always @(posedge clock) begin
if (reset) begin // @[cmd32.sc 21:22]
state <= 2'h2; // @[cmd32.sc 21:22]
end else if (state == 2'h2) begin // @[cmd32.sc 26:26]
state <= {{1'd0}, io_in};
end else if (state == 2'h1) begin // @[cmd32.sc 26:26]
state <= {{1'd0}, io_in};
end else if (state == 2'h0) begin // @[cmd32.sc 26:26]
state <= {{1'd0}, io_in};
end
end
endmodule
```
---
# 參考
* [Chisel-bootcamp](https://mybinder.org/v2/gh/freechipsproject/chisel-bootcamp/master)