├── .gitignore ├── Makefile ├── README.md ├── build.sc ├── sim_c ├── include │ └── sim.h ├── main.cc └── sim.cc └── src └── main └── scala ├── fsm └── fsm.scala └── top.scala /.gitignore: -------------------------------------------------------------------------------- 1 | /* 2 | !.gitignore 3 | !build.sc 4 | !Makefile 5 | !/src 6 | !/sim_c 7 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TOP = top 2 | MAIN = top.topMain 3 | BUILD_DIR = ./build 4 | OBJ_DIR = $(BUILD_DIR)/OBJ_DIR 5 | TOPNAME = top 6 | TOP_V = $(BUILD_DIR)/verilog/$(TOPNAME).v 7 | 8 | SCALA_FILE = $(shell find ./src/main -name '*.scala') 9 | 10 | VERILATOR = verilator 11 | VERILATOR_COVERAGE = verilator_coverage 12 | # verilator flags 13 | VERILATOR_FLAGS += -Wall -MMD --trace --build -cc --exe \ 14 | -O3 --x-assign fast --x-initial fast --noassert -report-unoptflat 15 | 16 | # timescale set 17 | VERILATOR_FLAGS += --timescale 1us/1us 18 | 19 | verilog: $(SCALA_FILE) 20 | @mkdir -p $(BUILD_DIR)/verilog 21 | mill -i $(TOP).runMain $(MAIN) -td $(BUILD_DIR)/verilog --emit-modules verilog 22 | 23 | vcd ?= 24 | ifeq ($(vcd), 1) 25 | CFLAGS += -DVCD 26 | endif 27 | 28 | # C flags 29 | INC_PATH += $(abspath ./sim_c/include) 30 | INCFLAGS = $(addprefix -I, $(INC_PATH)) 31 | CFLAGS += $(INCFLAGS) $(CFLAGS_SIM) -DTOP_NAME="V$(TOPNAME)" 32 | 33 | # source file 34 | CSRCS = $(shell find $(abspath ./sim_c) -name "*.c" -or -name "*.cc" -or -name "*.cpp") 35 | 36 | BIN = $(BUILD_DIR)/$(TOP) 37 | NPC_EXEC := $(BIN) 38 | 39 | sim: $(CSRCS) verilog 40 | @rm -rf $(OBJ_DIR) 41 | $(VERILATOR) $(VERILATOR_FLAGS) -top $(TOPNAME) $(CSRCS) $(wildcard $(BUILD_DIR)/verilog/*.v) \ 42 | $(addprefix -CFLAGS , $(CFLAGS)) $(addprefix -LDFLAGS , $(LDFLAGS)) \ 43 | --Mdir $(OBJ_DIR) -o $(abspath $(BIN)) 44 | 45 | run: 46 | @echo 47 | @echo "------------ RUN --------------" 48 | $(NPC_EXEC) 49 | ifeq ($(vcd), 1) 50 | @echo "----- see vcd file in logs dir ----" 51 | else 52 | @echo "----- if you need vcd file. add vcd=1 to make ----" 53 | endif 54 | 55 | srun: sim run 56 | 57 | clean: 58 | -rm -rf $(BUILD_DIR) logs 59 | 60 | clean_mill: 61 | -rm -rf out 62 | 63 | clean_all: clean clean_mill 64 | 65 | .PHONY: clean clean_all clean_mill srun run sim verilog 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # chisel-template 2 | 自建 chisel 工程模板 3 | 4 | # 概述 5 | 6 | 本模板适用于编写 chisel 并使用 Verilator 进行仿真的电路设计。在 Makefile 中指定了 Chisel 转 Verilog,编译仿真文件,执行仿真文件,编译并执行仿真文件等目标,使用 mill 工具进行 Chisel 工程的构建。可以方便的实现 Chisel 工程的练习。 7 | 8 | 本模板编写了一个使用 `Mux` 和 `RegNext` 实现的序列检测模块。 9 | 10 | # 运行工程 11 | 12 | ## 获取代码 13 | 14 | ```bash 15 | git clone https://github.com/light-ly/chisel-template 16 | ``` 17 | 18 | ## 运行工程 19 | 20 | ### 编译仿真目标并运行: 21 | 22 | ```bash 23 | # 编译并运行 24 | make srun 25 | ``` 26 | 27 | 或者: 28 | 29 | ```bash 30 | ## 只编译不运行 31 | make sim 32 | ## 运行编译好的仿真文件 33 | make run 34 | ``` 35 | 36 | ### 带仿真波形文件(vcd)的仿真 37 | 38 | ```bash 39 | make vcd=1 srun 40 | ``` 41 | 42 | 或 43 | 44 | ```bash 45 | make vcd=1 sim 46 | make run 47 | ``` 48 | 49 | 查看仿真文件 50 | 51 | ```bash 52 | gtkwave logs/top.vcd 53 | ``` 54 | 55 | ### Chisel 转 Verilog 56 | 57 | ```bash 58 | make verilog 59 | ``` 60 | 61 | 生成的 Verilog 文件和编译出的可执行仿真文件都会在 build 目录中,mill 的输出会生成在 out 文件夹中,verilator 编译的中间结果在 build/OBJ_DIR 中,仿真波形会输出在 logs 文件夹中。 62 | 63 | ## 清理仿真文件 64 | 65 | ```bash 66 | # 删除 build,out,logs 目录 67 | make clean_all 68 | 69 | # 删除 build,logs,保留 out。即删除 verilator 输出的仿真文件和 verilog 文件,保留 mill 构建的输出 70 | make clean 71 | 72 | # 删除 mill 构建的输出 out 73 | make clean_mill 74 | ``` 75 | 76 | # 编写自己的工程 77 | 78 | 请移步到: 79 | - [我的博客,Chisel 工程框架搭建(mill + verilator)](https://light-liuyi.top:2001/2023/07/10/chisel-template) 80 | - [我的知乎,Chisel 工程框架搭建(mill + verilator)](https://zhuanlan.zhihu.com/p/642588946) 81 | -------------------------------------------------------------------------------- /build.sc: -------------------------------------------------------------------------------- 1 | import mill._, scalalib._ 2 | import os.Path 3 | 4 | object top extends ScalaModule { 5 | def scalaVersion = "2.12.12" 6 | override def millSourcePath = os.pwd 7 | def scalaOptions = Seq( 8 | "-language:reflectiveCalls", 9 | "-deprecation", 10 | "-feature", 11 | "-Xcheckinit", 12 | "-P:chiselplugin:genBundleElements", 13 | "-Xsource:2.11" 14 | ) 15 | 16 | override def ivyDeps = Agg( 17 | ivy"edu.berkeley.cs::chisel3:3.5.0" 18 | ) 19 | 20 | override def scalacPluginIvyDeps = Agg( 21 | ivy"edu.berkeley.cs:::chisel3-plugin:3.5.0", 22 | ) 23 | 24 | } -------------------------------------------------------------------------------- /sim_c/include/sim.h: -------------------------------------------------------------------------------- 1 | #ifndef __SIM_H__ 2 | #define __SIM_H__ 3 | 4 | void single_cycle(); 5 | void reset(int n); 6 | void sim_init(int argc, char *argv[]); 7 | void sim_exit(); 8 | 9 | void sim_main(int argc, char *argv[]); 10 | 11 | #endif -------------------------------------------------------------------------------- /sim_c/main.cc: -------------------------------------------------------------------------------- 1 | #include "sim.h" 2 | 3 | int main(int argc, char *argv[]) { 4 | 5 | sim_main(argc, argv); 6 | 7 | return 0; 8 | } -------------------------------------------------------------------------------- /sim_c/sim.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include "Vtop.h" 6 | #ifdef VCD 7 | #include "verilated_vcd_c.h" 8 | VerilatedVcdC* tfp = nullptr; 9 | #endif 10 | 11 | #include "sim.h" 12 | 13 | using namespace std; 14 | 15 | // init pointers 16 | const std::unique_ptr contextp{new VerilatedContext}; 17 | const std::unique_ptr top{new Vtop{contextp.get(), "TOP"}}; 18 | 19 | /* sim initial */ 20 | void sim_init(int argc, char *argv[]) { 21 | top->reset = 1; 22 | top->clock = 0; 23 | #ifdef VCD 24 | Verilated::mkdir("logs"); 25 | contextp->traceEverOn(true); 26 | tfp = new VerilatedVcdC; 27 | top->trace(tfp, 99); 28 | tfp->open("logs/top.vcd"); 29 | #endif 30 | Verilated::commandArgs(argc,argv); 31 | } 32 | 33 | /* sim exit */ 34 | void sim_exit() { 35 | // finish work, delete pointer 36 | top->final(); 37 | #if VCD 38 | tfp->close(); 39 | tfp = nullptr; 40 | #endif 41 | } 42 | 43 | void single_cycle() { 44 | contextp->timeInc(1); 45 | top->clock = 0; top->eval(); 46 | #ifdef VCD 47 | tfp->dump(contextp->time()); 48 | #endif 49 | 50 | contextp->timeInc(1); 51 | top->clock = 1; top->eval(); 52 | #ifdef VCD 53 | tfp->dump(contextp->time()); 54 | #endif 55 | } 56 | 57 | void reset(int n) { 58 | top->reset = 1; 59 | while (n-- > 0) single_cycle(); 60 | top->reset = 0; 61 | top->eval(); 62 | } 63 | 64 | void sim_main(int argc, char *argv[]) { 65 | sim_init(argc, argv); 66 | reset(10); 67 | 68 | /* main simulation*/ 69 | int sim_time = 0; 70 | int seq_ptr = 0; 71 | int seq[] = {1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0}; 72 | 73 | /* main loop */ 74 | while (!contextp->gotFinish() && (sim_time <= 20)) { 75 | seq_ptr = (seq_ptr + 1) % 14; 76 | top->io_in = seq[seq_ptr]; 77 | single_cycle(); 78 | cout << "in: " << seq[seq_ptr] << "\t"; 79 | cout << "out: " << bitset<1>(top->io_out) < s1, 21 | (state === s1) -> s2, 22 | (state === s2) -> s2, 23 | (state === s3) -> s1)), 24 | MuxCase(s0, Array((state === s0) -> s0, 25 | (state === s1) -> s0, 26 | (state === s2) -> s3, 27 | (state === s3) -> s0))) 28 | 29 | io.out := RegNext((state === s3) & io.in, 0.B) 30 | } -------------------------------------------------------------------------------- /src/main/scala/top.scala: -------------------------------------------------------------------------------- 1 | package top 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | import chisel3.stage._ 6 | 7 | import fsm._ 8 | 9 | class top extends Module { 10 | val io = IO(new Bundle { 11 | val in = Input(UInt(1.W)) 12 | val out = Output(UInt(1.W)) 13 | }) 14 | 15 | val fsm = Module(new FSM) 16 | 17 | fsm.io.in := io.in 18 | io.out := fsm.io.out 19 | 20 | } 21 | 22 | object topMain extends App { 23 | (new ChiselStage).emitVerilog(new top, args) 24 | } 25 | --------------------------------------------------------------------------------