ZYNQ_project:test_fifo_255X8

news2024/11/27 22:23:10

首先,这个vivado的fifo和quartus有很大不同。

用BRAM来实现异步fifo。

vivado的fifo有复位,在时钟信号稳定后,复位至少三个时钟周期(读写端口的慢时钟),复位完成后30个时钟周期后再进行写操作(慢时钟)。

有两个模式:标准模式和预读模式。

标准模式,读出的数据会比读使能延后一个时钟周期,fifo的深度也会比配置的少一个。

预读模式,读出的数据会与读使能同步,深度会比配置的多一个。

犯下的错误:顶层模块,fifo的复位接到了系统复位上。

没有认真阅读正点原子开发指南,忽略了深度的问题。

模块框图:

时序图:

 

代码:

module  fifo_wr_ctrl(
    input       wire                sys_clk     , // clk_wr // 50Mhz
    input       wire                sys_rst_n   ,

    output      wire                rst_fifo    ,
    output      wire                wr_clk      ,
    output      wire    [7:0]       wr_din      ,
    output      reg                 wr_en       
);
    // parameter    
    parameter   RST_FIFO_CNT = 3    ,
                RST_WAIT_CNT = 30   ,
                DATA_IN_CNT  = 200  ; // 设置深度256,但实际深度只有255.写进数据0~254
    // localparam
    localparam  RST         = 4'b0001 ,
                RST_WAIT    = 4'b0010 ,
                DATA_IN_S   = 4'b0100 ,
                FINISH_S    = 4'b1000 ;
    // reg signal define
    reg     [7:0]       cnt_core    ;
    reg                 finish      ;
    reg     [3:0]       state       ;
    // wire signal define
    wire                rst_flag        ;
    wire                wait_flag       ;
    wire                data_over_flag  ;

    // reg     [7:0]       cnt_core    ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            cnt_core <= 8'd0 ;
        else if(rst_flag || wait_flag || data_over_flag || finish)
            cnt_core <= 8'd0 ;
        else 
            cnt_core <= cnt_core + 1'b1 ;
    end
    // reg                 finish          ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            finish <= 1'b0 ;
        else if(data_over_flag)
            finish <= 1'b1 ;
        else 
            finish <= finish ;
    end
    // reg     [3:0]       state       ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            state <= 4'b0001 ;
        else 
        case (state)
        RST         :   if(rst_flag)
                            state <= RST_WAIT ;
                        else 
                            state <= RST ;
        RST_WAIT    :   if(wait_flag)
                            state <= DATA_IN_S ;
                        else 
                            state <= RST_WAIT ;
        DATA_IN_S   :   if(data_over_flag)
                            state <= FINISH_S ;
                        else 
                            state <= DATA_IN_S ;
        FINISH_S    :   state <= FINISH_S ;
        default     :   state <= RST ;
        endcase
    end
    // wire                rst_flag        ;
    assign  rst_flag  = ((cnt_core == (RST_FIFO_CNT - 1)) && (state == RST)) ;
    // wire                wait_flag       ;
    assign  wait_flag = ((cnt_core == (RST_WAIT_CNT - 1)) && (state == RST_WAIT)) ;
    // wire                data_over_flag  ;
    assign  data_over_flag = ((cnt_core == (DATA_IN_CNT - 1)) && (state == DATA_IN_S)) ;
    // output      reg                 rst_fifo    ,
    // always @(posedge sys_clk or negedge sys_rst_n) begin
    //     if(~sys_rst_n) 
    //         rst_fifo <= 1'b1 ;
    //     else if(state == RST && rst_flag)
    //         rst_fifo <= 1'b1 ;
    //     else if(state == RST)
    //         rst_fifo <= 1'b0 ;
    //     else 
    //         rst_fifo <= 1'b1 ;  
    // end
    assign  rst_fifo = (state == RST) ? 1'b1 : 1'b0 ;
    // output      wire                wr_clk      ,
    assign  wr_clk = (sys_rst_n) ? sys_clk : 1'b0  ;
    // output      wire    [7:0]       wr_din      ,
    assign  wr_din = (state == DATA_IN_S) ? cnt_core : 8'd0 ;
    // output      reg                 wr_en       ,
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            wr_en <= 1'b0 ;
        else if(wait_flag || data_over_flag)
            wr_en <= ~wr_en ;
        else 
            wr_en <= wr_en ;
    end
    
