ZYNQ_project:test_fifo_255X8

首先,这个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

 

仿真图:

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络安全-黑客技术(自学笔记)

前言 前几天发布了一篇 网络安全&#xff08;黑客&#xff09;自学 没想到收到了许多人的私信想要学习网安黑客技术&#xff01;却不知道从哪里开始学起&#xff01;怎么学 今天给大家分享一下&#xff0c;很多人上来就说想学习黑客&#xff0c;但是连方向都没搞清楚就开始学习…

python基于DETR(DEtection TRansformer)开发构建人员手持物品检测识别分析系统

PyTorch训练代码和DETR&#xff08;DEDetection-TRansformer&#xff09;的预训练模型。我们用Transformer替换了完全复杂的手工制作的对象检测管道&#xff0c;并将Faster R-CNN与ResNet-50匹配&#xff0c;使用一半的计算能力&#xff08;FLOP&#xff09;和相同数量的参数在…

vue3路由

vue3路由总结 vue3路由安装和引入&#xff1a;路由配置、创建 Router 实例&#xff1a;导航守卫 使用路由返回上一个页面没有跳转指定页 vue3路由 Vue3 路由是 Vue.js 3.x 版本中用于管理页面跳转和导航的模块。它基于 Vue Router 4.x&#xff0c;相较于 Vue2 的路由机制&…

来讲解一手事务隔离级别

简介 在数据库管理系统中&#xff0c;事务是一组被视为单一工作单元的操作&#xff0c;这些操作要么全部执行成功&#xff0c;要么全部回滚。为了确保在多用户并发访问数据库时数据的一致性和可靠性&#xff0c;引入了事务隔离级别的概念。事务隔离级别定义了一个事务对于其他…

餐厅订座预约小程序的效果如何

市场中无论哪种城市&#xff0c;餐厅非常多&#xff0c;一条不长的商业街&#xff0c;汇聚着数家餐饮品牌&#xff0c;且相互间竞争激烈&#xff0c;并且各个商家都希望用成本低高效率的方法引流及转化。 随着互联网深入各个行业&#xff0c;传统餐饮行业经营痛点不少。 传统餐…

(Matalb回归预测)WOA-BP鲸鱼算法优化BP神经网络的多维回归预测

目录 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 亮点与优势&#xff1a; 二、实际运行效果&#xff1a; 三、部分代码&#xff1a; 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 本代码基于Matalb平台编译&#xff0c;将WOA(鲸鱼算法)与BP神…

代码随想录算法训练营第五十五天 | LeetCode 583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结

代码随想录算法训练营第五十五天 | LeetCode 583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结 文章链接&#xff1a;两个字符串的删除操作、编辑距离、编辑距离总结 视频链接&#xff1a;两个字符串的删除操作、编辑距离 1. LeetCode 583. 两个字符串的删除操作 1.1 思…

YOLOv8环境搭建

YOLOv8环境搭建 torch环境安装requestment.txt文件中的包安装ultralytics调用 torch环境 使用的是python3.9版本 pip install torch-2.1.0cu118-cp39-cp39-linux_x86_64.whl torchvision0.16.0 torchaudio2.1.0 --index-url https://download.pytorch.org/whl/cu118安装reques…

GUI编程--PyQt5--QTreeWidget

文章目录 树型控件展示数据修改节点数据获取所有节点的数据 Qt模组参考 QWidgets QTreeWidget 树型控件展示数据 展示数据的同时&#xff0c;每个节点标注数据类型。 class MyWindow(QWidget):def __init__(self, title):super(MyWindow, self).__init__()self.setWindowTitl…

【SpringBoot篇】分页查询 | 扩展SpringMvc的消息转换器

文章目录 &#x1f6f8;什么是分页查询&#x1f339;代码实现⭐问题&#x1f384;解决方法 做了几个项目&#xff0c;发现在这几个项目里面&#xff0c;都实现了分页查询效果&#xff0c;所以就总结一下&#xff0c;方便学习 我们基于黑马程序员的苍穹外卖来讲解分页查询的要点…

