文章目录
- 前言
- 一、vscode搭建scala开发环境
- 1.1 安装Scala官方插件
- 1.2 创建hello_world.scala文件
- 1.3 确认java的版本(博主使用的是1.8)
- 1.4 下载Scala Windows版本的二进制文件
- 1.5 配置环境变量
- 1.6 交互模式测试一下
- 1.7 vscode运行scala
- 二、windows安装sbt
- 2.1 下载sbt
- 2.2 设置环境变量
- 2.3 sbt配置
- 2.4 设置阿里云镜像
- 2.5 验证
- 三、用Chisel点亮FPGA小灯
- 3.1 参考文档
- 3.2 得到Verilog文件
- 1. 环境搭建
- 2. 克隆项目
- 3. 编译运行
- 4. 生成Verilog文件
- 3.3 上板验证
- 1. 创建quartus项目
- 2. 加入.v文件
- 3. 绑定引脚
- 4. 上板烧录
- 四、在DE2-115开发板上重做Verilog实验
- 4.1 流水灯
- 总结
- 参考
前言
由于verilog效率比较低下,重复劳动太多了QAQ
所以打算用近两年比较火的chisel进行开发。
于是先装一波环境,踩了一天的坑。
传统数字芯片的RTL设计采用Verilog语言为主,Chisel语言的全称是Constructing Harward in Scala Embeded Language,即在Scala语言中导入Chisel3库,即可使用Chisel语言。其特点是面向对象编程,可以方便地参数化定制硬件电路,加快设计流程。目前在RISC-V生态中应用较多,中科院计算所主持的培育下一代处理器设计人才的“一生一芯”项目也在极力推进该语言。
一、vscode搭建scala开发环境
1.1 安装Scala官方插件
在VS Code中安装插件,先安装 Scala Syntax (official)
,再安装 Scala (Metals)
:
(官方插件,有个语法高亮功能也挺香的)
1.2 创建hello_world.scala文件
代码如下:
object HelloWorld
{ def main(args: Array[String]): Unit = {println("Hello, world!") }
}
1.3 确认java的版本(博主使用的是1.8)
1.4 下载Scala Windows版本的二进制文件
下载链接:
https://downloads.lightbend.com/scala/2.13.3/scala-2.13.3.msi
双击进行安装,并一路 next
记住安装路径,等下配置环境变量需要用
博主的安装路径为:
1.5 配置环境变量
1.刚刚让记的那个 安装路径
2.PATH变量下再新增值
至此 安装完毕
。
1.6 交互模式测试一下
至此 Scala开发环境搭建成功
1.7 vscode运行scala
二、windows安装sbt
2.1 下载sbt
官网:http://www.scala-sbt.org/download.html
无脑执行下一步即可,注意 记住安装位置 ,方便后续环境变量的配置
2.2 设置环境变量
#SBT_HOME
设置为sbt解压目录,例如:
SBT_HOME=C:\Programs\sbt;
添加到 系统变量 中:
添加到 path 中:
2.3 sbt配置
修改 sbt\conf\sbtconfig.txt
为以下内容:
# sbt configuration file for Windows# Set the java args#-mem 1024 was added in sbt.bat as default-Xms1024m
-Xmx1024m
-Xss4M
-XX:ReservedCodeCacheSize=128m# Set the extra sbt options-Dsbt.log.format=true
-Dsbt.boot.directory=D:/SoftWare/scala-2.13.3/sbt/boot/
-Dsbt.global.base=D:/SoftWare/scala-2.13.3/sbt/.sbt
-Dsbt.ivy.home=D:/SoftWare/scala-2.13.3/sbt/.ivy2
-Dsbt.repository.config=D:/SoftWare/scala-2.13.3/sbt/conf/repo.properties
-Dsbt.override.build.repos=true
2.4 设置阿里云镜像
国内的网络环境复杂,阿里云还挺好用的,在 sbt\conf\
下新建 repo.properties
文件,内容为:
[repositories]localaliyun-central: https://maven.aliyun.com/repository/centralaliyun-public: https://maven.aliyun.com/repository/publicjcenter: https://jcenter.bintray.com/repo1: https://repo1.maven.org/maven2/store_2: https://repo2.maven.org/maven2/aliyun-releases: https://maven.aliyun.com/repository/releasesaliyun-apache-snapshots: https://maven.aliyun.com/repository/apache-snapshotsaliyun-google: https://maven.aliyun.com/repository/googlealiyun-jcenter: https://maven.aliyun.com/repository/jcenteraliyun-spring: https://maven.aliyun.com/repository/springaliyun-spring-plugin: https://maven.aliyun.com/repository/spring-pluginsbt-plugin: https://repo.scala-sbt.org/scalasbt/sbt-plugin-releases/sonatype: https://oss.sonatype.org/content/repositories/snapshots typesafe: https://repo.typesafe.com/typesafe/ivy-releases/, [organization]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext], bootOnlytypesafe2: https://repo.typesafe.com/typesafe/releases/atlassian: https://packages.atlassian.com/content/repositories/atlassian-public/spring-plugin: https://repo.spring.io/plugins-release/hortonworks: https://repo.hortonworks.com/content/repositories/releases/
2.5 验证
完成后打开cmd,输入 sbt,可能会有一段下载依赖包的过程,成功后会进入命令行,即sbt安装成功。
退出方式:在命令框中输入 exit 即可退出:
三、用Chisel点亮FPGA小灯
3.1 参考文档
参考的chisel书为chisel-book,是一个PDF文档,
Chisel-book: https://wwu.lanzoue.com/isdim08x8x5i
3.2 得到Verilog文件
1. 环境搭建
找到其中 WINDOWS开发环境搭建。
OK,按着以上内容下载所需要的软件(前面我们已经配置好了环境)。
question: 哪能找到一个Chisel例程?
OK,继续看这本书,这是本好书,Hello world例程书里有了,代码在Git上
2. 克隆项目
继续找到了GIT上的chisel-examples.
OK 点击去GIT上 克隆下来,
github:https://github.com/schoeberl/chisel-examples
好了,找到helloworld例程了。现在想想例程怎么编译?生成Verilog代码在哪?
书中3.7章节有写
3. 编译运行
书里只写了Chisel下的编译生成。至于下载到FPGA文档里说要自己动手,不在文档教程内了。
具体流程:
cmd命令下,
git clone https://github.com/schoeberl/chisel-examples.git
cd chisel-examples/hello-world/
执行编译 sbt run
第一次编译需要等待很长时间,然后显示成功。(因为我编译过了,所以第二次很快)。
Hello.scala
//点亮小灯
/** This code is a minimal hardware described in Chisel.* * Blinking LED: the FPGA version of Hello World*/
//
import chisel3._
//
/*** 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.Uwhen(cntReg === CNT_MAX) {cntReg := 0.UblkReg := ~blkReg}io.led := blkReg
}
//
/*** An object extending App to generate the Verilog code.*/
object Hello extends App {(new chisel3.stage.ChiselStage).emitVerilog(new Hello())
}
4. 生成Verilog文件
OK,现在找生成的Verilog,书中说是 Hello.v文件
。
生成的 Hello.v 文件:
module Hello(input clock,input reset,output io_led
);
`ifdef RANDOMIZE_REG_INITreg [31:0] _RAND_0;reg [31:0] _RAND_1;
`endif // RANDOMIZE_REG_INITreg [31:0] cntReg; // @[Hello.scala 23:23]reg blkReg; // @[Hello.scala 24:23]wire [31:0] _cntReg_T_1 = cntReg + 32'h1; // @[Hello.scala 26:20]assign io_led = blkReg; // @[Hello.scala 31:10]always @(posedge clock) beginif (reset) begin // @[Hello.scala 23:23]cntReg <= 32'h0; // @[Hello.scala 23:23]end else if (cntReg == 32'h17d783f) begin // @[Hello.scala 27:28]cntReg <= 32'h0; // @[Hello.scala 28:12]end else begincntReg <= _cntReg_T_1; // @[Hello.scala 26:10]endif (reset) begin // @[Hello.scala 24:23]blkReg <= 1'h0; // @[Hello.scala 24:23]end else if (cntReg == 32'h17d783f) begin // @[Hello.scala 27:28]blkReg <= ~blkReg; // @[Hello.scala 29:12]endend
// Register and memory initialization
`ifdef RANDOMIZE_GARBAGE_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_INVALID_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_REG_INIT
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_MEM_INIT
`define RANDOMIZE
`endif
`ifndef RANDOM
`define RANDOM $random
`endif
`ifdef RANDOMIZE_MEM_INITinteger initvar;
`endif
`ifndef SYNTHESIS
`ifdef FIRRTL_BEFORE_INITIAL
`FIRRTL_BEFORE_INITIAL
`endif
initial begin`ifdef RANDOMIZE`ifdef INIT_RANDOM`INIT_RANDOM`endif`ifndef VERILATOR`ifdef RANDOMIZE_DELAY#`RANDOMIZE_DELAY begin end`else#0.002 begin end`endif`endif
`ifdef RANDOMIZE_REG_INIT_RAND_0 = {1{`RANDOM}};cntReg = _RAND_0[31:0];_RAND_1 = {1{`RANDOM}};blkReg = _RAND_1[0:0];
`endif // RANDOMIZE_REG_INIT`endif // RANDOMIZE
end // initial
`ifdef FIRRTL_AFTER_INITIAL
`FIRRTL_AFTER_INITIAL
`endif
`endif // SYNTHESIS
endmodule
以及顶层文件 hello_top.v
:
hello_top.v
/* Minimal top level for the Chisel Hello World.Wire reset to 0. */module hello_top(input clk, output led);wire h_io_led;wire res;assign led = h_io_led;assign res = 1'h0;Hello h(.clock(clk), .reset(res),.io_led( h_io_led ));
endmodule
3.3 上板验证
1. 创建quartus项目
板子型号为 EP4CE115F29C7
2. 加入.v文件
将生成的 Hello.v文件
和 hello_top.v文件
添加到项目中,并设置hello_top.v为顶层文件
3. 绑定引脚
根据技术文档,led的引脚如下,任意选择一个led
绑定引脚
4. 上板烧录
实现效果:
四、在DE2-115开发板上重做Verilog实验
4.1 流水灯
修改 Hello.scala 文件为:
import chisel3._
import chisel3.util._class Hello extends Module {val io = IO(new Bundle {val led = Output(UInt(8.W)) // 8 位 LED 输出})val maxCount = (50000000 / 10).U // 调整这个参数改变流水灯的速度(DE2-115 使用 50MHz 时钟)val counter = RegInit(0.U(32.W))val position = RegInit(0.U(3.W))// 计数器逻辑counter := counter + 1.Uwhen(counter === maxCount) {counter := 0.Uwhen(position === 7.U) {position := 0.U}.otherwise {position := position + 1.U}}// LED 输出逻辑io.led := (1.U << position)
}object Hello extends App {(new chisel3.stage.ChiselStage).emitVerilog(new Hello())
}
重新运行:
生成的Hello.v 文件,直接将该文件设置为顶层文件:
module Hello(input clock,input reset,output [7:0] io_led
);
`ifdef RANDOMIZE_REG_INITreg [31:0] _RAND_0;reg [31:0] _RAND_1;
`endif // RANDOMIZE_REG_INITreg [31:0] counter; // @[Hello.scala 57:24]reg [2:0] position; // @[Hello.scala 58:25]wire [31:0] _counter_T_1 = counter + 32'h1; // @[Hello.scala 61:22]wire [2:0] _position_T_1 = position + 3'h1; // @[Hello.scala 67:28]assign io_led = 8'h1 << position; // @[Hello.scala 72:18]always @(posedge clock) beginif (reset) begin // @[Hello.scala 57:24]counter <= 32'h0; // @[Hello.scala 57:24]end else if (counter == 32'h4c4b40) begin // @[Hello.scala 62:30]counter <= 32'h0; // @[Hello.scala 63:13]end else begincounter <= _counter_T_1; // @[Hello.scala 61:11]endif (reset) begin // @[Hello.scala 58:25]position <= 3'h0; // @[Hello.scala 58:25]end else if (counter == 32'h4c4b40) begin // @[Hello.scala 62:30]if (position == 3'h7) begin // @[Hello.scala 64:28]position <= 3'h0; // @[Hello.scala 65:16]end else beginposition <= _position_T_1; // @[Hello.scala 67:16]endendend
// Register and memory initialization
`ifdef RANDOMIZE_GARBAGE_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_INVALID_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_REG_INIT
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_MEM_INIT
`define RANDOMIZE
`endif
`ifndef RANDOM
`define RANDOM $random
`endif
`ifdef RANDOMIZE_MEM_INITinteger initvar;
`endif
`ifndef SYNTHESIS
`ifdef FIRRTL_BEFORE_INITIAL
`FIRRTL_BEFORE_INITIAL
`endif
initial begin`ifdef RANDOMIZE`ifdef INIT_RANDOM`INIT_RANDOM`endif`ifndef VERILATOR`ifdef RANDOMIZE_DELAY#`RANDOMIZE_DELAY begin end`else#0.002 begin end`endif`endif
`ifdef RANDOMIZE_REG_INIT_RAND_0 = {1{`RANDOM}};counter = _RAND_0[31:0];_RAND_1 = {1{`RANDOM}};position = _RAND_1[2:0];
`endif // RANDOMIZE_REG_INIT`endif // RANDOMIZE
end // initial
`ifdef FIRRTL_AFTER_INITIAL
`FIRRTL_AFTER_INITIAL
`endif
`endif // SYNTHESIS
endmodule
引脚分配:
编译。没有错误了,OK,下载。
没反应!!!!准备要哭了,随便点了个开发板上reset按键,哦,哦,哦,流水灯居然正常工作了。
看看上面代码 ,
好像chisel里面代码生成里面有 if(res_n)判断,猜是判断按键吧?那么我把按键直接去掉试试?
好了,在逻辑判断里面,设置为复位之后有效即可,原先是需要手动按键才能触发:
实验效果:
总结
学习Chisel语言是一段既充满挑战又极具启发性的旅程。Chisel以Scala为基础,它的抽象级别高,极大提升了硬件设计效率,让代码更简洁且易于维护。通过Chisel,我体验了用近似软件工程的思维做硬件设计的便捷,特别是在模块化、参数化设计上的优势,这为复用代码和快速迭代创造了条件。Chisel结合Scala的强大生态,使得测试和验证更加高效,同时降低了硬件设计的学习曲线,尤其适合教学和研究用途。亲手实践,如在IDEA中配置环境并实现流水灯项目,让我深刻理解了理论到实践的每一步,过程中遇到问题的解决也锻炼了自我探索能力。总之,Chisel正引领硬件设计的新风潮,它不仅丰富了我的技术栈,也激发了对硬件设计未来无限可能的想象。
参考
WIN10系统下,用Chisel开发入门FPGA的HelloWorld呼吸灯
【多图预警】Windows 安装 SBT、IDEA 使用 SBT 构建项目指南
Scala安装出现neither build.sbt nor a…问题解决
Chisel入门之路(一)之在windows下vscode搭建|部署Scala2.13.3开发环境|安装教程
Chisel速成——跟着这个Chisel教程来就行了(已完结)
【IC设计】Windows下基于IDEA的Chisel环境安装教程(图文并茂)