endmodule
module  fifo_rd_ctrl(
    input       wire            sys_clk     ,// clk_rd
    input       wire            sys_rst_n   ,
    input       wire            wr_full     ,
    input       wire            almost_empty,// 将要读空

    output      reg             rd_en       ,
    output      wire            rd_clk      
);

    assign  rd_clk = (sys_rst_n) ? sys_clk : 1'b0 ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            rd_en <= 1'b0 ;
        else if(almost_empty) // 将要读空后拉低读使能。因为是时序逻辑,应该正好读空fifo
            rd_en <= 1'b0 ;
        else if(wr_full) // 写满后拉高写使能
            rd_en <= 1'b1 ;
        else 
            rd_en <= rd_en ;
    end
endmodule
module top(
    input       wire            sys_clk     ,
    input       wire            sys_rst_n   ,

    output      wire    [7:0]   data_out    
);
    // 例化间连线
	wire				clk_100Mhz	;
	wire				clk_50Mhz	;
	wire  				locked		;
	wire  				rst_n 		;

	wire                rst_fifo    ; // fifo的复位信号
	wire                wr_clk      ; // 写端口相关信号
	wire    [7:0]       wr_din      ; // 写端口相关信号
	wire                wr_en       ; // 写端口相关信号

    wire      [7:0]     dout		;
    wire                full		;
    wire                almost_full	;
    wire                empty		;
    wire                almost_empty;
    wire      [7:0]     rd_data_count;
    wire      [7:0]     wr_data_count;
    wire                wr_rst_busy	;
    wire                rd_rst_busy	;

	wire            	rd_en       ;
	wire            	rd_clk      ;

mmcm_100M_50M mmcm_100M_50M_inst (
	.resetn				( sys_rst_n 	) ,
	.clk_in1			( sys_clk 		) ,

	.clk_out1			( clk_100Mhz 	) ,
	.clk_out2			( clk_50Mhz  	) ,
	.locked				( locked	 	) 
);
	assign 	rst_n = sys_rst_n && locked ;

fifo_wr_ctrl fifo_wr_ctrl_inst(
    .sys_clk     		( clk_50Mhz 	) , // clk_wr // 50Mhz
    .sys_rst_n   		( rst_n     	) ,

    .rst_fifo    		( rst_fifo  	) ,
    .wr_clk      		( wr_clk    	) ,
    .wr_din      		( wr_din    	) ,
    .wr_en      		( wr_en     	) 
);

fifo_rd_ctrl fifo_rd_ctrl_inst(
    .sys_clk     		( clk_100Mhz 	) ,// clk_rd
    .sys_rst_n   		( rst_n 		) ,
    .wr_full     		( full 			) ,
    .almost_empty		( almost_empty  ) ,// 将要读空

    .rd_en       		( rd_en    		) ,
    .rd_clk     		( rd_clk   		)  
);

fifo_256X8 fifo_256X8_inst(
	.rst				( rst_fifo 		) ,  // 在fpga配置完成后,fifo必须要进行复位操作�?�复位信号至少保�?3个时钟周期以慢时钟为准�?�复位完成后至少经过30个时钟周期后,才能进行数据写操作�?
	.wr_clk				( wr_clk 		) ,  // 写数据时�?50Mhz // 复位高有效�??
	.rd_clk				( rd_clk 		) ,  // 读数据时�?100Mhz
	.din				( wr_din 		) ,  // 写入数据

	.wr_en				( wr_en 		) ,  // 写使�?
	.rd_en				( rd_en 		) ,  // 读使�?
	
	.dout				( data_out 		) ,  // 输出数据
	.full				( full			) ,  // 写满
	.almost_full		( almost_full	) ,  // 将写�?
	.empty				( empty			) ,  // 读空
	.almost_empty		( almost_empty	) ,  // 将读�?
	.rd_data_count		( rd_data_count	) ,  // 可读数据
	.wr_data_count		( wr_data_count	) ,  // 已写数据
	.wr_rst_busy		( wr_rst_busy	) ,  // 写复位忙�?
	.rd_rst_busy		( rd_rst_busy	)    // 读复位忙�?
); 

endmodule

 