el-table中el-popover失效问题

场景&#xff1a;先有一个数据表格&#xff0c;右侧操作栏为固定列&#xff0c;另外有一个字段使用了el-popover来点击弹出框来修改值&#xff0c;发现不好用&#xff0c;点击后无法显示弹出框&#xff0c;但当没有操作栏权限时却意外的生效了。 这种问题真是不常见&#xff0…

【蓝桥杯 第十五届模拟赛 Java B组】训练题(A - I)

目录 A、求全是字母的最小十六进制数 B、Excel表格组合 C、求满足条件的日期 D、 取数字 - 二分 &#xff08;1&#xff09;暴力 &#xff08;2&#xff09;二分 E、最大连通块 - bfs F、哪一天&#xff1f; G、信号覆盖 - bfs &#xff08;1&#xff09;bfs&#xf…

指静脉采集模组之调节Sensor

修改程序中gc0308_sensor_default_regs[]的类容&#xff0c;0x22寄存器的值改为0x55,关闭白平衡&#xff0c;0xd2寄存器的值改为0x10&#xff0c;关闭自动曝光。目前输出的图像没有自动曝光和自动白平衡&#xff0c;但是帧率比之前更低了。 以下是开启曝光模式和关闭曝光模式下…

论文排版一步搞定之图表题注——(图标自动编号,引用题注)

同学们在撰写研究生毕业大论文时&#xff0c;一定会进行章节的多次调整&#xff0c;不到最后一刻很难定稿。此时&#xff0c;一幅插图或表格位置的变化可能会导致此章内大部分插图或表格编号的变化&#xff0c;插图和表格编号的改变同样会使得前文的引用发生变化。牵一发而动全…

idea中误删.iml和.idea文件,如何处理

目录 一、问题描述 二、解决方案 1、理论知识 &#xff08;1&#xff09;.iml 文件 &#xff08;2&#xff09;.idea文件 2、操作环境 3、操作步骤 &#xff08;1&#xff09;找到【Maven】工具按钮 &#xff08;2&#xff09;点图标&#xff0c;重复导入maven项目&am…

【操作系统】内存的非连续分配管理

文章目录 前言非连续分配管理基本分页存储管理方式基本地址变换机构具有快表的地址变换机构两级页表 基本分段存储管理方式段页式管理方式 前言 在了解完内存的连续分配管理的三种方式后&#xff0c;可以看到它们之所以称之为连续分配是因为都有一个共同特点&#xff1a;每个进…

设计模式-适配器-笔记

适配器模式Adapter 动机&#xff08;Motivation&#xff09; 在软件系统中&#xff0c;由于应用环境的变化&#xff0c;常常需要将“一些现存的对象”放在新的环境中应用&#xff0c;但是新环境要求的接口是在这些现存对象所不满足的。 如何应对这种“迁移的变化”&#xff1…

QNX Typed memory介绍

文章目录 前言一、什么是 Typed memory二、查看系统已有Typed memory 的方法三、Typed memory 的使用方法1.定义一个packet memory并从系统内存中分出它1.1 as_add()1.2 as_add_containing()2. 从 Typed memory 中申请内存2.1 POSIX method 申请内存2.2 QNX Neutrino method 申…

redis设置密码

首先到redis的下载目录下&#xff1a;运行 redis-cli 查看redis密码&#xff1a; config get requirepass 设置redis密码为123456&#xff1a; config set requirepass 123456

GDS 命令的使用 srvctl service TAF application continuity

文档中prim and stdy在同一台机器上&#xff0c;不同机器需要添加address list TAF ENABLED GLOBAL SERVICE in GDS ENVIRONMNET 12C. (Doc ID 2283193.1)​编辑To Bottom In this Document Goal Solution APPLIES TO: Oracle Database - Enterprise Edition - Version 12.1.…