ZYNQ_project:ram_dual_port

news2024/10/6 16:31:06

伪双端口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

 

仿真图:

 

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

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

相关文章

Excel中使用数据验证、OFFSET实现自动更新式下拉选项

在excel工作簿中&#xff0c;有两个Sheet工作表。 Sheet1&#xff1a; Sheet2&#xff08;数据源表&#xff09;&#xff1a; 要实现Sheet1中的“班级”内容&#xff0c;从数据源Sheet2中获取并形成下拉选项&#xff0c;且Sheet2中“班级”内容更新后&#xff0c;Sheet1中“班…

小黑子—springMVC:第二章

springMVC入门2.0 4、小黑子的springMVC拦截器4.1 Interceptor简介4.2 拦截器快速入门4.3 拦截器执行顺序4.4 拦截器执行原理 5、小黑子的springMVC全注解开发5.1 spring-mvc.xml中组件转化为注解形式5.1.1 消除spring-mvc.xml一二三 5.1.2 消除web.xml 6、小黑子的springMVC组…

SpringBoot之手写starter

SpringBoot之手写starter 在开始之前呢&#xff0c;我们需要了解一些概念 1、starter介绍 spring boot 在配置上相比spring要简单许多, 其核心在于spring-boot-starter, 在使用spring boot来搭建一个项目时, 只需要引入官方提供的starter, 就可以直接使用, 免去了各种配置。…

数据分析面试题1

1.右表为一组数据&#xff0c;尝试进行简单分析&#xff0c;并给出结论&#xff08;使用公式和图表辅助&#xff09; ①理解数据 userid&#xff1a;用户id神兽印记消耗数量 ②数据清洗 冻结首行&#xff0c;将列标题的英文字段转换成汉字字段检查是否有重复项&#xff1a;…

计算机指令考前小记

RTL寄存器传送语言&#xff1a;简化对指令功能的说明 R[r]&#xff1a;存储器r的内容M[addr]&#xff1a;存储单元addr的内容M[R[r]]&#xff1a;寄存器r的内容所指的存储单元的内容 汇编指令movw 4(%ebp),%ax的RTL语言为&#xff1a;R[ax] <- M[R[ebp]4] 将寄存器EBP的内…

【C++】【Opencv】minMaxLoc()函数详解和示例

minMaxLoc&#xff08;&#xff09;函数 是 OpenCV 库中的一个函数&#xff0c;用于找到一个多维数组中的最小值和最大值&#xff0c;以及它们的位置。这个函数对于处理图像和数组非常有用。本文通过参数和示例详解&#xff0c;帮助大家理解和使用该函数。 参数详解 函数原型…

CSS特效007:绘制3D文字,类似PS效果

css实战中&#xff0c;怎么绘制3D文字呢&#xff1f; 实际上理论很简单&#xff0c;使用text-shadow&#xff0c;根据需要调整阴影的颜色、大小、偏移量等参数&#xff0c;以达到你想要的立体效果。下面是一个简单的示例。关键点就是知道如何设置text-shadow。 效果图 源代码 …

Scikit-LLM:一款大模型与 scikit-learn 完美结合的工具!

Scikit-LLM 是文本分析领域的一项重大变革&#xff0c;它将像 ChatGPT 这样强大的语言模型与 scikit-learn 相结合&#xff0c;提供了一套无与伦比的工具包&#xff0c;用于理解和分析文本。 有了 scikit-LLM&#xff0c;你可以发现各种类型的文本数据中的隐藏模式、情感和上下…

python类中的抽象函数,以及继承后子类的比较

抽象函数的定义方式 导包 from abs import ABCMeta,abstractmethod声明抽象类 class Area(object):abstractmethoddef area(self):pass在抽象类中&#xff0c;不用写构造函数&#xff0c;抽象类不能进行实例化 继承抽象类的子类必须将抽象类中的函数进行重写&#xff08;不重…

Mathtype公式自动转Word自带公式

