写在前面的话:之前都是写了一些关于在实践中遇到的问题。今天在和同门讨论中发现都在用Verilog实现一些IP核的功能,感觉自己有点落后了,不高兴。所以就开始着手试着实现一下,一开始有点蒙,一直用RAM但是正道自己用verilog 实现的时候,就发现你的了解的特别透彻。才能来时现。开始正文。

  RAM使我们经常用到的一个IP,在我们调用相关IP的时候就会发现RAM的种类还是挺多的。

第一步:认识RAM种类,并加以区别。

  单端口RAM:对应IP核中的Single-Port RAM,只有一组控制信号线、地址线和数据线,不能同时读写,某时刻只能在控制信号作用下作为数据输入或输出的一种;

  双端口RAM:对应IP核中的Dual-Port RAM,有两组独立的控制信号线、地址线和数据线,两组之间互不影响,允许两个独立的系统同时对其进行随机性的访问。即共享式多端口存储器,可以同时读写;

  伪双端口RAM:对应IP核中的Simple Dual-Port RAM,一个端口只读,一个端口只写;

注意双端口RAM同时对同一地址进行读写时,会出现仲裁;FIFO:先进先出数据缓冲器,也是一个端口只读,另一个端口只写。但是FIFO与伪双口RAM的不同,FIFO为先入先出,没有地址线,不能对存储单元寻址;而伪双口RAM两个端口都有地址线,可以对存储单元寻址。 

第二步:RAM与FIFO的相关联系以及应用场合   

  如FIFO实现专题所述,FIFO既可以利用寄存器实现,也可以使用RAM实现;实际上,规模较大的FIFO一般都是用RAM实现的(规模特别小的FIFO才会使用寄存器实现)。FIFO常用于数据传输缓存,避免数据丢失,如跨时钟域的数据传输就需要用到异步FIFO。RAM常用于暂存指令或中间数据,指令cache和数据cache就由RAM来实现。

第三步:实现这些RAM

  (1)单口RAM的实现:同步读,同步写

 

 1 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 2 // Project Name : 
 3 // Website      : https://home.cnblogs.com/lgy-gdeu/
 4 // Author         : LGY GUET Uiversity
 5 // Weixin         : li15226499835
 6 // Email          : 15277385992@163.com
 7 // File           : 
 8 // Create         : 2020
 9 // Revise         : 
10 // Editor         : sublime text{SUBLIME_VERSION}, tab size ({TABS})
11 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12 // Modification History:
13 // Date             By              Version                 Change Description
14 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
15 // {DATE} {TIME}    LGY           1.0                        ++++++++++++++++ 
16 // *********************************************************************************
17 `timescale      1ns/1ns
18 module signle_port_synrdwr #(
19     parameter           DATA_WIDTH   =   8,
20     parameter           ADDR_WIDTH   =   4,
21     parameter             DEEPTH  = 2**ADDR_WIDTH
22     )
23 (
24     //system signals
25     input                wire                             sclk       ,
26     input               wire                            sp_sy_oe  ,
27     input               wire                            sp_sy_wr  ,
28     input               wire                            sp_sy_cs  ,
29     input               wire   [ADDR_WIDTH-1:0]            spsy_addr ,
30     inout               wire   [DATA_WIDTH-1:0]            spsy_data 
31 );
32 
33 //========================================================================\
34 // ################ Define Parameter and Internal signals ################ 
35 //========================================================================/
36 reg                [DATA_WIDTH-1:0]       block_mem  [0:DEEPTH-1]   ; //相当于分配一个存储空间
37 reg             [DATA_WIDTH-1:0]       reg_spsy_data             ; //中间寄存器
38 
39 //=============================================================================
40 //+++++++++++++++++++++++++     Main Code    +++++++++++++++++++++++++++++++
41 //=============================================================================
42 //initialalization
43 integer    i ;
44 initial begin
45     for(i = 0 ; i< DEEPTH;i= i+1 )begin
46         block_mem[i]  = 8'h0 ;
47     end
48 end
49 
50 //out data 
51 assign  spsy_data  =  (sp_sy_cs & sp_sy_oe & !sp_sy_wr)? reg_spsy_data : 'hz;
52 
53 
54 //write port
55 always @(posedge sclk )begin
56     if(sp_sy_wr & sp_sy_cs )
57         block_mem[spsy_addr]    <=    reg_spsy_data;
58     else 
59         block_mem[spsy_addr]   <=   block_mem[spsy_addr];
60 end
61 
62 //read port 
63 always @(posedge sclk )begin
64     if(sp_sy_cs & !sp_sy_wr & sp_sy_oe)
65         reg_spsy_data    <=  block_mem[spsy_addr];
66 
67 end  
68 
69 endmodule
View Code

相关文章: