吃透Chisel语言.10.Chisel项目构建、运行和测试(二)——Chisel中生成Verilog代码&Chisel开发流程

2023-11-01

Chisel项目构建、运行和测试(二)——Chisel中生成Verilog代码&Chisel开发流程

上一篇文章我们提到了怎么用sbt构建Chisel项目并运行Chisel代码,但是毕竟还是在电脑上运行的。而在实践中,我们写的Chisel代码最终应该综合到FPGA或ASIC上,所以必须把Chisel翻译到一个综合工具能处理的硬件描述语言,比如Verilog。那怎么用Chisel代码生成Verilog代码呢?Chisel的开发流程又是怎样的呢?这篇文章来学习一下。

Chisel生成Verilog代码

Chisel是可以生成可综合的Verilog代码的,把生成Verilog的代码放到一个应用入口里面就可以了。这个应用入口就是个Scala对象,是从App拓展来的,上一节提到过,它会在程序启动的时候隐式地生成主函数。这个应用入口里面只有一行代码,它创建了一个新的Hello对象,然后传递给Chisel的emitVerilog()函数,它会生成Hello模块对应的Verilog文件Hello.v。代码如下:

object Hello extends App {
    emitVerilog(new Hello())
}

不过这种调用emitVerilog的写法会把生成的文件默认地放到项目根目录下,也就是运行sbt命令的路径。如果想要把生成的文件放到指定文件夹下的话,就需要给emitVerilog()指定选项。构建选项可以设置为emitVerilog()的第二个参数,参数类型是字符串的数组。上一篇文章讲Chisel项目目录结构的时候提到过,建议把生成的文件放到generated文件夹下,下面的代码就能实现这个需求:

object HelloOption extends App {
    emitVerilog(new Hello(), Array("--target-dir", "generated"))
}

如果我们不想把Verilog代码输出为文件,只是想把它作为Scala字符串在命令行输出的话,只需要使用getVerilogString()函数即可:

object HelloString extends App {
    val s = getVerilogString(new Hello())
    println(s)
}

这种生成方法在小Chisel项目中很好用,比如这个网页上Led灯闪烁的例子Hello World - Scastie (scala-lang.org),用getVerilogString函数输出了该模块对应的Verilog代码。

另外这个Scastie其实是个在线的Scala开发环境,我们如果本地没有配环境的话也完全可以用这个在线环境来进行简单的Chisel开发,能免去配环境的麻烦。

Chisel的工具流开发流程

下面我们运行一个简单但完整的生成Verilog的例子,对应的电路就是直接四位的有符号输入连接到四位的有符号输出:

package my.hello

import chisel3._

class ModuleSample extends Module {
    val io = IO(new Bundle {
        val in_a = Input(SInt(4.W))
        val out_b = Output(SInt(4.W))
    })
    
    io.out_b := io.in_a
}

object MyModule extends App {
    emitVerilog(new ModuleSample(), Array("--target-dir", "generated"))
}

但是我们可以惊奇的看到,generated文件夹下除了*.v的Verilog文件,还有*.fir文件和*.anno.json文件:

在这里插入图片描述

也就是不光生成了Verilog代码,还生成了其他文件,说到原因就涉及到Chisel的工具流了。Chisel的工具流如下图所示:

在这里插入图片描述

我们写的数字电路是其实就是Chisel的类,也就是图中的Hello.scala,本质是Scala源码。但Chisel区别于Scala的地方在于编译的时候不光用到了Scala的库scala.lib,还用到了Chisel的库chisel3.lib

有了Chisel源码,Scala的编译器基于Chisel、Scala的库将我们的代码生成Java类文件Hello.class,也就是字节码文件。这类文件是可以在标准的JVM(Java Virtual Machine,Java虚拟机)上直接执行的。

用Chisel驱动执行这个字节码文件会生成FIRRTL文件Hello.fir。这个FIRRTL全称为Flexible Intermediate Representation for RTL,即RTL的可变中间表示,是数字电路的的中间表示。FIRRTL编译器可以在电路上执行一些变换,是Chisel到其他硬件描述语言的关键桥梁,如果想理解更高阶的Chisel的内容甚至为Chisel开源代码做贡献,那就需要深入学习FIRRTL了。

再往下的Treadle是一个FIRRTL的解释器,用于电路的仿真。配合Chisel测试器,它可以用于调试和测试Chisel电路。根据输出的断言信息我们可以得到测试的结果。Treadle还可以生成波形文件,即Hello.vcd,这个波形文件是可以用波形查看器查看的,比如可以在GTKWare或Modelsim等上查看。

回到FIRRTL编译器部分,Verilog Emitter也是FIRRTL变换之一,可以用Hello.fir生成可综合的Verilog代码Hello.v。接着我们就可以用一个电路综合工具(比如Intel的Quartus,Xilinx的Vivado或其他的ASIC工具)来综合电路。在FPGA设计的工作流中,综合工具会生成FPGA比特流用于配置FPGA,即Hello.bit

结语

现在我们已经学会了怎么在Chisel中生成Verilog代码,也对用Chisel进行开发的工具流有了基本的了解。学会了怎么编译、怎么运行,接下来就得学习怎么测试了。我们肯定不能每次调试都把工具流走完来试错,比如每次修改完代码后都生成FPGA比特流进行测试,这样一是找不到错误所在,二是耗费时间太久。所以必须要在Chisel阶段就测试明白,对于小的模块是如此,对于更大规模的数字电路更得做好测试。后面几篇文章就讲讲几种Chisel测试框架怎么使用,测试代码该怎么写。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

