Intel FPGA (2):线性序列机

news2024/11/23 7:16:08

Intel FPGA (2):线性序列机

前提摘要

  1. 个人说明:

    • 限于时间紧迫以及作者水平有限,本文错误、疏漏之处恐不在少数,恳请读者批评指正。意见请留言或者发送邮件至:“Email:noahpanzzz@gmail.com”
    • 本博客的工程文件均存放在:GitHub:https://github.com/panziping。
    • 本博客的地址:CSDN:https://blog.csdn.net/ZipingPan
  2. 参考:

    • 芯片型号:Intel EP4CE10F17C8(Cyclone IV E)
    • 《数字电子技术基础》-阎石
    • 《FPGA自学笔记—设计与验证》袁玉卓,曾凯锋,梅雪松
    • 《Verilog 数字系统设计教程》夏宇闻
    • 《Verilog HDL 高级数字设计》Michael D.Ciletti
    • 《Intel FPGA/CPLD设计》(基础篇)王欣 王江宏等
    • 《Intel FPGA/CPLD设计》(高级篇)王江宏 蔡海宁等
    • 《综合与时序分析的设计约束 Synopsys设计约束(SDC)实用指南》Sridhar Gangadharan
  3. 日期:

    • 2024-01-01

正文

点亮LED灯

硬件资源

在这里插入图片描述

由原理图可知,FPGA的IO口输出低电平,则LED点亮。

程序编写
module led_test(
	led
);
	output led;

	assign led = 1'b0;

endmodule 

点亮LED灯进阶

将LED点亮200ms,熄灭800ms。

程序编写
module led_test(
	clk,
	rst_n,
	led
);

	input clk;
	input rst_n;
	output reg led;
	reg [27:0] r_led_cnt;
	localparam LED_CNT_MAX = 28'd50_000_000;
	localparam LED_CNT_TURN = 28'd40_000_000;

    always@(posedge clk or negedge rst_n) begin
		if(!rst_n)
			r_led_cnt <= 'd0;
		else if(r_led_cnt == LED_CNT_MAX-1)
			r_led_cnt <= 'd0;
		else
			r_led_cnt <= r_led_cnt + 1'd1;
	end
	
    always@(posedge clk or negedge rst_n) begin
		if(!rst_n)
			led <= 1'd1;
		else if(r_led_cnt == LED_CNT_TURN-1)
			led <= 1'd0;
		else if(r_led_cnt == LED_CNT_MAX-1)
			led <= 1'd1;
		else
			led <= led;
	end

	
endmodule 
波形图

在这里插入图片描述

由上述实验可以发现,通过计数器可以产生一个占空比不是50%的周期信号。那么是不是由此可以引申,通过计数器对时钟计数,产生一串带有数字信息的信号。

线性序列机(LSM)

产生一段信号,包含的内容为11011010,每个码元所占用的时间为50us。

