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

news2024/11/27 3:49:36

这篇是关于always 时序逻辑的。直接上代码。

引脚配置文件

set_io  leds[0]  99
set_io  leds[1]  98
set_io  leds[2]  97
set_io  leds[3]  96

set_io  -pullup yes pmod[0]  78
set_io  -pullup yes pmod[1]  79

参看icestick的原理图
请添加图片描述

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

代码

module top_counter (
    input [1:0] pmod,  // 对应icestick IO
    output reg [3:0] leds   // reg: 综合工具Yosys会将leds连接到D-FF
);
    wire clk;
    wire rst;
    assign clk = ~pmod[0];
    assign rst = ~pmod[1];

    always @(posedge clk or posedge rst) begin
        if (rst == 1'b1) begin
            leds <= 4'b0000;
        end 
        
        if (clk == 1'b1) begin
            leds <= leds + 1'b1;
        end

    end
endmodule

这段时序逻辑电路在使用Yosys 综合的时候产生了如下错误:

Creating register for signal `\SB_DFFES.\Q' using process `\SB_DFFES.$proc$/usr/local/bin/../share/yosys/ice40/cells_sim.v:803$203'.
  created $adff cell `$procdff$447' with positive edge clock and positive level reset.
Creating register for signal `\SB_DFFESS.\Q' using process `\SB_DFFESS.$proc$/usr/local/bin/../share/yosys/ice40/cells_sim.v:742$196'.
  created $dff cell `$procdff$448' with positive edge clock.
Creating register for signal `\SB_DFFER.\Q' using process `\SB_DFFER.$proc$/usr/local/bin/../share/yosys/ice40/cells_sim.v:662$192'.
  created $adff cell `$procdff$449' with positive edge clock and positive level reset.
Creating register for signal `\SB_DFFESR.\Q' using process `\SB_DFFESR.$proc$/usr/local/bin/../share/yosys/ice40/cells_sim.v:601$185'.
  created $dff cell `$procdff$450' with positive edge clock.
Creating register for signal `\SB_DFFS.\Q' using process `\SB_DFFS.$proc$/usr/local/bin/../share/yosys/ice40/cells_sim.v:527$182'.
  created $adff cell `$procdff$451' with positive edge clock and positive level reset.
Creating register for signal `\SB_DFFSS.\Q' using process `\SB_DFFSS.$proc$/usr/local/bin/../share/yosys/ice40/cells_sim.v:477$179'.
  created $dff cell `$procdff$452' with positive edge clock.
Creating register for signal `\SB_DFFR.\Q' using process `\SB_DFFR.$proc$/usr/local/bin/../share/yosys/ice40/cells_sim.v:406$176'.
  created $adff cell `$procdff$453' with positive edge clock and positive level reset.
Creating register for signal `\SB_DFFSR.\Q' using process `\SB_DFFSR.$proc$/usr/local/bin/../share/yosys/ice40/cells_sim.v:356$173'.
  created $dff cell `$procdff$454' with positive edge clock.
Creating register for signal `\SB_DFFE.\Q' using process `\SB_DFFE.$proc$/usr/local/bin/../share/yosys/ice40/cells_sim.v:311$171'.
  created $dff cell `$procdff$455' with positive edge clock.
Creating register for signal `\SB_DFF.\Q' using process `\SB_DFF.$proc$/usr/local/bin/../share/yosys/ice40/cells_sim.v:271$169'.
  created $dff cell `$procdff$456' with positive edge clock.
Creating register for signal `\top_counter.\leds' using process `\top_counter.$proc$top_counter.v:13$383'.
ERROR: Multiple edge sensitive events found for this signal!
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 所报的错误:

ERROR: Multiple edge sensitive events found for this signal!

正确的设计方式

在时序逻辑设计中,我们不应该在always块内部检查时钟信号的电平(例如clk == 1’b1),因为我们已经在always块的触发条件中指定了对时钟上升沿的响应。对于复位信号,一般我们会处理为同步或异步复位,这取决于设计要求。代码中已经指定了posedge rst,这通常表示异步复位。

修正后的always块

always @(posedge clk or posedge rst) begin
    if (rst) begin
        leds <= 4'b0000; // 异步复位
    end else begin
        leds <= leds + 1'b1; // 时钟上升沿时计数
    end
end
  1. 触发条件:
  • always @(posedge clk or posedge rst)表示每当clk上升沿或rst上升沿时,这个块中的代码会被执行。
  • 触发条件是“边沿触发”(edge-sensitive),即代码只会在信号的边沿(上升或下降)发生变化时执行,而不会响应信号的电平状态。
  1. 复位处理:
  • 在块的开头,我们首先检查复位信号rst是否为高电平(有效),如果是,则将leds重置为4’b0000。
  • 这里的复位是异步的,因为复位发生时不需要等待时钟上升沿,只要rst变为高电平就立即重置。
  1. 计数逻辑:
  • 如果复位信号不为高电平(即rst无效),那么在时钟的上升沿,leds会递增1。
  • 这里的计数逻辑是同步的,因为计数操作仅在时钟的上升沿进行。

Makefile

上篇一条条输入命令有点麻烦,这次我写了一个 Makefile 方便很多。

# Define the top-level module and output files
TOP = top_counter
BLIF = top_counter.blif
JSON = top_counter.json
ASC = top_counter.asc
BIN = top_counter.bin
PCF = pinmap.pcf

# Define the Yosys, nextpnr, and icestorm commands
YOSYS_CMD = yosys -p "synth_ice40 -top $(TOP) -blif $(BLIF) -json $(JSON)" $(TOP).v
NEXTPNR_CMD = nextpnr-ice40 --hx1k --json $(JSON) --pcf $(PCF) --asc $(ASC)
ICEPACK_CMD = icepack $(ASC) $(BIN)
ICETIME_CMD = icetime -tmd hx1k $(ASC)
ICEPROG_CMD = iceprog $(BIN)

# Default target
all: $(BIN)

# Yosys synthesis
$(BLIF) $(JSON): $(TOP).v
	$(YOSYS_CMD)

# nextpnr place and route 
$(ASC): $(JSON) $(PCF)
	$(NEXTPNR_CMD)

# Icepack to create a binary file
$(BIN): $(ASC)
	$(ICEPACK_CMD)

# Timing analysis (optional)
timing: $(ASC)
	icetime -tmd hx1k $(ASC)

# Program the FPGA
program: $(BIN)
	iceprog $(BIN)

# Clean up
clean:
	rm -f $(BLIF) $(JSON) $(ASC) $(BIN)

.PHONY: all clean timing program

烧写

$ iceprog top_counter.bin 
init..
cdone: high
reset..
cdone: low
flash ID: 0x20 0xBA 0x16 0x10 0x00 0x00 0x23 0x72 0x21 0x19 0x05 0x00 0x58 0x00 0x21 0x16 0x07 0x17 0xCE 0x6D
file size: 32220
erase 64kB sector at 0x000000..
programming..
done.                 
reading..
VERIFY OK             
cdone: high
Bye.

结果

我没有按钮,就随便用几根线模拟一下按键按下的时候的GND 下降沿和 被内部上拉电阻上拉后的上升沿。

这里时钟用一根连线模拟,不然时钟跳得太快看不见led变化。后面我们可以做一个分频。

白线 = CLK
灰线 = RST

  • Count up
    请添加图片描述

请添加图片描述

  • Reset
    请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1805359.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

两轮自平衡小车资料(L298N 模块原理图及使用说明+c源码)

本文详细介绍了基于STM32微控制器的两轮自平衡小车的设计与实现过程。内容包括小车的硬件选型、电路设计、软件编程以及PID控制算法的应用。通过陀螺仪和加速度计获取小车的姿态信息&#xff0c;利用PID控制算法调整电机输出&#xff0c;实现小车的自主平衡。此外&#xff0c;还…

mac Network: use --host to expose

本地启动无法访问&#xff0c;这个不是权限问题是mac 主机端口安全策略&#xff0c;现在我们只需要开启端口自动检测就可以 npm run dev --host 网络&#xff1a;未暴露 方案一 1、执行 npm run dev -- --host 方案二 1、请在 vite.config.js server: {host: true } 1…

c++之旅第十弹——IO流

大家好啊&#xff0c;这里是c之旅第十弹&#xff0c;跟随我的步伐来开始这一篇的学习吧&#xff01; 如果有知识性错误&#xff0c;欢迎各位指正&#xff01;&#xff01;一起加油&#xff01;&#xff01; 创作不易&#xff0c;希望大家多多支持哦&#xff01; 一.流的概念&…

知乎网站只让知乎用户看文章,普通人看不了

知乎默认不显示全部文章&#xff0c;需要点击展开阅读全文 然而点击后却要登录&#xff0c;这意味着普通人看不了博主写的文章&#xff0c;只有成为知乎用户才有权力查看文章。我想这不是知乎创作者希望的情况&#xff0c;他们写文章肯定是希望所有人都能看到。 这个网站篡改…

力扣每日一题129:从根节点到叶子节点的和

题目 中等 相关标签 相关企业 给你一个二叉树的根节点 root &#xff0c;树中每个节点都存放有一个 0 到 9 之间的数字。 每条从根节点到叶节点的路径都代表一个数字&#xff1a; 例如&#xff0c;从根节点到叶节点的路径 1 -> 2 -> 3 表示数字 123 。 计算从根节…

Linux基础 (十三):计算机网络基础概论

一、网络基本概念 1.1 网络 把独立自主的计算机通过传输介质和网络设备链接起来&#xff0c;就构成一个网络 &#xff0c;网络是由若干结点和连接这些结点的链路组成&#xff0c;网络中的结点可以是计算机&#xff0c;交换机、 路由器等设备。 网络设备有&#xff1a;交换机、…

跨域、JSONP、CORS、Spring、Spring Security解决方案

概述 JavaScript出于安全方面的考虑&#xff0c;不允许跨域调用其他页面的对象。跨域是浏览器&#xff08;如Chrome浏览器基于JS V8引擎&#xff0c;可以简单理解为JS解释器&#xff09;的一种同源安全策略&#xff0c;是浏览器单方面限制脚本的跨域访问。因此&#xff0c;仅有…

Chrome浏览器书签同步不及时怎么办?两种方法帮你解决!

&#x1f468;‍&#x1f393;博主简介 &#x1f3c5;CSDN博客专家   &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01…

Elasticsearch 认证模拟题 - 17

这两道题目非常具有代表性&#xff0c;分别是跨集群复制和跨集群检索&#xff0c;需要相应的 许可 这里在虚拟机上搭建集群完成这两道题目&#xff0c;这里补充一下 elasticsearch 和 kibana 的配置文件 # elasticsearch.yml cluster.name: cluster2 node.name: cluster2-node…

一定要了解的 WordPress 数据库中默认 12 个表

WordPressan 安装的时候会有 12 张默认的数据表,每张表的数据都包含了 WordPress 不同的功能。看看这些表的结构,你能很容易的了解网站不同的部分都是存在哪里的。目前,默认的 WordPress 安装会创建如下的数据表。 注意:每张表名前面的 wp_ 是你在安装过程中选择的数据库前…

新书推荐:2.2.4 第11练:消息循环

/*------------------------------------------------------------------------ 011 编程达人win32 API每日一练 第11个例子GetMessage.c&#xff1a;消息循环 MSG结构 GetMessage函数 TranslateMessage函数&#xff1a;将虚拟键消息转换为字符消息 DispatchMessage函数…

【微信小程序】事件分类以及阻止事件冒泡

在微信小程序中&#xff0c;事件分为冒泡事件和非冒泡事件两大类&#xff0c;它们的区别在于事件是否能从原始触发组件开始&#xff0c;向父级组件传播&#xff08;即“冒泡”&#xff09;。 冒泡事件&#xff1a;当一个组件上的事件被触发后&#xff0c;不仅当前组件会接收到这…

cisco packet tracer 8.2.2 (思科模拟器) ospf路由协议

1 实验拓扑图 2 配置路由器和交换机 #sw1 en config t hostname sw1 ip routing int vlan 2 ip address 192.168.2.1 255.255.255.0 exit int vlan 3 ip address 192.168.3.1 255.255.255.0 exit int gigabitEthernet 1/0/1 switchport access vlan 2 exit int gigabitEthe…

012-Linux逻辑卷管理(LVM)

前言 安装 Linux 操作系统时遇到的⼀个常见的难以决定的问题就是如何正确地评估各分区大小&#xff0c;以分配合适的硬盘空间; 基本的磁盘分区管理方式在逻辑分区划分好之后就无法改变其大小。随着 Linux的逻辑卷管理功能的出现&#xff0c;这些问题都迎刃而解&#xff0c;用户…

[C++初阶]string类的详解

一、string类的模拟实现 上面已经对string类进行了简单的介绍&#xff0c;大家只要能够正常使用即可。在面试中&#xff0c;面试官总喜欢让我们来模拟实现string类&#xff0c;最主要是实现string类的构造、拷贝构造、赋值运算符重载以及析构函数。大家看下以下string类的实现是…

深度学习-CPGNet部署

1、导出onnx提示以下警告 问题&#xff1a; 原因&#xff1a; 模型是torch1.8导出的&#xff0c;对应的onnx版本是11&#xff0c;但是onnx是torch1.12生成的&#xff0c;对应的onnx版本是16。 解决方法&#xff1a; 将onnx.export函数的属性从opset_version16改成opset_version…

【数据结构】查找(顺序查找、二分查找、索引顺序查找、二叉排序树、平衡排序树、B树、B+树、哈希表)

目录 数据结构——查找何为查找1. 查找表2. 关键字3. 查找方法效果评价指标——平均查找长度ASL(Average Search Length) 静态查找表1.顺序查找2.二分查找二分查找判定树 3.静态查找表—索引顺序表的查找索引顺序查找表的算法原理&#xff1a; 动态查找树表1. 二叉排序树2. 二叉…

7种方法教你如何解决msvcp140_1.dll丢失问题,一键修复dll丢失问题

msvcp140_1.dll 是 Microsoft Visual C 2015 Redistributable 的一部分&#xff0c;它提供了运行时所需的 C 标准库的实现。这个 DLL 文件对于依赖 Visual C 2015 编译的应用程序至关重要&#xff0c;因为它包含了程序运行时所必需的函数和资源。 作用 运行时支持&#xff1a…

点击一张图片,到最后渲染到屏幕,都经历了哪些流程?

文章目录 图像的表示在iOS设备上 图像的表示 位图&#xff08;bitmap&#xff09;是一种常见的图像表示方式&#xff0c;它通过记录图像中每个像素的颜色信息来表示整张图片。以下是位图表示图片的基本原理&#xff1a; 像素网格&#xff1a; 位图将图像分解成一个网格&…