fpga实操训练(小功能到模块开发)

news2025/2/6 6:50:32

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        有过c、java编程语言经验的朋友,是否还记得曾经自己是如何学习编程语言的?一开始的时候,为了学习语法,我们练习的代码可能都比较少。主要是一些简单的逻辑判断、循环和小算法之类的内容。等到这一切都ok之后,就开始慢慢编写一些复杂的功能了。这个时候,如果再将所有的代码集中在同一个源文件当中,就会显得非常臃肿了。我至今还记得,当初硕士论文中设计的代码,就是全部放在一个文件中的,前前后后大约有5000行左右。

        回到今天的主题,其实编写verilog也是一样的。一方面,曾经的小功能可以变成独立的模块,方便我们将来调用;另外一方面,对于相似的逻辑内容,也可以抽象成单独的一个模块来处理;最后,也是很重要的一点,我们要学会利用别人开发好的模块,这样可以快速拓展自己的能力边界,这点有点类似于使用第三方SDK。只是,纯软件模块和verilog不一样的地方,就是每一次模块实例化都是实实在在的电路,这和函数调用几乎不花成本是完全不一样的。

        为了说明如何做一个基于模块开发的项目,我们可以写一个简单的计时工具。即,上电后,数码管开始计时,每1s计时一次,一共可以累计到99999秒,再重新恢复为0。

1、准备进位代码


module add_bit(clk, rst,in, value, over);

input in;
input clk;
input rst;
output[3:0] value;
output over;

wire in;
wire clk;
wire rst;
reg[3:0] value;
reg over;

