【FPGA项目】沙盘演练——基础版报文收发

news2024/11/28 6:37:36

                        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        第1个虚拟项目

前言

        点灯开启了我们的FPGA之路,那么我们来继续沙盘演练。

        用一个虚拟项目,来入门练习,以此步入数字逻辑的大门。

        Key Words:FIFO 、SOF 、EOF、计数器、缓存、时序图、方案设计

一、项目要求

  1. 输入报文长度64~2048字节;
  2. 输入报文之间最小间隔为两拍;
  3. 输出报文的前两拍添加16bit报文长度信息;第1拍为报文长度高8位;第2拍为报文长度低8位;第3拍开始为输入报文;

信号

I/O

位宽

描述

系统接口信号

i_sys_clk

I

1

系统时钟,125Mhz

i_rst_n

I

1

硬复位,低有效

输入接口信号

i_sop_in

I

1

输入报文头指示信号,高有效

i_eop_in

I

1

输入报文尾指示信号,高有效

i_vld_in

I

1

输入报文数据有效信号,高有效

i_data_in

I

8

输入报文数据

输出接口信号

o_sop_out

O

1

输出报文头指示信号,高有效

o_eop_out

O

1

输出报文尾指示信号,高有效

o_vld_out

O

1

输出报文数据有效信号,高有效

o_data_out

O

8

输出报文数据

输入接口时序

输出接口时序

二、项目方案设计

2.1项目需求

  1. 输出报文;
  2. 输出报文长度;
  3. 报文与报文长度输出满足时序要求;

2.2项目方案

1. 要求输出报文,且报文输出在报文长度输出之后,所以需要先对输入报文进行缓存,根据输入报文的位宽和长度范围,此处选择合适的同步FIFO即可;(如果是IC,那么就需要自己写FIFO,可以参考本博客的FIFO介绍)

        这里项目提出了第1个要求,掌握FIFO的使用。

2. 要求输出报文长度,所以需要对输入报文长度进行计数,并将其缓存;

        此处有坑,若只用寄存器对长度进行缓存,存在被后续报文长度覆盖的风险,故需要第2个FIFO对报文长度进行缓存。

3. 要求先输出报文长度然后紧跟着输出报文,此处需要对时序进行设计,需要掌握FIFO的读写时序,需要理解fpga的时钟沿采样。

        理解:时钟沿采样及数据下一时钟沿变化。

2.3项目代码

module zmj0001(
	input 			sys_clk,
	input 			rst_n,
	
	input			sop_in,
	input 			eop_in,
	input 			vld_in,
	input	[7:0]	data_in,
	
	output 			sop_out,
	output			eop_out,
	output			vld_out,
	output 	[7:0] 	data_out
	);

当然这不是唯一的设计方案,可以先自行考虑设计及验证。

若需完整代码工程,🐟搜索“zmj0001”

项目重难点:

  1. FIFO的使用及时序的设计
  2. 考虑包间隔2 clk cycle
  3. 考虑长包+超短包的情况

时序设计可以用TimingDesigner软件,简单易用,需要的可以下载。

​​​​​​​三、仿真验证

可以使用计数器来产生数据源data_in;

