|
本帖最后由 dukelec 于 2019-8-28 22:16 编辑
很多人想学 fpga,即使是由简单的流水灯开始学,但也经常学不下去。
我觉得,原因之一是:现有的 fpga ide 软件太复杂,动不动 10 几个 G 大小,过于复杂的开发环境给学者带来不小的阻力。
先简单为新手介绍下 verilog 的特点。(下面的 always 主要是指时钟驱动型的。)
学 fpga,最简单是学 verilog 语言(相对 vhdl),其实,也不复杂,跟 c 语言相比,多了并行的思想(每个 always 各自独立运行),和很多限制而已。
比如,我觉得最关键的几点:
1. 一个 reg 变量,可以被多个 always 读取,但只能被一个 always 赋值。
如果只写一个 always 就不会有限制,实现一些功能会简单很多,但一个 always 很大的话,生成的电路性能会很差,代码也不好维护,所以要尽可能小一点,模块化一些。
2. 在一个 always 中,赋值是下一次循环才生效,相比 c 有比较大区别:
- always @(posedge clk) begin
- counter <= counter + 1; // 譬如本次自加前 counter 等于 5
- data <= counter; // 自加后,给 data 赋值,赋的值依然是 5,即使颠倒这两条语句也没有区别
- end
复制代码
3. 但也不是说所有语句都可以调换顺序,譬如为同一个变量赋值,第二次赋值会覆盖第一次:
(常用此方式,输出一个 flag 脉冲)
- always @(posedge clk) begin
- flag <= 0; // 默认赋值 0 (如果把此句放到尾部,那么 flag 将永远为 0)
- if (a == b)
- flag <= 1; // 当条件成立,改变 flag 的赋值为 1
- end
复制代码
其它的限制是,没法像 c 语言那样调用函数、for 循环遍历,很多情况都要很笨的写死。剩下其实跟 c 语言差不多。
## 下面介绍正题,先是单独使用 iverilog
可综合的 led 闪烁示例代码在 https://github.com/dukelec/cdpga ... ga_b/code/cdpga_bx/ 目录下的 cdpga_bx.v
单独 iverilog 测试代码在 https://github.com/dukelec/cdpga ... pga_bx/test_verilog 目录下的 cdpga_tb.v
cdpga_bx.v 的主要内容是:
- reg [7:0] counter;
- always @(posedge clk or negedge reset_n)
- if (!reset_n) begin
- counter <= 0;
- tx_en <= 0;
- end
- else begin
- counter <= counter + 1'b1;
- if (counter >= 10) begin
- counter <= 0;
- tx_en <= !tx_en; // tx_en 接 led
- end
- end
复制代码
cdpga_tb.v 中比较关键的是最后面的:
- initial begin
- $dumpfile("cdpga_bx.vcd"); // 把当前和子模块的所有数据波形保存到该文件中
- $dumpvars();
- end
复制代码
最后两条命令进行仿真:
- cdpga_bx/test_verilog $ iverilog -o cdpga_bx cdpga_tb.v cdpga_pll_sim.v ../cdpga_bx.v
- cdpga_bx/test_verilog $ vvp cdpga_bx
- VCD info: dumpfile cdpga_bx.vcd opened for output.
- 20000 tx: 0, tx_en: 0
- 40000 tx: 1, tx_en: 0
- 60000 tx: 1, tx_en: 1
- 80000 tx: 1, tx_en: 0
- 2100000 tx: 1, tx_en: 1
复制代码
第一个命令是编译,跟 gcc 命令差不多,pll 可以忽略,因为示例代码有调用 pll,所以这里用个空的、假的代替,防止编译报错而已。
第二个命令是运行仿真,打印的 tx_en 数据是调用 $display 单独显示出来的,跟 printf 差不多。
仿真结束后,就可以使用开源的 GTKWave 工具查看生成的波形文件。
GTKWave 非常好用,你只要打开一次波形文件,接下来改了代码重新仿真生成新的波形文件后,只要点一下刷新按钮就可以了。
iverilog 要用 v10 以上版本。
GTKWave 的截图可以参考下面一节。
## 用 cocotb,使用 python 仿真
由于 verilog 不能像 c 那样调用函数,用来写 test bench 很麻烦,所以复杂的系统可以用 SystemVerilog 等更高阶的语言来写,
但是,依然没有更通用的 python 方便,譬如用 python 甚至可以很方便的实现图片和视频数据的仿真。
操作方法是先下载 cocotb:https://github.com/cocotb/cocotb
下载下来不用管它。
然后参考 https://github.com/dukelec/cdpga ... dpga_bx/test_python
建立一个 cdpga_bx_wrapper.v,目的是生成 cdpga_bx.vcd 波形文件。
然后最核心的 python 测试脚本 test_cdpga_bx.py,完整内容:
- import cocotb
- from cocotb.binary import BinaryValue
- from cocotb.triggers import RisingEdge, ReadOnly, Timer
- from cocotb.clock import Clock
- from cocotb.result import ReturnValue, TestFailure
- CLK_FREQ = 40000000
- CLK_PERIOD = 1000000000000 / CLK_FREQ
- @cocotb.test()
- def test_cdpga_bx(dut):
- """
- test_cdpga_bx
- """
- dut._log.info("test_cdpga_bx start.")
- dut.rx = 0
- cocotb.fork(Clock(dut.clk, CLK_PERIOD).start())
- yield Timer(5000000) # wait reset
-
- dut._log.info("get tx: %d, tx_en: %d" % (dut.tx, dut.tx_en))
- dut._log.info("set rx = 1")
- dut.rx = 1;
-
- yield Timer(CLK_PERIOD)
- dut._log.info("get tx: %d, tx_en: %d" % (dut.tx, dut.tx_en))
- dut._log.info("set rx = 0")
- dut.rx = 0;
-
- yield Timer(CLK_PERIOD * 6)
- dut._log.info("get tx: %d, tx_en: %d" % (dut.tx, dut.tx_en))
- dut._log.info("set rx = 1")
- dut.rx = 1;
-
- yield Timer(5000000)
- dut._log.info("test_cdpga_bx done.")
复制代码
然后是一个 makefile:
- CDCTL_HDL = $(PWD)/..
- VERILOG_SOURCES = $(PWD)/cdpga_bx_wrapper.v \
- $(PWD)/cdpga_pll_sim.v \
- $(CDCTL_HDL)/cdpga_bx.v
- TOPLEVEL = cdpga_bx_wrapper
- MODULE = test_cdpga_bx
- include $(COCOTB)/makefiles/Makefile.inc
- include $(COCOTB)/makefiles/Makefile.sim
复制代码
最后用一条命令就可以生成波形文件:
- $ COCOTB=/path/to/cocotb make
复制代码
同样是用 GTKWave 查看波形:
clk_i 和 clk_o 是接外部无源晶体的,内部是一个反向器,为了节省成本。具体细节可参考:http://blog.dukelec.com/crystal-input-to-fpga
关于 cocotb 具体用法请自行前往其项目专页查阅相关文档。
cocotb 调用的是标准的 verilog 仿真后台的 c 语言的 api 接口,理论上商业 ide 也是可以集成使用的,如果现在不支持,以后也可能会支持。
(cocotb 默認調用 iverilog 進行仿真。)
这几个工具应该都是可以跨平台的,只不过,做开发,linux 下最简单方便。
再次附上 linux 学习方法:https://www.amobbs.com/thread-5715819-1-1.html (1 楼) |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
|