• 使用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。

  • 相关阅读:
    特殊json处理
    css3
    居中定位
    微信支付
    vue 封装cookie,请求,登录拦截,接口拦截
    vue中axios的封装(简易版拦截,get,post
    JS的Event Loop
    JS模块化
    JS的排序算法
    时间复杂度 空间复杂度
  • 原文地址:https://www.cnblogs.com/lyuyangly/p/14320473.html
Copyright © 2020-2023  润新知