Mathtype公式自动转Word自带公式 前言/word技巧探索过程参考资料&#xff08;有效与无效&#xff09;全自动方案/代码/教程 前言/word技巧 word公式 用ALT号可以输入简单latex显示公式&#xff1b;复杂度&#xff0c;需要引入latex包的不行&#xff1b;显示不出来的话按一下en…

3分钟带你了解前端缓存-HTTP缓存

前情提要 前端缓存分为下面三大类&#xff0c;本文主要讲解HTTP缓存~ 1. HTTP缓存 强缓存协商缓存 2. 浏览器缓存 本地小容量缓存本地大容量缓存 3. 应用程序缓存 HTML5应用程序缓存 缓存作用 减少了冗余的数据传输减少服务器的负担提高了网站的性能加快加载网页速度 …

初阶JavaEE(17)Linux 基本使用和 web 程序部署

接上次博客&#xff1a;初阶JavaEE&#xff08;16&#xff09;博客系统&#xff08;Markdown编辑器介绍、博客系统功能、博客系统编写&#xff1a;博客列表页 、博客详情页、实现登录、实现强制登录、显示用户信息、退出登录、发布博客&#xff09;-CSDN博客 目录 Linux 基本…

Unity中Shader雾效的实现方法一

文章目录 前言一、在片元着色器中使用如下公式计算最终的颜色 lerp(雾效颜色&#xff0c;物体颜色&#xff0c;雾效混合因子)1、获取雾效颜色2、物体的颜色一般通过纹理采样得到&#xff0c;此处用 1 代替测试3、获取 雾效混合因子&#xff08;由 雾的距离 和 雾的浓度决定&am…

生成式AI - Knowledge Graph Prompting:一种基于大模型的多文档问答方法

大型语言模型&#xff08;LLM&#xff09;已经彻底改变了自然语言处理&#xff08;NLP&#xff09;任务。它们改变了我们与文本数据交互和处理的方式。这些强大的AI模型&#xff0c;如OpenAI的GPT-4&#xff0c;改变了理解、生成人类类似文本的方式&#xff0c;导致各种行业出现…

mysql主从复制-使用心得

文章目录 前言环境配置主库从库 STATEMENTbinloggtidlog-errorDistSQL总结 前言 mysql 主从复制使用感受&#xff0c;遇到一些问题的整理&#xff0c;也总结了一些排查问题技巧。 环境 mysql5.7 配置 附&#xff1a;千万级数据快速插入配置可以参考&#xff1a;mysql千万数…

把字符串转换为整数函数atoi

今天我们来认识一个函数&#xff0c;叫atoi&#xff0c;我们开始研究它吧&#xff01; 1.认识atoi 1.函数功能&#xff1a;将字符串转换为整数 只能将整数字符串转换为整数&#xff0c;不能转换字符字符串 2.头文件&#xff1a;#include<stdlib.h> 3.使用格式&#xff1a…

从0到0.01入门React | 001.精选 React 面试题

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

sqli-labs关卡12(基于post提交的双引号闭合的字符型注入)通关思路

文章目录 前言一、回顾第十一关知识点二、靶场第十二关通关思路1、判断注入点2、爆显位个数3、爆显位位置4、爆数据库名5、爆数据库表名6、爆数据库列名7、爆数据库数据 总结 前言 此文章只用于学习和反思巩固sql注入知识&#xff0c;禁止用于做非法攻击。注意靶场是可以练习的…

数据代理机制

目录 前言 Object.defineProperty() 语法 第三个参数配置项 数据代理机制的实现 MVVM分层思想 前言 本文介绍Vue的数据代理机制&#xff0c;也就是通过vue实例对象来代理data对象中的属性的操作 Object.defineProperty() 在介绍vue的数据代理机制前&#xff0c;我们需要…

Java --- JVM的执行引擎

目录 一、执行引擎概述 1.1、执行引擎的工作过程 二、Java代码编译和执行的过程 三、解释器 3.1、解释器工作机制 3.2、解释器分类 3.3、解释器现状 四、JIT编译器 五、热点代码及探测方式 六、方法调用计数器 6.1、热点衰减 七、回边计数器 八、HotSpot VM设置程序…