always@(posedge clk or negedge rst)
	if(!rst)
		value <= 4'd0;
	else if(in) begin
		if(value == 4'd9)
			value <= 4'd0;
		else 
			value <= value + 1'b1;
	end

always@(posedge clk or negedge rst)
	if(!rst)
		over <= 1'b0;
	else if(over)
		over <= 1'b0;
	else if(in == 1 && value == 4'd9)
		over <= 1'b1;
		
endmodule

        所谓进位代码,就是看有没有进位传上来,有没有进位送出去,当前应该显示的数据是什么。有了这么一个进位,其实就构成了基本的6位数显示方法。

2、数码管的显示

        前面的章节,我们说过。一个6节的数码管,会有6个sel信号,8个数据信号。但是,6个数码管每一个都有自己的数字,这应该如何处理?想来想去,唯一可行的办法就是通过快速刷新,利用人的视觉残留效应,误以为数码管的显示是连贯的。


module seg_select(clk, rst, seg_sel);

input clk;
input rst;
output[5:0] seg_sel;

wire clk;
wire rst;
reg[5:0] seg_sel;

reg[31:0] sel_count;

// select data
always@(posedge clk or negedge rst)
	if(!rst)
		sel_count <= 32'b0;
	else if(sel_count != 32'd4_9999)
		sel_count <= sel_count + 1;
	else
		sel_count <= 32'b0;

always @(posedge clk or negedge rst)
	if(!rst)
		seg_sel <= 6'b011111;
	else if(sel_count == 32'd4_9999)
		seg_sel <= {seg_sel[0],seg_sel[5:1]};

endmodule

3、数码管的解码

        相比较而言,数码管的解码就很简单的。主要是根据需要显示的数字,点亮数码管上面不同部分的led灯。


module seg_decode(clk, rst, seg_sel, num0, num1, num2, num3, num4, num5, seg_data);

input clk;
input rst;
input[5:0] seg_sel;
input[3:0] num0;
input[3:0] num1;
input[3:0] num2;
input[3:0] num3;
input[3:0] num4;
input[3:0] num5;
output[7:0] seg_data;

wire clk;
wire rst;
wire[5:0] seg_sel;
wire[3:0] num0;
wire[3:0] num1;
wire[3:0] num2;
wire[3:0] num3;
wire[3:0] num4;
wire[3:0] num5;

reg[3:0] num;
reg[7:0] seg_data;


always@(*)
	case(seg_sel)
		6'b011111: 
			num <= num0;

		6'b101111:
			num <= num1;

		6'b110111:
			num <= num2;

		6'b111011:
			num <= num3;

		6'b111101:
			num <= num4;
	
		6'b111110:
			num <= num5;

		default:
			num <= 4'd0;
	endcase

// decode data
always@(posedge clk or negedge rst)
	if(!rst)
		seg_data <= 8'b1100_0000;
	else
		case (num)
			4'd0: 
				seg_data <= 8'b1100_0000;				
			4'd1: 
				seg_data <= 8'b1111_1001;
			4'd2: 
				seg_data <= 8'b1010_0100;
			4'd3: 
				seg_data <= 8'b1011_0000;
			4'd4: 
				seg_data <= 8'b1001_1001;
			4'd5: 
				seg_data <= 8'b1001_0010;
			4'd6:
				seg_data <= 8'b1000_0010;
			4'd7:
				seg_data <= 8'b1111_1000;
			4'd8:	
				seg_data <= 8'b1000_0000;
			4'd9:
				seg_data <= 8'b1001_0000;
				
			default: 
				seg_data <= 8'b1100_0000;
		endcase
endmodule

4、模块的整合

        有了上面3个模块的编写,下面就可以开始他们的整合了,一起构建一个完整的功能模块。整个过程并不复杂,大家看一下代码就了解相关的流程了。

        模块中的调用顺序是这样的,

        代码的组成是这样的,


module seg_test(clk, rst, seg_sel, seg_data);

input clk;
input rst;
output[5:0] seg_sel;
output[7:0] seg_data;

wire clk;
wire rst;
wire[5:0] seg_sel;
wire[7:0] seg_data;

reg[31:0] count;

wire[3:0] num0;
wire in0;
wire over0;

wire[3:0] num1;
wire in1;
wire over1;

wire[3:0] num2;
wire in2;
wire over2;

wire[3:0] num3;
wire in3;
wire over3;

wire[3:0] num4;
wire in4;
wire over4;

wire[3:0] num5;
wire in5;
wire over5;


// from seg selector

seg_select seg_select0(
	.clk(clk),
	.rst(rst),
	.seg_sel(seg_sel)
	);


// from basic		
		
always@(posedge clk or negedge rst)
	if(!rst)
		count <= 32'b0;
	else if(count != 32'd4999_9999)
		count <= count + 1;
	else
		count <= 32'b0;


// use add_bit

add_bit add_bit0(
	.clk(clk),
	.rst(rst),
	.in(count == 32'd4999_9999),
	.value(num0),
	.over(over0)
	);		
		

add_bit add_bit1(
	.clk(clk),
	.rst(rst),
	.in(over0),
	.value(num1),
	.over(over1)
	);	
	
add_bit add_bit2(
	.clk(clk),
	.rst(rst),
	.in(over1),
	.value(num2),
	.over(over2)
	);	
	
add_bit add_bit3(
	.clk(clk),
	.rst(rst),
	.in(over2),
	.value(num3),
	.over(over3)
	);	
	
add_bit add_bit4(
	.clk(clk),
	.rst(rst),
	.in(over3),
	.value(num4),
	.over(over4)
	);	
	
add_bit add_bit5(
	.clk(clk),
	.rst(rst),
	.in(over4),
	.value(num5),
	.over(over5)
	);	
		

// choose num	
	
seg_decode seg_deocode0(
	.clk(clk),
	.rst(rst),
	.seg_sel(seg_sel),
	.num0(num0),
	.num1(num1),
	.num2(num2),
	.num3(num3),
	.num4(num4),
	.num5(num5),
	.seg_data(seg_data)
	);

endmodule


5、RTL显示

        综合完毕后,如果大家有兴趣需要看下RTL综合后的效果,可以选择“RTL Viewer”,

        如图所示,上图中绿色的部分就是子模块。如果需要了解里面的细节,点击模块左上方的田字格即可,类似于这样,

6、pin脚bind

7、所有这些都完成值之后,就可以开始实验了

题外话:

        很多时候,模块的拆解整合是需要反复进行的,并不意味着马上就可以做对。来来去去、反反复复都是常有的事情。不过还是要相信自己,每一次的思考、每一次的修正都会让自己有所改进的。

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

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

相关文章

光电传感器调研报告

目录 前言&#xff1a; 一、理论基础——光电效应 二、光电传感器原理 三、光电元件 3.1光电管 3.2光敏电阻 四、光电传感器特性 4.1伏安特性 4.2光电特性 4.3光谱特性 五、光电传感器的应用 LED&#xff08;发光二极管&#xff09; 超声波传感器 光纤 六、总结 …

用Python赚钱的方法有哪些?

很多人想知道用Python赚钱的方法有哪些&#xff1f;Python很容易使用&#xff0c;应用性较强。可以通过使用Python开发小程序、抓取数据、游戏开发、兼职编程老师&#xff0c;发展副业的方式来赚钱。 用Python赚钱的方法&#xff1a; 1、某宝搜python程序   可以到某宝上搜&a…

中年人怎么转行做程序员,教你不怕年龄限制奔向高薪之路

网上很多人都说&#xff0c;人到了中年再去学编程已经来不及了&#xff0c;体力和精力都跟不上年轻人&#xff0c;做开发还要经常学习&#xff0c;然而中年人基本上有老下有小&#xff0c;根本没那么多时间去学习新技术&#xff0c;最重要的是&#xff0c;很多公司都有年龄限制…

学会这八个小技巧,让你软文推广更有效果!

软文营销已经出现在了我们的日常生活中&#xff0c;软文对于硬性的广告来说&#xff0c;具有独特的优势以及特殊性&#xff0c;受到了很多企业的青睐&#xff0c;其中还有一个重要的原因软文的花费是非常低的&#xff0c;适合一些中小型企业进行宣传推广,今天这篇文章就给大家讲…

vue学习笔记(五)-vuex

什么是vuex 1.概念&#xff1a;专门在Vue中实现集中式状态&#xff08;数据&#xff09;管理的一个Vue插件&#xff0c;对Vue应用中多个组件的共享状态进行集中式的管理&#xff08;读/写&#xff09;&#xff0c;也是一种组件间通信的方式&#xff0c;且适用于任意组件间通信…

此时此刻此景,“零”就代表着赢

编辑 | 阿冒 设计 | 沐由2022卡塔尔世界杯&#xff0c;终于步入到最强、最美和最终的华章&#xff0c;阿根廷与法兰西共同上演了世界杯决赛史上的一幕奇迹&#xff0c;意想不到的转折和蹉跎而至的结局&#xff0c;让人不得不感慨全球第一运动的巨大魅力。在这种世界顶级水准…

统计学习方法 | 决策树

一.一棵有理想的树 分类决策树模型是一种描述对实例进行分类的树形结构 决策树是通过一系列规则对数据进行分类的过程 步骤 ①构建根节点 ②选择最优特征&#xff0c;以此分割训练数据集 ③若子集被基本正确分类&#xff0c;构建叶结点&#xff0c;否则&#xff0c;继续选…

java实验报告之模拟银行存取款业务

一个不知名大学生&#xff0c;江湖人称菜狗 original author: jacky Li Email : 3435673055qq.com Time of completion&#xff1a;2022.12.20 Last edited: 2022.12.20 目录 一、实验目的 二、实验内容 三、总体设计&#xff08;设计原理、设计方案及流程等&#xff09; 四…

医院导诊图怎么做,专业便捷、低成本的室内电子地图绘制平台!

目前的医院综合性强&#xff0c;面积大&#xff0c;科室多&#xff0c;布局复杂&#xff0c;病患在就医过程中&#xff0c;往往因为对医院各科室与区域分布不清晰而找不到方向&#xff0c;多走冤枉路&#xff0c;耗费时间&#xff0c;影响就医体验。上海懒图信息科技有限公司上…

轻量级网络模型MobileNet发展脉络(V1-V2-V3)

卷积神经网络发展 卷积神经网络被广泛应用在图像分类、目标检测等视觉任务中&#xff0c;并取得了巨大的成功。然而&#xff0c;卷积神经网络通常需要较大的运算量和内存占用&#xff0c;在移动端以及嵌入式设备等资源受限的环境中受到限制&#xff0c;因此需要进行网络压缩。从…

虹科案例 | 如何快速精准监测打桩机打桩深度?

想要精准测量打桩设备每个桩的测量深度&#xff0c;以正确设置多排电池板的太阳能农场&#xff1f;但是由于测量环境恶劣&#xff0c;导致普通传感器无法正常工作&#xff1f;那快了解一下我们的虹科Dimetix激光测距传感器吧&#xff0c;它可以完美解决上述问题&#xff01; 一…

NFC技术的特点与应用

NFC技术能给我们的生活带来极大的便利&#xff0c;能够用于乘车、购物、交换信息、刷门禁卡&#xff0c;可以说它能够应用到我们生活的方方面面。 但是&#xff0c;NFC到底是谁发明的&#xff1f;什么时候发明的&#xff1f;我们就来了解一下。 NFC的中文全称为近场通信技术&…

85%的攻击现在使用加密通道

©网络研究院 加密攻击仍然是全球各国面临的一个重大问题&#xff0c;美国、印度和日本的攻击数量在过去12个月中增长最快。 此外&#xff0c;与2021年相比&#xff0c;南非的TLS/SSL攻击显著增加。 Zscaler的安全研究和运营副总裁表示:“随着组织网络防御的成熟&#x…

22-12-19 西安 vue-cli(01) vue-cli脚手架、组件化编程、vue-router路由

"对A&#xff0c;我还剩一张牌啦&#xff01;" "呃。。。要不起" 周六&#xff08;12-03&#xff09;&#xff0c;早上刷到印度的三相神。梵天&#xff0c;毗湿奴&#xff0c;湿婆&#xff0c;看来很多个相关的视频介绍&#xff0c;结果睡觉&#xff08;不…

蓝桥杯题目类型总结

搜索类 BFS 大胖子走迷宫&#xff08;简单&#xff09;&#xff08;2019国赛&#xff09; 迷宫与陷阱&#xff1a;&#xff08;中等2018国赛&#xff09; 迷宫与陷阱&#xff1a;&#xff08;中等2018国赛&#xff09; 迷宫与陷阱&#xff1a;&#xff08;中等2018国赛&…

安卓PorterDuffXfermode之正片叠底 PorterDuff.Mode.MULTIPLY

setXfermode Paint#setXfermode()接口是在绘制时设置画笔的图形混合模式的,下面是官网的介绍&#xff1a; public Xfermode setXfermode (Xfermode xfermode) Set or clear the transfer mode object. A transfer mode defines how source pixels (generate by a drawing com…

three.js之旋转成型(车削缓冲几何体)

文章目录简介例子解释专栏目录请点击 简介 一条曲线围绕空间中的某个轴进行旋转&#xff0c;会形成一个几何体这个在three.js中也是可以实现的&#xff0c;主要就是使用到了three.js中的LatheGeometry&#xff0c;官网 例子 <!DOCTYPE html> <html lang"en&qu…

SpringBoot2.X+Vue+UniAPP 全栈开发医疗小程序 中间件搭建

文章目录一、安装Docker环境1. 关闭SELINUX服务2. 更新yum程序3. 安装Docker4. 管理Docker二、搭建HBasePhoenix大数据平台2.1. 加载镜像2.2. 创建容器2.3. 创建逻辑库2.4. 创建数据表与导入数据2.5. 配置JDBC连接信息三、Redis服务3.1. 加载镜像3.2. 配置文件3.3. 创建Redis容…

专注性能的多端研发框架 - ice.js 3 正式发布!

ice.js 框架在之前的版本中&#xff0c;主要服务于中后台 / PC 的项目研发&#xff0c;而随着无线端以及多端能力的拓展&#xff0c;ice.js 3 将成为一套面向大淘宝技术的终端应用框架。因此在 ice.js 3 的版本中除了「开发者体验」之外&#xff0c;还围绕「用户体验」探索了大…

拥抱实体经济,可以说是当下互联网参与者的首要选择

拥抱实体经济&#xff0c;绝对是当下互联网玩家们的首要选择。无论是头部的互联网企业来讲&#xff0c;还是新生的互联网玩家而言&#xff0c;它们都不约而同地将关注的焦点聚焦在了这样一个方向上。   透过这一点&#xff0c;我们可以非常明显地感受到&#xff0c;一个全新的…