ZYNQ_project:ram_dual_port

伪双端口ram:写端口:clk_w,en_A,we_A,addr_A,din_A;读端口:clk_r,en_B,addr_B;dout_B.

设计读写模块,写入256个数据,再读出256个数据。

输入时钟100Mhz,输出时钟50Mhz。

多bit数据,高速时钟域到低速时钟域处理。

模块框图:

代码:

module ram_real_wr(
    input       wire            clk_w       ,
    input       wire            clk_r       ,
    input       wire            sys_rst_n   ,

    output      reg             en_A        ,
    output      reg             we_A        ,
    output      wire    [7:0]   addr_A      ,
    output      wire    [7:0]   din_A       ,

    output      reg             en_B        ,
    output      wire    [7:0]   addr_B      
);
    //  parameter
    parameter   WR_NUM = 256 ,
                RD_NUM = 256 ;

    reg     [7:0]       cnt_w   ; // 用来产生写地�?与写数据�?
    reg                 flag_wr ;
    reg                 done    ;
    reg     [7:0]       cnt_r   ;
    always @(posedge clk_w or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            cnt_w <= 8'd0 ;
        else if(en_A && we_A && (cnt_w == WR_NUM - 1))
            cnt_w <= 8'd0 ;
        else if(en_A && we_A)
            cnt_w <= cnt_w + 1'b1 ;
        else 
            cnt_w <= cnt_w;
    end
    always @(posedge clk_w or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            flag_wr <= 1'b1 ;
        else if(cnt_w == WR_NUM - 2)
            flag_wr <= 1'b0 ;
        else 
            flag_wr <= flag_wr ;
    end
    always @(posedge clk_w or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            en_A <= 1'b0 ; 
        else 
            en_A <= 1'b1 ;
    end
    always @(posedge clk_w or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            we_A <= 1'b0 ; 
        else 
            we_A <= flag_wr ;
    end
    assign  addr_A = (we_A) ? cnt_w : 8'd0 ;
    assign  din_A  = (we_A) ? cnt_w : 8'd0 ;

    always @(posedge clk_r or negedge sys_rst_n) begin
        if(~sys_rst_n)
            done <= 1'b0 ;
        else if(en_B && (cnt_r == RD_NUM - 2))
            done <= 1'b1 ;
        else 
            done <= done ; 
    end
    always @(posedge clk_r or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            en_B <= 1'b0 ;
        else if(~done) begin
            if(~flag_wr)
                en_B <= 1'b1 ;
            else 
                en_B <= 1'b0 ;
        end
        else
            en_B <= 1'b0 ;
    end
    always @(posedge clk_r or negedge sys_rst_n) begin
        if(~sys_rst_n)
            cnt_r <= 8'd0 ;
        else if(en_B && (cnt_r == RD_NUM - 1))
            cnt_r <= 8'd0 ;
        else if(en_B)
            cnt_r <= cnt_r + 1'b1 ;
        else
            cnt_r <= 8'd0 ;
    end
    assign addr_B = (en_B) ? cnt_r : 8'd0 ;

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            en_A        ;
	wire            we_A        ;
	wire    [7:0]   addr_A      ;
	wire    [7:0]   din_A       ;
	wire            en_B        ;
	wire	[7:0]	addr_B      ;
pll_clk pll_clk_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 ;
    
ram_real_wr ram_real_wr_inst(
    .clk_w       			( clk_100Mhz	) ,
    .clk_r       			( clk_50Mhz 	) ,
    .sys_rst_n   			( rst_n     	) ,

    .en_A        			( en_A  		) ,
    .we_A        			( we_A  		) ,
    .addr_A      			( addr_A		) ,
    .din_A       			( din_A 		) ,

    .en_B        			( en_B  		) ,
    .addr_B     			( addr_B		)  
); 
    
blk_mem_gen_0 blk_mem_gen_0_inst(
    .clka                   ( clk_100Mhz 	) , 
    .ena                    ( en_A  		) , 
    .wea                    ( we_A  		) , 
    .addra                  ( addr_A		) , 
    .dina                   ( din_A 		) , 

    .clkb                   ( clk_50Mhz 	) , 
    .enb                    ( en_B   		) , 
    .addrb                  ( addr_B 		) , 

    .doutb                  ( data_out 		) 
);

endmodule

改进一下,使得只读出偶数地址内的数据:

module ram_real_wr(
    input       wire            clk_w       ,
    input       wire            clk_r       ,
    input       wire            sys_rst_n   ,

    output      reg             en_A        ,
    output      reg             we_A        ,
    output      wire    [7:0]   addr_A      ,
    output      wire    [7:0]   din_A       ,

    output      reg             en_B        ,
    output      wire    [7:0]   addr_B      
);
    //  parameter
    parameter   WR_NUM = 256 ,
                RD_NUM = 256 ;

    reg     [7:0]       cnt_w   ; // 用来产生写地�?与写数据�?
    reg                 flag_wr ;
//    reg                 done    ;
    reg     [7:0]       cnt_r   ;
    always @(posedge clk_w or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            cnt_w <= 8'd0 ;
        else if(en_A && we_A && (cnt_w == WR_NUM - 1))
            cnt_w <= 8'd0 ;
        else if(en_A && we_A)
            cnt_w <= cnt_w + 1'b1 ;
        else 
            cnt_w <= cnt_w;
    end
    always @(posedge clk_w or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            flag_wr <= 1'b1 ;
        else if(cnt_w == WR_NUM - 2)
            flag_wr <= 1'b0 ;
        else 
            flag_wr <= flag_wr ;
    end
    always @(posedge clk_w or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            en_A <= 1'b0 ; 
        else 
            en_A <= 1'b1 ;
    end
    always @(posedge clk_w or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            we_A <= 1'b0 ; 
        else if(cnt_w == WR_NUM - 2)
            we_A <= 1'b0 ;
        else 
            we_A <= flag_wr ;
    end
    assign  addr_A = (we_A) ? cnt_w : 8'd0 ;
    assign  din_A  = (we_A) ? cnt_w : 8'd0 ;

    // always @(posedge clk_r or negedge sys_rst_n) begin
    //     if(~sys_rst_n)
    //         done <= 1'b0 ;
    //     else if(en_B && (cnt_r == RD_NUM - 2))
    //         done <= 1'b1 ;
    //     else 
    //         done <= done ; 
    // end
    // always @(posedge clk_r or negedge sys_rst_n) begin
    //     if(~sys_rst_n) 
    //         en_B <= 1'b0 ;
    //     else if(~done) begin
    //         if(~flag_wr)
    //             en_B <= 1'b1 ;
    //         else 
    //             en_B <= 1'b0 ;
    //     end
    //     else
    //         en_B <= 1'b0 ;
    // end
    // always @(posedge clk_r or negedge sys_rst_n) begin//只读出偶数地址的数据。
    //     if(~sys_rst_n) 
    //         en_B <= 1'b0 ;
    //     else if(~flag_wr) begin
    //         if(cnt_r[0]) // 奇数赋值1,读使能有效,偶数读使能无效。
    //             en_B <= 1'b1 ;
    //         else 
    //             en_B <= 1'b0 ;
    //     end
    //     else 
    //         en_B <= 1'b0 ;
    // end
    always @(posedge clk_r or negedge sys_rst_n) begin//只读出偶数地址的数据。
        if(~sys_rst_n) 
            en_B <= 1'b0 ;
        else if(~flag_wr && (cnt_r[0])) 
            en_B <= 1'b1 ;
        else 
            en_B <= 1'b0 ;
    end
    always @(posedge clk_r or negedge sys_rst_n) begin
        if(~sys_rst_n)
            cnt_r <= 8'd0 ;
        else if(~flag_wr && (cnt_r == RD_NUM - 1))
            cnt_r <= 8'd0 ;
        else if(~flag_wr)
            cnt_r <= cnt_r + 1'b1 ;
        else
            cnt_r <= 8'd0 ;
    end
    assign addr_B = (en_B) ? cnt_r : 8'd0 ;

endmodule

 

仿真图:

 

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

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

相关文章

05-Spring中Bean的生命周期

Bean的生命周期 生命周期就是对象从创建开始到最终销毁的整个过程 , Spring其实就是一个管理Bean对象的工厂,它负责对象的创建和销毁等 Bean生命周期的管理可以参考Spring的源码&#xff1a;AbstractAutowireCapableBeanFactory类的doCreateBean()方法 研究生命周期的意义&am…

消息中心常见解决方案分享

解决方案 1、问题2、设计3、流程 看了大部分的消息中心解决方案&#xff0c;发现大家的中心思想都大差不差&#xff0c;区别基本都是在符合自身业务场景的做了一些定制化处理。本文为我对消息中心基本骨架的知识梳理&#xff0c;亦在帮助大家对消息中心设计有一个基本的理解。 …

Centos, RockyLinux 常用软件安装汇总

一、基本指令&#xff1a; 命令作用clear清屏pwd显示当前路径cat / more显示文本文档uname -a查看当前版本hostnamectl查看当前版本cat /etc/redhat-release查看当前版本free查看剩余内存df -h[查看磁盘剩余空间]du -sh 查看文件夹名"dir"占用的空间lsof -i:8080查看…

进亦忧,退亦忧,Github Copilot 集成进入 Visual Studio 带来的思考

开篇想到《岳阳楼记》的结尾&#xff1a; 不以物喜&#xff0c;不以己悲&#xff1b;居庙堂之高则忧其民&#xff1b;处江湖之远则忧其君。是进亦忧&#xff0c;退亦忧。然则何时而乐耶&#xff1f;其必曰&#xff1a;“先天下之忧而忧&#xff0c;后天下之乐而乐”乎。未来30…

mini-vue 的设计

mini-vue 的设计 mini-vue 使用流程与结果预览&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><meta name&qu…

std::any

一、简介 std::any 可以储存任何可拷贝构造和可销毁的类型的对象。 struct test {test(int a,int b){} };int main(int argc, char *argv[]) {std::any a 1;qDebug() << a.type().name();a 3.14;qDebug() << a.type().name();a true;qDebug() << a.type…

LeetCode 189.轮转数组(三种方法解决)

文章目录 题目暴力求解空间换时间三段逆置总结 题目 LeetCode 189.轮转数组 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5…

2023 年最新企业微信官方会话机器人开发详细教程(更新中)

目标是开发一个简易机器人&#xff0c;能接收消息并作出回复。 获取企业 ID 企业信息页面链接地址&#xff1a;https://work.weixin.qq.com/wework_admin/frame#profile 自建企业微信机器人 配置机器人应用详情 功能配置 接收消息服务器配置 配置消息服务器配置 配置环境变量…

数据结构与算法【数组】Java实现

数组是一组元素组成的数据结构&#xff0c;元素类型必须相同&#xff0c;其次&#xff0c;数组内元素是连续存储的&#xff0c;因此数组中元素地址可以通过索引计算出来。 空间占用 在Java中&#xff0c;数组本质上也是一个对象&#xff0c;因此也存在对象头信息。那么数组的…

04-详解SpringBoot自动装配的原理,依赖属性配置的实现,源码分析

自动装配原理 依赖属性配置 提供Bean用来封装配置文件中对应属性的值 Data public class Cat {private String name;private Integer age; }Data public class Mouse {private String name;private Integer age; }cartoon:cat:name: "图多盖洛"age: 5mouse:name: …

若依Linux与Docker集群部署

若依Linux集群部署 1. 若依2.MYSQL Linux环境安装2.1 MYSQL数据库部署和安装2.2 解压MYSQL安装包2.3 创建MYSQL⽤户和⽤户组2.4 修改MYSQL⽬录的归属⽤户2.5 准备MYSQL的配置⽂件2.6 正式开始安装MYSQL2.7 复制启动脚本到资源⽬录2.8 设置MYSQL系统服务并开启⾃启2.9 启动MYSQL…

XoT:一种新的大语言模型的提示技术

这是微软在11月最新发布的一篇论文&#xff0c;题为“Everything of Thoughts: Defying the Law of Penrose Triangle for Thought Generation”&#xff0c;介绍了一种名为XOT的提示技术&#xff0c;它增强了像GPT-3和GPT-4这样的大型语言模型(llm)解决复杂问题的潜力。 当前提…

PHP原生类总结利用

再SPL介绍 SPL就是Standard PHP Library的缩写。据手册显示&#xff0c;SPL是用于解决典型问题(standard problems)的一组接口与类的集合。打开手册&#xff0c;正如上面的定义一样&#xff0c;有许多封装好的类。因为是要解决典型问题&#xff0c;免不了有一些处理文…

kr 第三阶段(九)64 位逆向

X64 汇编程序 64 位与 32 位的区别 更大的内存 64 位 CPU 与 32 位 CPU 的区别 引脚根数&#xff1a; x86 程序&#xff1a;20 根x64 程序&#xff1a;52 根&#xff0c;实际寻址的有 48 根&#xff0c;所以最大内存是 0~256T 寻址区间&#xff1a; x86 程序&#xff1a;0x0…

python实现一个简单的桌面倒计时小程序

本章内容主要是利用python制作一个简单的桌面倒计时程序&#xff0c;包含开始、重置 、设置功能。 目录 一、效果演示 二、程序代码 一、效果演示 二、程序代码 #!/usr/bin/python # -*- coding: UTF-8 -*- """ author: Roc-xb """import tkin…

汽车ECU的虚拟化技术初探(二)

目录 1.概述 2.U2A虚拟化方案概述 3.U2A的虚拟化功能概述 4.虚拟化辅助功能的使能 5.留坑 1.概述 在汽车ECU的虚拟化技术初探(一)-CSDN博客里&#xff0c;我们聊到虚拟化技术比较关键的就是vECU的虚拟地址翻译问题&#xff0c;例如Cortex-A77就使用MMU来进行虚实地址的转换…

阿里云国际站:专有宿主机

文章目录 一、专有宿主机的概念 二、专有宿主机的优势 三、专有宿主机的应用场景 一、专有宿主机的概念 专有宿主机&#xff08;Dedicated Host&#xff0c;简称DDH&#xff09;是阿里云专为企业用户定制优化的解决方案。具有物理资源独享、部署更灵活、配置更丰富、性价比…

遇到问题,我该如何提问?

作为IT行业的从业者&#xff0c;我们深知程序员在保障系统安全、数据防护以及网络稳定方面所起到的重要作用。他们是现代社会的护城河&#xff0c;用代码构筑着我们的未来。那程序员的护城河又是什么呢&#xff1f;是技术能力的深度&#xff1f;是对创新的追求&#xff1f;还是…

Linux yum,vim详解

yum是什么 yum是一个Linux系统预装的指令&#xff0c;yum的功能是可以对app进行搜索&#xff0c;下载&#xff0c;相当于Linux下的应用商店。 yum是读取Linux中镜像文件中的网页地址&#xff0c;下载用户所输入的命令。 如何使用yum下载软件 yum install -y(所有选项都yes) …

换根dp学习笔记

最近模拟赛经常做到&#xff0c;于是我就学习了一下。 算法原理 换根 d p dp dp的题一般都会给出一个无根树&#xff0c;因为以不同的点为根时&#xff0c;问题的答案不一样&#xff0c;所以它会让你输出答案的最大或最小值。 暴力去做这种题&#xff0c;就是以每个点为根然…