我是靠谱客的博主 冷酷荔枝,最近开发中收集的这篇文章主要介绍verilog 实现 单口 ram ,我确定你看完后会彻底理解 ram,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

link

`timescale 1ns / 1ps

// Engineer: Reborn Lee
// Module Name: single_port_syn_ram


module single_port_syn_ram#(
	parameter ADDR_WIDTH = 4,   //地址位宽
	parameter DATA_WIDTH = 16,  // 数据位宽
	
	//内存 ram 的本质是一个一维的列表
	//对于这个 一维度的列表式的ram ,他的地址就是 一个序号而已
	//故而 ,列表的长度最大可以使 2的  ADDR_WIDTH(4) 次方,也就是16 
	//其实这里你可以设置成为 任何一个比16 小的数字
	
	parameter DEPTH = 2**ADDR_WIDTH    //ram 列表长度
	)(
	input  i_clk,                        //时钟信号
	input [ADDR_WIDTH - 1 : 0] addr,    // ram 地址参数
	inout [DATA_WIDTH - 1 : 0] data,    //这个是一个零时变量法,位宽与ram 一样,用于存放缓存的数据
	input cs,                             // 这是ram 使能 信号,表示是否操作这个ram 
	                                      //其实这个cs本质是一个选择符号
	input wr,                            // 写使能
	input oe                            // output enable,输出使能时RAM读取的结果才能输出

    );

    reg [DATA_WIDTH - 1 : 0] mem[0 : DEPTH - 1];   //ram 的位宽 是 16  DATA_WIDTH ,列表的长度是 DEPTH  16
    reg [DATA_WIDTH - 1 : 0] mid_data;             //中间缓存的寄存器

	// write part                                 //写数据部分
	always@(posedge i_clk) begin                  //在时钟上升沿
		if(cs&wr) begin                          //如果  cs=1 并且 写 wr=1  使能  ,则操作数据的写
			mem[addr] <= data;                   //数据放在缓存寄存器
		end
	end

	// read part
	always@(posedge i_clk) begin              //在时钟上升沿
		if(cs & !wr) begin           //如果  cs=1 并且 写 wr=0  使能  ,则操作数据的读数据,这里一共只有两个状态,
		                             //读和写,这里并没有 读使能 read_enable 
			mid_data <= mem[addr];   //数据放在缓存寄存器
		end
	end
//在读数据的时候,我们需要设计一个三态缓冲器,如下:
/***
读使能有效时,我们将从缓冲区读出的数据放到mid_data中,之后通过一个三态门来将数据mid_data输出到三态总线上,此三态门的使能条件为读使能!
这条语句在综合工具中就会被推断为一个三态缓冲器!
在读使能有效时,将读取数据放在总线上,否则呈现为高阻态,避免占用此数据总线。
***/
    //读使能有效时,我们将从缓冲区读出的数据放到mid_data中
    //这个例子中并没有读使能,当使能cs=1且& 输出使能 oe=1 且&  写使能 wr=0 的时候 ,将读取数据放在总线上,否则呈现为高阻态,避免占用此数据总线。
	assign data = (cs & oe & !wr)? mid_data: 'hz;  //读数据

endmodule



//下面是 testbench 
`timescale 1ns / 1ps

// Engineer: Reborn Lee
// Module Name: ram_tb

module ram_tb(

    );

	parameter ADDR_WIDTH = 4;         //地址位宽
	parameter DATA_WIDTH = 16;        // 数据位宽
	parameter DEPTH = 2**ADDR_WIDTH;   //ram 列表长度

	reg i_clk;                          //时钟
	reg [ADDR_WIDTH - 1 : 0] addr;       // ram 地址参数
	wire [DATA_WIDTH - 1 : 0] data;      //这个是一个零时变量法,位宽与ram 一样,用于存放缓存的数据
	reg cs;                              // 这是ram 使能 信号,表示是否操作这个ram 
	reg wr;                              // 写使能
	reg oe;                              // output enable,输出使能时RAM读取的结果才能输出

	reg [DATA_WIDTH-1:0] tb_data;        //这个是一个零时变量法,位宽与ram 一样,用于存放缓存的数据

	//generate system clock
	initial begin                        
		i_clk = 0;
		forever begin                     //这里的forever 不是绝对意义上的永远 而是,在数据读写的时候,永远每5ns 翻转一次
		                                 //就想说我永远爱你,不是从现在开始,到时间无涯的尽头一直爱你,而是在我的整个生命力,永远爱你
			# 5 i_clk = ~i_clk;          // 每5 ns 时钟翻转一次,
		end
	end

	assign data = !oe ? tb_data : 'hz;   // 写数据,
   // assign data =  tb_data ;
	initial begin
    {cs, wr, addr, tb_data, oe} = 0;    //一开始都置零
 
    repeat (2) @ (posedge i_clk);       //先来两个时钟周期



    //注意 verilog 是硬件描述语言,只要不涉及到时钟或者#的时延,都是同时 并行
    //不可以 有C 语言 和python 的方法学习 verilog 
    
    
    //write test
    //每个时钟周期,向 ram 中写一个随机数据,数据写的时候不能读 ,oe=0  输出使能0
    for (integer i = 0; i < 2**ADDR_WIDTH; i= i+1) begin
      repeat (1) @(negedge i_clk) addr = i; wr = 1; cs =1; oe = 0; tb_data = $random;
    end

    //read test
    //两次读写之间 有两个时钟周期的延时
    repeat (2) @ (posedge i_clk);    
     //每个时钟周期,向 ram 中读一个随机数据,数据读的时候不能写 ,wr=0  写使能 0 
    for (integer i = 0; i < 2**ADDR_WIDTH; i= i+1) begin
      repeat (1) @(posedge i_clk) addr = i; wr = 0; cs = 1; oe = 1;
    end
 
    #20 $finish;
  end
    //下面是函数调用的接口
    
	single_port_syn_ram #(
			.ADDR_WIDTH(ADDR_WIDTH),
			.DATA_WIDTH(DATA_WIDTH),
			.DEPTH(DEPTH)
		) inst_single_port_syn_ram (
			.i_clk (i_clk),
			.addr  (addr),
			.data  (data),
			.cs    (cs),
			.wr    (wr),
			.oe    (oe)
		);

endmodule



我用的是 vivado 21 秒学会 vivado 仿真

在这里插入图片描述

最后

以上就是冷酷荔枝为你收集整理的verilog 实现 单口 ram ,我确定你看完后会彻底理解 ram的全部内容,希望文章能够帮你解决verilog 实现 单口 ram ,我确定你看完后会彻底理解 ram所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(64)

评论列表共有 0 条评论

立即
投稿
返回
顶部