文章目錄
- 前言
- 一、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環境安裝教程(圖文并茂)