吃透Chisel语言.10.Chisel项目构建、运行和测试(二)——Chisel中生成Verilog代码&Chisel开发流程 的相关文章

  • 【Xilinx DDR3 MIG】Xilinx FPGA DDR3读写实验相关用户接口引脚解释

    目录 DDR3读写实验 实验框图 时钟模块 DDR3读写及LED指示模块 MIG IP核 用户接口解释
  • 握手2倍速率进,一倍速率出[verilog]

    module two to one parameter WORD LEN 33 input clk input arst input 2 WORD LEN 1 0 i din input i din valid output o din r
  • TestBench编写_激励产生

    TestBench编写 激励产生 TestBench编写 激励产生 基本背景 读取函数介绍 a fopen函数使用 b fread函数使用 c fclose函数使用 实际使用 TestBench编写 激励产生 基本背景 最近遇到项目中需要对
  • Chisel手册之Types

    本文是Chisel手册第二篇Types Types 表示硬件设计的Chisel图包含原始节点和类型节点 Chisel类型系统与底层Scala类型系统分开维护 因此类型节点散布在原始节点之间 以允许Chisel检查并响应Chisel类型 Ch
  • Verilog HDL——Modelsim仿真

    常用testbench语法 finish 和 stop finish任务用于终止仿真并跳出仿真器 stop任务则用于中止仿真 timescale time unit time precision time unit指定计时和延时的测量单位
  • BUCK电路分析(二)

    BUCK电路分析 二 PSIM仿真同步BUCK电路 在上片文章中 初步的分析了BUCK电路的工作原理 本章使用PSIM软件仿真BUCK电路 观察分析BUCK电路器件关键波形 图1是同步BUCK电路图 开关频率设置为200K 固定占空比 在仿
  • 使用七牛云进行文件上传

    目录 一 七牛云入门测试 1 注册七牛云账号 完成后选择对象存储 2 在里面创建空间 一个空间相当于一个文件夹 就是将对象上传到的地方 3 查看个人秘钥 注册完成账号后 会有一个秘钥 上传文件的时候进行授权和认证 4 文件上传测试 二 封装
  • 【FPGA多周期时序约束详解】- 解读FPGA多周期时序约束的全过程

    FPGA多周期时序约束详解 解读FPGA多周期时序约束的全过程 FPGA作为数字电路设计的常见工具 其设计中必然会遇到时序约束的问题 而多周期时序约束更是FPGA设计中不可避免的难点之一 本文将详细介绍FPGA多周期时序约束的全过程 并结合
  • Risc-V:能够利用 GCC 的简单 RV32I 实现的最低 CSR 要求

    对于能够运行 GCC 生成的机器代码的 RV32I 最低的 CSR 要求是什么 我正在考虑一个简单的基于 fpga 嵌入式 的实现 不需要虚拟内存或 Linux 支持 另外 我应该使用什么 GCC 标志来防止它使用未实现的 CSR 相关指令
  • 【FMC141】基于VITA57.4标准的4通道2.8GSPS 16位DA播放子卡(2片DAC39J84)

    FMC141是一款基于VITA57 4标准的4通道2 8GSPS 2 5GSPS 1 6GSPS采样率16位DA播放FMC子卡 该板卡为FMC 标准 符合VITA57 4与VITA57 1规范 16通道的JESD204B接口通过FMC 连接
  • 为什么 $ra 被调用者保存在 RISC-V 中

    我发现在 RISC V 中 ra调用者是否已保存 以 MIPS 为单位 ra是被调用者 这意味着在 RISC V 中被调用者可以直接更改ra没有保存 但自从ra已经改变了 被调用者如何返回调用者 无论名称如何 RISC V ra 和 MIP
  • 基于FPGA的简易BPSK和QPSK

    1 框图 2 顶层 3 m generator M序列的生成 输出速率为500Kbps 4 S2P是串并转换模块 将1bit的m序列转换到50M时钟下的2bit M序列数据 就有4个象限 5 my pll是生成256M的时钟作为载波 因为s
  • 如何生成异步复位verilog总是阻塞凿子

    Chisel 始终生成敏感度列表中仅包含时钟的块 always posedge clk begin end 是否可以将模块配置为使用异步重置并生成这样的始终块 always posedge clk or posedge reset begi
  • 如何为 Risc-V(汇编语言)编写旋转操作 我们有像 8086 中那样的命令吗?

    我以前使用过8086的汇编语言 8086中的旋转操作只是一个命令 但我在 Risc V 汇编语言中找不到旋转操作的特定关键字 看起来扩展 B 最终应该定义这样的指令 在那之前你必须使用左移和右移来组合它 这是 MIPS32R2 rotrv
  • MINI-UTDE 10 BASE-T 集成控制器

    MINI UTDE 10 BASE T 集成控制器 MINI UTDE 10 BASE T 拥有多达三个本地I O板和远程I OS总线通信 为用户提供了一系列生产单元功能的单一控制点 包括诸如夹头 反馈器和辅助机器等外围生产设备 支持所有主
  • 为什么 RV64 为 32 位操作而不是 64 位操作引入新的操作码

    在浏览 RISC V 规范时 我注意到 64 位版本与 32 位版本的不同之处在于 它 将寄存器扩展至 64 位 更改了指令以作用于整个 64 位范围 添加了执行 32 位操作的新指令 这使得 RV32 代码与 RV64 不兼容 但是 如果
  • 裸机 RISC-V CPU - 处理器如何知道从哪个地址开始获取指令?

    我正在设计自己的 RISC V CPU 并且已经能够实现一些指令代码 我已经安装了 RV32I 版本的 GCC 编译器 所以我现在有了汇编器riscv32 unknown elf as可用的 我正在尝试仅用一条指令来汇编一个程序 simpl
  • ESP10B 锁定连接器

    ESP10B 锁定连接器 ESP10B 电机新增内容包括双极型号标准 NEMA 尺寸 17 23 和 34 的步进电机现在包括输出扭矩范围从 61 盎司英寸到 1291 盎司英寸的双极型号 该电机配有带锁定连接器的尾缆 可轻松连接 每转可步
  • Chisel3:对 Vector IO 的多位切片的部分分配

    可以对向量 IO 进行部分赋值 如下所示 import chisel3 class example 1 extends Module val io IO new Bundle val in1 Input Vec 4 Bool val out
  • RISC-V指令集中的FENCE指令是什么意思?

    在浏览 RISC V ISA 时 我在内存模型部分看到了一条指令 FENCE 指令 它到底是什么意思 RISC V ISA 使用宽松的内存模型 其中一个线程执行的加载和存储的顺序在另一个线程看到时可能不同 这样做是为了启用提高内存系统性能的

随机推荐