Verilog实战学习到RiscV - 4 : ICEStick 评估板计数器

打印 上一主题 下一主题

主题 663|帖子 663|积分 1989

这篇是关于always 时序逻辑的。直接上代码。
引脚配置文件

  1. set_io  leds[0]  99
  2. set_io  leds[1]  98
  3. set_io  leds[2]  97
  4. set_io  leds[3]  96
  5. set_io  -pullup yes pmod[0]  78
  6. set_io  -pullup yes pmod[1]  79
复制代码
参看icestick的原理图

这里在pmod上使用了内部的上拉电阻。
代码

  1. module top_counter (
  2.     input [1:0] pmod,  // 对应icestick IO
  3.     output reg [3:0] leds   // reg: 综合工具Yosys会将leds连接到D-FF
  4. );
  5.     wire clk;
  6.     wire rst;
  7.     assign clk = ~pmod[0];
  8.     assign rst = ~pmod[1];
  9.     always @(posedge clk or posedge rst) begin
  10.         if (rst == 1'b1) begin
  11.             leds <= 4'b0000;
  12.         end
  13.         
  14.         if (clk == 1'b1) begin
  15.             leds <= leds + 1'b1;
  16.         end
  17.     end
  18. endmodule
复制代码
这段时序逻辑电路在使用Yosys 综合的时候产生了如下错误:
  1. Creating register for signal `\SB_DFFES.\Q' using process `\SB_DFFES.$proc$/usr/local/bin/../share/yosys/ice40/cells_sim.v:803$203'.
  2.   created $adff cell `$procdff$447' with positive edge clock and positive level reset.
  3. Creating register for signal `\SB_DFFESS.\Q' using process `\SB_DFFESS.$proc$/usr/local/bin/../share/yosys/ice40/cells_sim.v:742$196'.
  4.   created $dff cell `$procdff$448' with positive edge clock.
  5. Creating register for signal `\SB_DFFER.\Q' using process `\SB_DFFER.$proc$/usr/local/bin/../share/yosys/ice40/cells_sim.v:662$192'.
  6.   created $adff cell `$procdff$449' with positive edge clock and positive level reset.
  7. Creating register for signal `\SB_DFFESR.\Q' using process `\SB_DFFESR.$proc$/usr/local/bin/../share/yosys/ice40/cells_sim.v:601$185'.
  8.   created $dff cell `$procdff$450' with positive edge clock.
  9. Creating register for signal `\SB_DFFS.\Q' using process `\SB_DFFS.$proc$/usr/local/bin/../share/yosys/ice40/cells_sim.v:527$182'.
  10.   created $adff cell `$procdff$451' with positive edge clock and positive level reset.
  11. Creating register for signal `\SB_DFFSS.\Q' using process `\SB_DFFSS.$proc$/usr/local/bin/../share/yosys/ice40/cells_sim.v:477$179'.
  12.   created $dff cell `$procdff$452' with positive edge clock.
  13. Creating register for signal `\SB_DFFR.\Q' using process `\SB_DFFR.$proc$/usr/local/bin/../share/yosys/ice40/cells_sim.v:406$176'.
  14.   created $adff cell `$procdff$453' with positive edge clock and positive level reset.
  15. Creating register for signal `\SB_DFFSR.\Q' using process `\SB_DFFSR.$proc$/usr/local/bin/../share/yosys/ice40/cells_sim.v:356$173'.
  16.   created $dff cell `$procdff$454' with positive edge clock.
  17. Creating register for signal `\SB_DFFE.\Q' using process `\SB_DFFE.$proc$/usr/local/bin/../share/yosys/ice40/cells_sim.v:311$171'.
  18.   created $dff cell `$procdff$455' with positive edge clock.
  19. Creating register for signal `\SB_DFF.\Q' using process `\SB_DFF.$proc$/usr/local/bin/../share/yosys/ice40/cells_sim.v:271$169'.
  20.   created $dff cell `$procdff$456' with positive edge clock.
  21. Creating register for signal `\top_counter.\leds' using process `\top_counter.$proc$top_counter.v:13$383'.
  22. ERROR: Multiple edge sensitive events found for this signal!
  23. make: *** [Makefile:23: top_counter.json] Error 1
复制代码
两个if语句处理两种环境没有题目啊? 但实在,这是一个典型的C语言嵌入式程序猿会犯的典型错误。以下详细表明。
时钟和复位信号的处理

在时序逻辑计划中,always块的触发条件决定了什么时候实行其中的逻辑。在Verilog代码中,我们必要处理两个信号:
时钟信号(clk):通常用于在每个时钟周期(上升沿或下降沿)更新状态。
复位信号(rst):通常用于在复位条件下重置状态,一般来说是异步复位,即不依赖时钟。
为什么不在always块内部检查时钟电平?



  • 冗余:在always块中检查clk == 1’b1是多余的,因为我们已经在触发条件中指定了posedge clk,这意味着我们只在clk上升沿时实行代码。在实行代码时,clk一定处于高电平,因此再检查clk的电平是多余的。
  • 潜在错误:在时序逻辑中直接检查时钟的电平大概导致不一致或错误的活动,特别是在综合工具和仿真环境中。
这就表明了Yosys 所报的错误:
  1. ERROR: Multiple edge sensitive events found for this signal!
复制代码
精确的计划方式

在时序逻辑计划中,我们不应该在always块内部检查时钟信号的电平(例如clk == 1’b1),因为我们已经在always块的触发条件中指定了对时钟上升沿的响应。对于复位信号,一般我们会处理为同步或异步复位,这取决于计划要求。代码中已经指定了posedge rst,这通常表示异步复位。
修正后的always块
  1. always @(posedge clk or posedge rst) begin
  2.     if (rst) begin
  3.         leds <= 4'b0000; // 异步复位
  4.     end else begin
  5.         leds <= leds + 1'b1; // 时钟上升沿时计数
  6.     end
  7. end
复制代码

  • 触发条件:


  • always @(posedge clk or posedge rst)表示每当clk上升沿或rst上升沿时,这个块中的代码会被实行。
  • 触发条件是“边沿触发”(edge-sensitive),即代码只会在信号的边沿(上升或下降)发生变化时实行,而不会响应信号的电平状态。

  • 复位处理:


  • 在块的开头,我们首先检查复位信号rst是否为高电平(有效),如果是,则将leds重置为4’b0000。
  • 这里的复位是异步的,因为复位发生时不必要等待时钟上升沿,只要rst变为高电平就立刻重置。

  • 计数逻辑:


  • 如果复位信号不为高电平(即rst无效),那么在时钟的上升沿,leds会递增1。
  • 这里的计数逻辑是同步的,因为计数操纵仅在时钟的上升沿进行。
Makefile

上篇一条条输入命令有点麻烦,这次我写了一个 Makefile 方便很多。
  1. # Define the top-level module and output files
  2. TOP = top_counter
  3. BLIF = top_counter.blif
  4. JSON = top_counter.json
  5. ASC = top_counter.asc
  6. BIN = top_counter.bin
  7. PCF = pinmap.pcf
  8. # Define the Yosys, nextpnr, and icestorm commands
  9. YOSYS_CMD = yosys -p "synth_ice40 -top $(TOP) -blif $(BLIF) -json $(JSON)" $(TOP).v
  10. NEXTPNR_CMD = nextpnr-ice40 --hx1k --json $(JSON) --pcf $(PCF) --asc $(ASC)
  11. ICEPACK_CMD = icepack $(ASC) $(BIN)
  12. ICETIME_CMD = icetime -tmd hx1k $(ASC)
  13. ICEPROG_CMD = iceprog $(BIN)
  14. # Default target
  15. all: $(BIN)
  16. # Yosys synthesis
  17. $(BLIF) $(JSON): $(TOP).v
  18.         $(YOSYS_CMD)
  19. # nextpnr place and route
  20. $(ASC): $(JSON) $(PCF)
  21.         $(NEXTPNR_CMD)
  22. # Icepack to create a binary file
  23. $(BIN): $(ASC)
  24.         $(ICEPACK_CMD)
  25. # Timing analysis (optional)
  26. timing: $(ASC)
  27.         icetime -tmd hx1k $(ASC)
  28. # Program the FPGA
  29. program: $(BIN)
  30.         iceprog $(BIN)
  31. # Clean up
  32. clean:
  33.         rm -f $(BLIF) $(JSON) $(ASC) $(BIN)
  34. .PHONY: all clean timing program
复制代码
烧写

  1. $ iceprog top_counter.bin
  2. init..
  3. cdone: high
  4. reset..
  5. cdone: low
  6. flash ID: 0x20 0xBA 0x16 0x10 0x00 0x00 0x23 0x72 0x21 0x19 0x05 0x00 0x58 0x00 0x21 0x16 0x07 0x17 0xCE 0x6D
  7. file size: 32220
  8. erase 64kB sector at 0x000000..
  9. programming..
  10. done.                 
  11. reading..
  12. VERIFY OK            
  13. cdone: high
  14. Bye.
复制代码
结果

我没有按钮,就随便用几根线模拟一下按键按下的时候的GND 下降沿和 被内部上拉电阻上拉后的上升沿。
这里时钟用一根连线模拟,否则时钟跳得太快看不见led变化。背面我们可以做一个分频。
白线 = CLK
灰线 = RST


  • Count up




  • Reset


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

盛世宏图

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表