`timescale 1ns/1ns
module  test_top();
    reg             sys_clk     ;
    reg             sys_rst_n   ;
    wire    [7:0]   data_out    ;


top top_inst(
    .sys_clk            ( sys_clk   ) ,
    .sys_rst_n          ( sys_rst_n ) ,

    .data_out           ( data_out  )  
);
    parameter CYCLE = 20 ;
    initial begin
        sys_clk = 1'b1 ;
        sys_rst_n <= 1'b0 ;
        #( CYCLE * 5) ;
        sys_rst_n <= 1'b1 ;
        #(3000*CYCLE) ;
        $stop;
    end
    always #(CYCLE/2) sys_clk = ~sys_clk ;
endmodule

 

仿真图:

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

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

相关文章

【UE5】物体沿样条线移动

目录 效果 步骤 一、使用样条线创建路径 二、创建沿样条线路径移动的物体 三、定义可移动物体的生成器 效果 步骤 一、使用样条线创建路径 先创建一个Actor蓝图&#xff0c;这里命名为“BP_Line” 该蓝图中只需添加一个样条组件 将“BP_Line”拖入场景中 按住Alt鼠标左键…

如何制定LinkedIn商进行品牌推广?

在网络上脱颖而出不是一件简单的事。不仅有比以往更多的平台、算法和内容类型&#xff0c;而且还有更多的企业在争夺注意力。据统计&#xff0c;每天有超过 270 万家公司在 LinkedIn 上发布信息。 策略很重要&#xff0c;尤其是在 LinkedIn 营销领域。下面将为你总结LinkedIn 营…

Spring Cloud与Spring Cloud Alibaba怎么正确引入依赖版本

一.Spring Cloud与Spring Cloud Alibaba与Springboot各版本的依赖关系 我们可以去springcloud alibaba的github仓库中的说明中查找到三个依赖版本的对应关系&#xff1a; 版本说明 alibaba/spring-cloud-alibaba Wiki GitHub 二.通过BOM对Spring Cloud与Spring Cloud Alib…

三江城115m²3室2厅2卫,现代简约不单是居所更是对生活的向往。福州中宅装饰,福州装修

【前言】 简洁有力&#xff0c;静默无声。 以简约精致的方式&#xff0c;展现现代都市生活&#xff1b; 经典不因潮流褪色&#xff0c;不为悦人只为悦己。 项目信息 项目名称 | 三江城 设计地址 | 福建福州 项目面积 | 115㎡ 项目户型 | 3室2厅 设计风格 | 现代简约 全…

BananaPi BPI-M6(Raspberry Pi 5) Android 平板电脑镜像测试温度

我已经在本文中介绍了 全新的Banana Pi BPI-M6&#xff0c;并讨论了其与Raspberry Pi 5的硬件特性比较。 然后我将 Android 平板电脑固件上传到 eMMC&#xff0c;从而使 Banana Pi 实际可用。一开始有点坎坷&#xff0c;但文章中有更多内容。 在另一台电脑上&#xff0c;一切都…

ubuntu 20.04安装 Anaconda教程

在安装Anaconda之前需要先安装ros(防止跟conda冲突&#xff0c;先装ros)。提前安装好cuda 和cudnn。 本博客参考&#xff1a;ubuntu20.04配置ros noetic和cuda&#xff0c;cudnn&#xff0c;anaconda&#xff0c;pytorch深度学习的环境 安装完conda后&#xff0c;输入: pyth…

在 HarmonyOS 上使用 ArkUI 实现计步器应用

介绍 本篇 Codelab 使用 ArkTS 语言实现计步器应用&#xff0c;应用主要包括计步传感器、定位服务和后台任务功能&#xff1a; 1. 通过订阅计步器传感器获取计步器数据&#xff0c;处理后显示。 2. 通过订阅位置服务获取位置数据&#xff0c;处理后显示。 3. 通过服务开…

vue2 mixin的方式 大屏适配(缩放居中的方式)

使用要求&#xff1a;指定容器的 id 为 bigScreenContainer 一、效果图 不管你的屏幕多大都会根据设计稿 1920*1080 进行缩放 图一&#xff1a;缩小的效果 图二&#xff1a;放大的效果 二、使用方式 <template><div id"bigScreenContainer" ref"big…

又在为年会头疼了?看易知微教你用数据可视化搭建工具制作年会抽奖大屏!

距离过年还有2个多月&#xff0c;但是各个公司的行政、组织部门已经接到了年会策划的通知&#xff0c;年会是公司内部重要的社交盛事之一&#xff0c;不仅可以展示公司的实力和成绩&#xff0c;还可以加强员工之间的沟通和团队合作意识。好的年会策划不仅要注重细节&#xff0c…

欧盟铅镉RSL邻苯项目化学物质检测报告办理(RSL Report 资质)REACH 认证

如果您在亚马逊上销售商品&#xff0c;则必须遵守所有适用的欧盟和地方法律法规&#xff0c;以及适用于这些商品和商品信息的亚马逊政策。要在亚马逊上销售某些商品&#xff0c;)您需要向我们提供 REACH 符合性声明或检测报告。 RSL-Phthalate资质 欧盟RSL邻苯项目检测报告 Ph…

一张图系列 - “position_embedding”

关于位置编码&#xff0c;我感觉应该我需要知道点啥&#xff1f; 0、需要知道什么知识&#xff1f; multi head atten 计算 复数的常识 1、embedding 是什么&#xff1f; position embedding常识、概念&#xff0c;没有会怎样&#xff1f; 交换token位置&#xff0c;没有P…

keil程序载入硬件成功,但未按代码执行

可能是因为keil版本的问题 1.在个人电脑上测试&#xff0c;安装keil软件如下。 2.测试stlinkv2仿真器&#xff0c;A202208\A202303\A202210,对1号和2号M3核心板验证。皆下载成功并执行程序。 程序如下: #include "stm32f10x.h" void delay_nms(u16 time); int ma…

【LeetCode刷题-滑动窗口】--487.最大连续1的个数II

487.最大连续1的个数II 方法&#xff1a;滑动窗口 维护一个区间&#xff0c;使得该区间中只包含一个0 class Solution {public int findMaxConsecutiveOnes(int[] nums) {int n nums.length;int left 0,right 0,sum 0;int zero 0; //计算0的个数while(right < n){if(…

mysql之rsync远程同步

&#xff08;一&#xff09;rsync 1、rsync&#xff1a;是一个开源的快速备份工具&#xff0c;可以在不同主机之间同步整个目录 2、在远程同步中&#xff0c;一个是源端&#xff0c;一个是发起端 &#xff08;1&#xff09;源端负责文件的原始位置&#xff0c;发起端和源端的…

《洛谷深入浅出进阶篇》P1995 程序自动分析——并查集,离散化

上链接&#xff1a;P1955 [NOI2015] 程序自动分析 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P1955 上题干&#xff1a; 首先给你一个整数t&#xff0c;代表t次操作。 每一次操作包含以下内容&#xff1a; 1.给你一个整数n&#xff0c;让…

node 第十八天 中间件express-session实现会话密钥

express-session 文档 express-session 一个简单的express会话中间件 使用场景 在一个系统中&#xff0c; 需要维持一个临时的与登录态无关的会话密钥 比如登录系统后&#xff0c; 请求某一个接口&#xff0c; 接口的行为与登录态无关&#xff0c; 也就是说任何人对接口的访问…

【java学习—十五】线程的通信(6)

文章目录 1. 线程通信1.1. wait() 方法&#xff1a;1.2. notify()/notifyAll() 方法 1. 线程通信 wait() 与 notify() 和 notifyAll()&#xff1a; ①wait()&#xff1a;令当前线程挂起并放弃 CPU 、同步资源&#xff0c;使别的线程可访问并修改共享资源&#xff0c;而当前线程…

Vue3 生命周期

如下是Vue3的生命周期函数图&#xff1a; 一、Vue2生命周期和Vue3声明周期的区别 1. Vue2 中&#xff0c;只要创建Vue实例对象而不需要挂载就可以实现beforeCreate 和 created 生命周期函数。 Vue3中必须要将Vue实例对象挂载完成&#xff0c;所有的准备工作做完&#xff0c;…

视频号视频怎么保存?教你三种方法

现在随着视频号的兴起&#xff0c;很多用户都喜欢在视频号上分享自己的生活、工作和兴趣爱好。但是很多人都遇到了一个问题&#xff0c;就是视频号上看到了喜欢的视频&#xff0c;想要保存下来&#xff0c;却不知道怎么做。今天我们就来教大家三种方法&#xff0c;让你轻松保存…