module tx_test(
	clk,
	rst_n,
	tx
);
	input clk;
	input rst_n;
	output reg tx;

	reg [15:0] r_tim_cnt;
	
	localparam TIM_CNT_MAX = 16'd20_000;
	localparam DATA0 = 16'd2_500;
	localparam DATA1 = 16'd5_000;
	localparam DATA2 = 16'd7_500;
	localparam DATA3 = 16'd10_000;
	localparam DATA4 = 16'd12_500;
	localparam DATA5 = 16'd15_000;
	localparam DATA6 = 16'd17_500;
	localparam DATA7 = 16'd20_000;
    always@(posedge clk or negedge rst_n) begin
		if(!rst_n)
			r_tim_cnt <= 'd0;
		else if(r_tim_cnt == TIM_CNT_MAX-1)
			r_tim_cnt <= 'd0;
		else
			r_tim_cnt <= r_tim_cnt + 1'd1;
	end
	
    always@(posedge clk or negedge rst_n) begin
		if(!rst_n)
			tx <= 1'd1;
		else if(r_tim_cnt == DATA0 - 1'd1)
			tx <= 1'd0;
		else if(r_tim_cnt == DATA1 - 1'd1)
			tx <= 1'd1;
		else if(r_tim_cnt == DATA2 - 1'd1)
			tx <= 1'd0;
		else if(r_tim_cnt == DATA3 - 1'd1)
			tx <= 1'd1;
		else if(r_tim_cnt == DATA4 - 1'd1)
			tx <= 1'd1;
		else if(r_tim_cnt == DATA5 - 1'd1)
			tx <= 1'd0;
		else if(r_tim_cnt == DATA6 - 1'd1)
			tx <= 1'd1;
		else if(r_tim_cnt == DATA7 - 1'd1)
			tx <= 1'd1;
		else 
			tx <= tx;
	end
	
//	always@(posedge clk or negedge rst_n) begin
//		if(!rst_n)
//			tx <= 1'd1;
//		else 
//			case(r_tim_cnt)
//			DATA0-1'd1: tx <= 1'd0;
//			DATA1-1'd1: tx <= 1'd1;			
//			DATA2-1'd1: tx <= 1'd0;
//			DATA3-1'd1: tx <= 1'd1;		
//			DATA4-1'd1: tx <= 1'd1;
//			DATA5-1'd1: tx <= 1'd0;			
//			DATA6-1'd1: tx <= 1'd1;
//			DATA7-1'd1: tx <= 1'd1;			
//			default:tx <= tx;
//			endcase
//	end
//	

endmodule 
波形图

在这里插入图片描述

由上述实验可以发现,通过线性序列机产生了8bits(11011010)的信号。那么是不是对于串行信号都可以通过线性序列机进行输出。

数码管驱动

上述是线性序列机(LSM)的简单应用。

这一部分展示线性序列机应用在数码管驱动电路中(完整请见(Intel FPGA (3):数码管显示)),需要通过线性序列机产生三个信号seg_sclk(sh_cp),seg_rclk(st_cp),seg_dio(ds)

波形图

在这里插入图片描述

程序编写
module hc595_driver(
	clk,
	rst_n,
	seg_data,
	seg_data_valid_go,
	seg_sclk,
	seg_rclk,
	seg_dio
);

	input clk;
	input rst_n;
	input [15:0] seg_data;
	input seg_data_valid_go;
	output reg seg_sclk;
	output reg seg_rclk;
	output reg seg_dio;
	

	reg [15:0] r_seg_data;
	always@(posedge clk or negedge rst_n) begin
		if(!rst_n)
			r_seg_data <= 'd0;
		else if(seg_data_valid_go == 1'b1)
			r_seg_data <= seg_data;
		else
			r_seg_data <= r_seg_data;
	end
	
	localparam DIV_CNT_MAX = 4;			//fsh_cp = 6.25MHz
	reg [2:0] r_div_cnt;
	
	always@(posedge clk or negedge rst_n) begin
		if(!rst_n)
			r_div_cnt <= 'd0;
		else if(r_div_cnt == DIV_CNT_MAX -1)
			r_div_cnt <= 'd0;
		else	
			r_div_cnt <= r_div_cnt + 1'b1;
	end
	wire w_sclk_pluse;	//SH_CP
	assign w_sclk_pluse = (r_div_cnt == DIV_CNT_MAX -1) ? 1'b1 :1'b0;
	
	
	reg [4:0] r_sclk_edge_cnt;	//SH_CP
	
	
	always@(posedge clk or negedge rst_n) begin
		if(!rst_n)
			r_sclk_edge_cnt <= 'd0;
		else if(w_sclk_pluse == 1'b1)
			if(r_sclk_edge_cnt == 5'd31)
				r_sclk_edge_cnt <= 'd0;
			else
				r_sclk_edge_cnt <= r_sclk_edge_cnt + 1'd1;
		else
			r_sclk_edge_cnt <= r_sclk_edge_cnt;
	end
	

	
	always@(posedge clk or negedge rst_n) begin
		if(!rst_n) begin
			seg_sclk <= 1'd0;
			seg_rclk <= 1'd0;
			seg_dio <= 1'd0;
		end
		else begin
			case(r_sclk_edge_cnt)
				5'd0 : begin seg_sclk = 1'b0; seg_rclk = 1'b1; seg_dio = r_seg_data[15]; end //Q2H(HEX_DP)
				5'd1 : begin seg_sclk = 1'b1; seg_rclk = 1'b0;  								 end 
				5'd2 : begin seg_sclk = 1'b0;				        seg_dio = r_seg_data[14]; end //Q2G(HEX_G)
				5'd3 : begin seg_sclk = 1'b1;								   						 end
				5'd4 : begin seg_sclk = 1'b0;				        seg_dio = r_seg_data[13]; end //Q2F(HEX_F)
				5'd5 : begin seg_sclk = 1'b1;														    end
				5'd6 : begin seg_sclk = 1'b0;				        seg_dio = r_seg_data[12]; end //Q2E(HEX_E)
				5'd7 : begin seg_sclk = 1'b1;														    end
				5'd8 : begin seg_sclk = 1'b0;				        seg_dio = r_seg_data[11]; end //Q2D(HEX_D)	
				5'd9 : begin seg_sclk = 1'b1;														    end
				5'd10: begin seg_sclk = 1'b0;				        seg_dio = r_seg_data[10]; end //Q2C(HEX_C)	
				5'd11: begin seg_sclk = 1'b1;														    end
				5'd12: begin seg_sclk = 1'b0;				        seg_dio = r_seg_data[9];  end //Q2B(HEX_B)	
				5'd13: begin seg_sclk = 1'b1;					    									 end
				5'd14: begin seg_sclk = 1'b0;				        seg_dio = r_seg_data[8];  end //Q2A(HEX_A)
				5'd15: begin seg_sclk = 1'b1;					    									 end
				5'd16: begin seg_sclk = 1'b0;				        seg_dio = r_seg_data[7];  end //Q1H(HEX_SEL7)		
				5'd17: begin seg_sclk = 1'b1;					    									 end
				5'd18: begin seg_sclk = 1'b0;				        seg_dio = r_seg_data[6];  end //Q1G(HEX_SEL6)
				5'd19: begin seg_sclk = 1'b1;					    									 end
				5'd20: begin seg_sclk = 1'b0;				        seg_dio = r_seg_data[5];  end //Q1F(HEX_SEL5)
				5'd21: begin seg_sclk = 1'b1;					    									 end
				5'd22: begin seg_sclk = 1'b0;				        seg_dio = r_seg_data[4];  end //Q1E(HEX_SEL4)		
				5'd23: begin seg_sclk = 1'b1;					    									 end
				5'd24: begin seg_sclk = 1'b0;				        seg_dio = r_seg_data[3];  end //Q1D(HEX_SEL3)			
				5'd25: begin seg_sclk = 1'b1;					    									 end
				5'd26: begin seg_sclk = 1'b0;				        seg_dio = r_seg_data[2];  end //Q1C(HEX_SEL2)	
				5'd27: begin seg_sclk = 1'b1;					    									 end
				5'd28: begin seg_sclk = 1'b0;				        seg_dio = r_seg_data[1];  end //Q1B(HEX_SEL1)	
				5'd29: begin seg_sclk = 1'b1;					    									 end
				5'd30: begin seg_sclk = 1'b0;				        seg_dio = r_seg_data[0];  end //Q1A(HEX_SEL0)
				5'd31: begin seg_sclk = 1'b1;					    									 end
				default:;
			endcase
		end
	end

endmodule 

总结

线性序列机可以画出任意波形的数字信号!常用作为最低层RTL设计。


本文均为原创,欢迎转载,请注明文章出处:CSDN:https://blog.csdn.net/ZipingPan。百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。

非原创博客会在文末标注出处,由于时效原因,可能并不是原创作者地址(已经无法溯源)。

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

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

相关文章

预处理指令——一些比较少见的概念

前言&#xff1a;预处理是我们的c语言源代码成为可执行程序的第一个步骤。而宏和预处理指令都是在这个阶段完成。本节内容就是关于宏和预处理指令相关知识点的解析。 目录 宏 预定义符号 #define定义常量 #define定义符号 #define定义宏 带副作用的宏参数 宏的替换规则…

【C语言基础】:自定义类型(二) -->联合和枚举

文章目录 一、联合体1.1 联合体类型的声明1.2 联合体的特点1.3 相同成员的结构体和联合体对比1.4 联合体大小的计算1.5 联合体练习 二、枚举类型2.1 枚举类型的声明2.2 枚举的优点 书山有路勤为径&#xff0c;学海无涯苦作舟。 创作不易&#xff0c;宝子们&#xff01;如果这篇…

嵌入式介绍

1、嵌入式系统学习的三条路线 单片机入门HAL 单片机核心/RTOS Liuxc 2.学习嵌入式的三条路线的优缺点 2.1.单片机入门(HAL) 简单、快速&#xff0c;实际上工作中涉及单片机编程时&#xff0c;也提倡使用HAL库。 对于学习来说&#xff0c;HAL封装了很多技术细节&#xff0c…

使用虚拟引擎为AR体验提供动力

Powering AR Experiences with Unreal Engine ​​​​​​​ 目录 1. 虚拟引擎概述 2. 虚拟引擎如何为AR体验提供动力 3. 虚拟引擎中AR体验的组成部分是什么&#xff1f; 4. 使用虚拟引擎创建AR体验 5. 虚拟引擎中AR的优化提示 6. 将互动性融入AR与虚拟引擎 7. 在AR中…

Python反爬案例——验证码的识别

验证码的识别 使用打码平台识别验证码 利用打码平台可以轻松识别各种各样的验证码&#xff0c;图形验证码、滑动验证码、点选验证码和逻辑推理验证码。打码平台提供了一系列API&#xff0c;只需要向API上传验证码图片&#xff0c;它便会返回对应的识别结果。 使用超级鹰平台…

Qt 实现的万能采集库( 屏幕/相机/扬声器/麦克风采集)

【写在前面】 之前应公司需要&#xff0c;给公司写过一整套直播的库( 推拉流&#xff0c;编解码)&#xff0c;类似于 libobs。 结果后来因为没有相关项目&#xff0c;便停止开发&维护了。 不过里面很多有用的组件&#xff0c;然后也挺好用的&#xff0c;遂开源出来一部分。…

软件测试(测试用例详解)(三)

1. 测试用例的概念 测试用例&#xff08;Test Case&#xff09;是为了实施测试而向被测试的系统提供的一组集合。 测试环境操作步骤测试数据预取结果 测试用例的评价标准&#xff1a; 用例表达清楚&#xff0c;无二义性。。用例可操作性强。用例的输入与输出明确。一条用例只有…

怎么在UE游戏中加入原生振动效果

我是做振动触感的。人类的五感“视听嗅味触”&#xff0c;其中的“触”就是触觉&#xff0c;是指皮肤、毛发与物体接触时的感觉。触感可以带来更加逼真的沉浸式体验。但也许过于司空见惯&#xff0c;也是习以为常&#xff0c;很多人漠视了触感的价值。大家对触感的认知还远远不…

skywalking idea中启动调试报错Output path is shared between the same module error

报错信息 简单描述&#xff1a;就是多个moudle一样用了一样的输出路径&#xff0c;这样容易造成冲突 Output path is shared between the same module error 参考&#xff1a;scala - Output path is shared between the same module error - Stack Overflow 解决方法&…

VScode使用Prettier格式化代码

1、安装Prettier插件 2、扩展设置 3、设置.prettierrc.json配置文件路径 4、.prettierrc 配置文件 .prettierrc.json 是 Prettier 格式化工具的配置文件&#xff0c;用于指定代码格式化的规则和风格。下面是一些可能的配置选项&#xff0c;请自行选择&#xff1a; {"prin…

spring boot自动配置原理-怎样回答这个问题

首先我们说一下自动配置的概念。 自动配置&#xff1a;遵循约定大约配置的原则&#xff0c;在boot程序启动后&#xff0c;起步依赖中的一些bean对象会自动注入到ioc容器 例子 程序引入spring-boot-starter-web 起步依赖&#xff0c;启动后&#xff0c;会自动往ioc容器中注入…

一文了解微带天线

微带天线介绍 微带天线的结构一般由介质基板、辐射体及接地板构成。介质基板的厚度远小于波长&#xff0c;基板底部的金属薄层与接地板相接&#xff0c;正面则通过 光刻工艺 制作具有特定形状的金属薄层作为辐射体。 辐射片的形状根据要求可进行多种变化。微波集成技术和新型制…

高频小信号放大器概述

高频放大器与低频&#xff08;音频&#xff09;放大器的主要区别是&#xff1a;工作频率范围和所需通过的频带宽度都有所不同。其采用的负载也不相同。 低频放大器的工作频率低&#xff0c;但工作频带宽度很宽&#xff0c;所以负载采用无调谐负载&#xff0c;例如电阻、有铁心…

Docker容器监控之CAdvisor+InfluxDB+Granfana

介绍&#xff1a;CAdvisor监控收集InfluxDB存储数据Granfana展示图表 目录 1、新建3件套组合的docker-compose.yml 2、查看三个服务容器是否启动 3、浏览cAdvisor收集服务&#xff0c;http://ip:8080/ 4、浏览influxdb存储服务&#xff0c;http://ip:8083/ 5、浏览grafan…

flink: 将接收到的tcp文本流写入HBase

一、依赖&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.o…

总结:微信小程序中跨组件的通信、状态管理的方案

在微信小程序中实现跨组件通信和状态管理,有以下几种主要方案: 事件机制 通过事件机制可以实现父子组件、兄弟组件的通信。 示例: 父组件向子组件传递数据: 父组件: <child binddata"handleChildData" /> 子组件: Component({..., methods: { handleChildData(…

VTK 简介

VTK 简介 VTK 简介什么是 VTK&#xff1f;VTK 能做什么&#xff1f;VTK 的基本组成VTK 的框架结构VTK 的数据结构VTK 的可视化流程参考 VTK 简介 什么是 VTK&#xff1f; VTK&#xff0c;全称是Visualization Toolkit&#xff0c;即可视化工具包。是一个开源、跨平台、可自由…

C++面向对象程序设计 - 访问对象中成员的3种方法

在C程序中访问对象的成员变量和成员函数&#xff0c;有三种方法&#xff1a; 通过对象名和成员运算符访问对象中的成员&#xff1b;通过指向对象的指针访问对象中的成员&#xff1b;通过对象的引用变量访问对象中的成员 在了解访问对象中成员的3种方法前&#xff0c;先了解下C…

uniapp 小程序和app map地图上显示多个酷炫动态的标点,头像后端传过来,真机测试有效

展示效果 二、引入地图 如果需要搜索需要去腾讯地图官网上看文档&#xff0c;找到对应的内容 1.申请开发者密钥&#xff08;key&#xff09;&#xff1a;申请密钥 2.开通webserviceAPI服务&#xff1a;控制台 ->应用管理 -> 我的应用 ->添加key-> 勾选WebService…

LCD TP触摸屏调试方法

一、硬件连接 I2C总线&#xff1a;I2C-SDA和i2C-SCL 中断信号&#xff1a;touch-gpio 复位信号&#xff1a;reset-gpio 电源信号&#xff1a;power-gpio 二、驱动调试 2.1 确认从设备地址 在给TP供电正常后&#xff0c;检测其I2C设备从地址&#xff0c;或者通过datashee…