`timescale 1ns / 1ps

module zmj0001_tb();

reg					sys_clk				;
reg					rst_n				;
reg 	[7	:0]		data_in				;
reg					vld_in				;
reg					sop_in				;
reg					eop_in				;
reg		[11	:0]		cnt					;									
wire 				sop_out  			;
wire 				eop_out             ;
wire				vld_out             ;
wire 	[7:0] 		data_out            ;

initial
begin
	sys_clk		=	0;
	rst_n		=	0;
	#100
	rst_n		=	1;
end
always #5	sys_clk	=	~sys_clk;	//100Mhz
//用计数器来产生data_in
always @(posedge	sys_clk	or	negedge	rst_n)begin
	if(~rst_n)
		cnt				<=		12'b0;
	else if(cnt > 2048)
		cnt				<=		cnt;
	else
		cnt				<=		cnt	+	12'b1;
end
always @(posedge	sys_clk	or	negedge	rst_n)begin
	if(~rst_n)begin
		data_in			<=		8'b0;
		sop_in			<=		1'b0;
		eop_in			<=		1'b0;
		vld_in			<=		1'b0;
		end
	else begin
		data_in			<=		8'b0;
		sop_in			<=		1'b0;
		eop_in			<=		1'b0;
		vld_in			<=		1'b0;
		if((cnt > 'd10  &&   cnt  <=  'd60)|(cnt > 'd68  &&   cnt  <=  'd668))begin
			data_in		<=		data_in + 1'b1;
			vld_in		<=		1'b1;
			end
		if((cnt == 'd11)|(cnt == 'd69))
			sop_in		<=		1'b1;
		if((cnt == 'd60)|(cnt == 'd668))
			eop_in		<=		1'b1;
		if((cnt == 'd62) | (cnt == 'd63))begin  //63  66
			data_in		<=		data_in + 1'b1;
			vld_in		<=		1'b1;
			sop_in 		<= 		1'b1;
			eop_in 		<= 		1'b1;
			end
		
		end
end	


zmj0001		u_zmj0001(
	.sys_clk			(sys_clk   ),	
	.rst_n              (rst_n     ),
						 			
	.sop_in             (sop_in    ),
	.eop_in             (eop_in    ),
	.vld_in             (vld_in    ),
	.data_in            (data_in   ),
						 			
	.sop_out            (sop_out   ),
	.eop_out            (eop_out   ),
	.vld_out            (vld_out   ),
	.data_out           (data_out  )
	);

endmodule

        具体modelsim使用及与vivado的联合仿真,脚本编写请参考其他博文,后续FPGA其他专栏再考虑写相关内容。

        验证时重点关注边界情况

输入:

        共4包数据,长包+超短包+超短包+长包,包间隔均为2clk cycle

        data_in : 第1包:1-50的累加数;第2包:1;第3包:1;

输出:

若包间隔<2 clk?

输入:

输出:

可以看到,本设计甚至支持背靠背的超短包输入。

四、项目收获

  1. 方案设计的重要性:任何项目都是始于方案设计,前期需要花大量的功夫去理清思路,方案设计完成,代码实现只不过是水到渠成的事情。
  2. 仿真的学习:通过本项目,完成了testbench的编写,仿真验证,是对自己设计的一次检验,是实际项目缩短调试时间的最佳利器。
  3. 对xilinx IP的使用,对datasheet的阅读学习。
  4. 对时序的理解,时钟是FPGA的心跳:任何时序操作都是发生在时钟的跳变沿。当采样发生在当前上升沿时刻,数据变化是发生在下一时刻的上升沿。
  5. 绘画时序图,TimingDesigner的使用。有了时序图,代码就很容易实现了。

五、进阶考虑

本次虚拟项目旨在用最简单的例子带大家了解数字逻辑设计的一些基本概念,所以很多东西是没有考虑的。比如:

  1. 如果包间隔小于2个时钟周期怎么办? -----握手与反压
  2. 如果输入数据有错误怎么办? -----CRC校验
  3. 如果需要跨时钟域传输呢? -----CDC处理
  4. 报文只是简单转发,如果需要做处理呢?-----数据处理
  5. ...

所以,下一篇将沿着这个思路展开,进阶版的虚拟项目,同样可以作为公司的入职培训。

咱们下期见!

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

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

相关文章

《C++ primer plus》精炼(OOP部分)——对象和类(1)

聪明在于学习&#xff0c;天才在于积累。所谓天才&#xff0c;实际上是依靠学习。 文章目录 概述正文面向对象编程和面向过程编程类和对象类的组成公共接口 类声明访问控制封装 类和结构体类定义 概述 C是门包罗万象的语言&#xff0c;它将各门类的编程思想杂糅&#xff0c;最…

Parallels Desktop 19新功能解析,助力跨平台工作流程提升!

对于许多Mac用户来说&#xff0c;运行Windows应用程序是必不可少的。也许你的雇主使用的软件只适用于Windows&#xff0c;或者需要使用依赖于某些Windows技术的网站。或者你想在Mac上玩Windows游戏。或者&#xff0c;你可能需要在其他操作系统上测试应用程序和服务——你可以在…

系统vcomp120.dll丢失怎么办?要怎样修复呢?三个修复方法分享

我要和大家分享一个关于系统丢失vcomp120.dll文件的问题。这个问题可能会困扰很多使用电脑的朋友&#xff0c;特别是在运行某些软件时&#xff0c;可能会出现“找不到vcomp120.dll”的错误提示。那么&#xff0c;遇到这样的问题&#xff0c;我们应该如何解决呢&#xff1f;接下…

用 ChatGPT 写代码太省时间了

几个月前&#xff0c;我们聊过陶哲轩使用 ChatGPT 辅助解决数学问题。当时&#xff0c;他觉得虽然测试结果不太令人满意&#xff0c;但也并没有对 ChatGPT 持完全否定的态度。他觉得&#xff0c;像 ChatGPT 这类大型语言模型在数学中可以用来做一些半成品的语义搜索工作&#x…

【leetcode 力扣刷题】汇总区间//合并区间//插入区间

一些关于区间的力扣题目 228. 汇总区间56. 合并区间57. 插入区间 228. 汇总区间 题目链接&#xff1a;228.汇总区间 题目内容&#xff1a; 看题目真是没懂这个题到底是要干啥……实际上题目要求的恰好覆盖数组中所有数字的最小有序区间范围列表&#xff0c;这个最小是指一个区…

QT 设置应用程序图标

1.下载xx.ico图标&#xff1a;ico网址 2.在线PNG转换ICO&#xff1a;png在线转换ico 3.添加图标资源 1&#xff09;新建文件路径 2&#xff09;添加图片资源 3&#xff09;在 .pro文件里面添加图片 4&#xff09;将xx.ico放到工程目录&#xff0c;编译完可以看到xx.exe的图标…

【LeetCode】515.在每个树行中找最大值

题目 给定一棵二叉树的根节点 root &#xff0c;请找出该二叉树中每一层的最大值。 示例1&#xff1a; 输入: root [1,3,2,5,3,null,9] 输出: [1,3,9]示例2&#xff1a; 输入: root [1,2,3] 输出: [1,3]提示&#xff1a; 二叉树的节点个数的范围是 [0,10^4]-2^31 < No…

无涯教程-JavaScript - CUBERANKEDMEMBER函数

描述 CUBERANKEDMEMBER函数返回集合中的第n个或排序的成员。 使用此功能可返回一组中的一个或多个元素,如销售业绩最好的人或前十名的学生。 语法 CUBERANKEDMEMBER (connection, set_expression, rank, [caption])争论 Argument描述Required/OptionalconnectionThe name …

Linux--进程--创建子进程一般目的

父进程创建子进程的目的&#xff1a;简单来说&#xff1a;给特定的输入&#xff0c;给出特定的输出 父进程希望复制自己&#xff0c;使父、子进程同时执行不同的代码段。这在网络服务进程中是常见的——父进程等待客户端的服务请求。当请求到达&#xff0c;父进程调用fork&…

FPGA 学习笔记:Vivado 工程管理技巧

前言 当前使用 Xilinx 的 FPGA,所以需要熟悉 Xilinx FPGA 的 开发利器 Vivado 的工程管理方法 这里初步列举一些实际 Xilinx FPGA 开发基于 Vivado 的项目使用到的工程的管理技巧 代码管理 做过嵌入式软件或者其他软件开发的工程技术人员,都会想到使用代码管理工具,如 SVN 、…

架构师成长之路Redis第一篇|Redis 安装介绍以及内存分配器jemalloc

安装 Redis官网:https://redis.io/download/ 下载安装二进制文件 可下载安装最新版Redis7.2.0,或者可选版本6.x 我这里下载6.2.13和7.2最新版本,后面我们都是安装6.2.13版本的信息进行讲解 二进制文件安装步骤 安装前期准备: 安装gcc yum install gcc 压缩文件 tar -xzf re…

SpringCloud(34):Nacos服务发现

1 从单体架构到微服务 1.1单体架构 Web应用程序发展的早期,大部分web工程师将所有的功能模块打包到一起并放在一个web容器中运行,所有功能模块使用同一个数据库,同时,它还提供API或者UI访问的web模块等。 尽管也是模块化逻辑,但是最终它还是会打包并部署为单体式应用,这…

Linux:内核解压缩过程简析

文章目录 1. 前言2. 背景3. zImage 的构建过程4. 内核引导过程5. 内核解压缩过程6. 内核加压缩过程小结7. 参考资料 1. 前言 限于作者能力水平&#xff0c;本文可能存在谬误&#xff0c;因此而给读者带来的损失&#xff0c;作者不做任何承诺。 2. 背景 本文基于 ARM32架构 …

【德哥说库系列】-ASM管理Oracle 19C单实例部署

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

垃圾回收 - 引用计数法

GC原本是一种“释放怎么都无法被引用的对象的机制”。那么人们自然而然就会想到&#xff0c;可以让所有对象事先记录下“有多少程序引用了自己”。让各对象知道自己的“人气指数”&#xff0c;从而让没有人气的对象自己消失&#xff0c;这就是引用计数法。 1、计数器 计数器表…

【Unity基础】1.项目搭建与视图编辑

【Unity基础】1.项目搭建与视图编辑 大家好&#xff0c;我是Lampard~~ 欢迎来到Unity基础系列博客&#xff0c;终于要开始写基础系列的博客了&#xff0c;前两篇的内容基本上与入门系列相同&#xff0c;如果有紧跟入门系列的同学可以直接从第三篇文章开始看 好了话不多说我们开…

Java切换到Kotlin,Crash率上升了?

前言 最近对一个Java写的老项目进行了部分重构&#xff0c;测试过程中波澜不惊&#xff0c;顺利上线后几天通过APM平台查看发现Crash率上升了&#xff0c;查看堆栈定位到NPE类型的Crash&#xff0c;大部分发生在Java调用Kotlin的函数里&#xff0c;本篇将会分析具体的场景以及…

ORB-SLAM3复现过程中遇到的问题及解决办法

在复现过程中遇到的问题的解决过程 1. 版本检查1.1 Opencv版本的检测1.2 Eigen版本的检测1.3 查看Python版本1.4 其他 2. 编译过程中遇到的问题及解决办法2.1 ./build.sh遇到的问题2.2 ./build_ros.sh遇到的问题 因为环境比较干净&#xff0c;所以遇到的问题相对少一些&#xf…

ARM 汇编基础知识

1.为什么学习汇编&#xff1f; 我们在进行嵌入式 Linux 开发的时候是绝对要掌握基本的 ARM 汇编&#xff0c;因为 Cortex-A 芯片一 上电 SP 指针还没初始化&#xff0c; C 环境还没准备好&#xff0c;所以肯定不能运行 C 代码&#xff0c;必须先用汇编语言设置好 C 环境…

【python】实现积分

借助sympy.integrate() 符号运算库&#xff0c;所以里面的exp()&#xff0c;sin()等都要使用sympy库中的函数&#xff0c;如果使用numpy库中的函数时没用的。 import sympy as sp import numpy as np x sp.symbols("x") print(sp.integrate(sp.exp(-x**2), (x, -s…