使用chisel做数字电路开发的Hello World

首先安装构建环境(我用的系统是LinuxMint):

安装scala: sudo apt install scala; chisel是scala语言编写的库,而scala语言编译出来的字节码运行于JVM;所以会一并安装java运行时环境。

安装sbt: sudo apt install sbt; 安装的版本是1.4.6; sbt是scala的构建工具,可以方便的管理工程和处理依赖包。

设置sbt仓库:~/.sbt/repositories

[repositories]
local
aliyun-maven-public: https://maven.aliyun.com/repository/public
aliyun-maven-central: https://maven.aliyun.com/repository/central

建立一个Hello World工程:

├── build.sbt
├── src
│   ├── main
│   │   └── scala
│   │   └── Hello.scala
│   └── test
│   └── scala
│   └── HelloSpec.scala

import chisel3._
import chisel3.Driver

/**
 * The blinking LED component.
 */

class Hello extends Module {
  val io = IO(new Bundle {
    val led = Output(UInt(1.W))
  })
  val CNT_MAX = (50000000 / 2 - 1).U;

  val cntReg = RegInit(0.U(32.W))
  val blkReg = RegInit(0.U(1.W))

  cntReg := cntReg + 1.U
  when(cntReg === CNT_MAX) {
    cntReg := 0.U
    blkReg := ~blkReg
  }
  io.led := blkReg
}

/**
 * An object extending App to generate the Verilog code.
 */
object Hello extends App {
  (new chisel3.stage.ChiselStage).emitVerilog(new Hello())
}
import chisel3.iotesters.PeekPokeTester
import org.scalatest._

class HelloSpec extends FlatSpec with Matchers {

  "Hello" should "pass" in {
    chisel3.iotesters.Driver(() => new Hello()) { c =>
      new PeekPokeTester(c) {

        var ledStatus = -1
        println("Start the blinking LED")
        for (i <- 0 until 100) {
          step(10000)
          val ledNow = peek(c.io.led).toInt
          val s = if (ledNow == 0) "o" else "*"
          if (ledStatus != ledNow) {
            System.out.println(s)
            ledStatus = ledNow
          }
        }
        println("
End the blinking LED")
      }
    } should be (true)
  }

}

build.sbt

scalaVersion := "2.11.12"

scalacOptions := Seq("-deprecation", "-Xsource:2.11")

resolvers ++= Seq(
Resolver.sonatypeRepo("snapshots"),
Resolver.sonatypeRepo("releases")
)

// Chisel 3.4
libraryDependencies += "edu.berkeley.cs" %% "chisel-iotesters" % "1.5.1"
libraryDependencies += "edu.berkeley.cs" %% "chiseltest" % "0.3.1"

上述工程实现了LED闪烁的功能,如果有FPGA可以把生成的Hello.v集成一下测试。

在build.sbt所在目录执行sbt compile编译源代码;执行sbt "run Hello"即可生成HDL文件,执行sbt test运行单元测试。我们来看看生成的Verilog代码:

 1 module Hello(
 2   input   clock,
 3   input   reset,
 4   output  io_led
 5 );
 6 `ifdef RANDOMIZE_REG_INIT
 7   reg [31:0] _RAND_0;
 8   reg [31:0] _RAND_1;
 9 `endif // RANDOMIZE_REG_INIT
10   reg [31:0] cntReg; // @[Hello.scala 20:23]
11   reg  blkReg; // @[Hello.scala 21:23]
12   wire [31:0] _T_1 = cntReg + 32'h1; // @[Hello.scala 23:20]
13   assign io_led = blkReg; // @[Hello.scala 28:10]
14   always @(posedge clock) begin
15     if (reset) begin // @[Hello.scala 20:23]
16       cntReg <= 32'h0; // @[Hello.scala 20:23]
17     end else if (cntReg == 32'h17d783f) begin // @[Hello.scala 24:28]
18       cntReg <= 32'h0; // @[Hello.scala 25:12]
19     end else begin
20       cntReg <= _T_1; // @[Hello.scala 23:10]
21     end
22     if (reset) begin // @[Hello.scala 21:23]
23       blkReg <= 1'h0; // @[Hello.scala 21:23]
24     end else if (cntReg == 32'h17d783f) begin // @[Hello.scala 24:28]
25       blkReg <= ~blkReg; // @[Hello.scala 26:12]
26     end
27   end
28 // Register and memory initialization
29 `ifdef RANDOMIZE_GARBAGE_ASSIGN
30 `define RANDOMIZE
31 `endif
32 `ifdef RANDOMIZE_INVALID_ASSIGN
33 `define RANDOMIZE
34 `endif
35 `ifdef RANDOMIZE_REG_INIT
36 `define RANDOMIZE
37 `endif
38 `ifdef RANDOMIZE_MEM_INIT
39 `define RANDOMIZE
40 `endif
41 `ifndef RANDOM
42 `define RANDOM $random
43 `endif
44 `ifdef RANDOMIZE_MEM_INIT
45   integer initvar;
46 `endif
47 `ifndef SYNTHESIS
48 `ifdef FIRRTL_BEFORE_INITIAL
49 `FIRRTL_BEFORE_INITIAL
50 `endif
51 initial begin
52   `ifdef RANDOMIZE
53     `ifdef INIT_RANDOM
54       `INIT_RANDOM
55     `endif
56     `ifndef VERILATOR
57       `ifdef RANDOMIZE_DELAY
58         #`RANDOMIZE_DELAY begin end
59       `else
60         #0.002 begin end
61       `endif
62     `endif
63 `ifdef RANDOMIZE_REG_INIT
64   _RAND_0 = {1{`RANDOM}};
65   cntReg = _RAND_0[31:0];
66   _RAND_1 = {1{`RANDOM}};
67   blkReg = _RAND_1[0:0];
68 `endif // RANDOMIZE_REG_INIT
69   `endif // RANDOMIZE
70 end // initial
71 `ifdef FIRRTL_AFTER_INITIAL
72 `FIRRTL_AFTER_INITIAL
73 `endif
74 `endif // SYNTHESIS
75 endmodule

如此ugly的代码,怎么保证scala和HDL的形式验证(formal)?如果后期bug做ECO,网表命名成这样子,可读性这么差怎么搞?生成的Verilog怎么投入验证?chisel版本的迭代兼容性怎么保证?bug修改后继承版本如何回归验证?AMS系统如何验证?在模拟为顶层包数字的电路如何带入scala验证?

我会选择SystemVerilog和Verilog-A,而不是Chisel。

原文地址:https://www.cnblogs.com/lyuyangly/p/14320473.html