基于FPGA设计 的SRAM读写测试Verilog源码

SRAM的读写时序操作如下:

    因为在硬件上已经把CE和OE拉低了,所以如果不希望读写SRAM的时候,实际上SRAM的数据总线上的值是这时候的地址总线上的地址对应的数据。所以为了避免误操作,我们可以把地址总线置高阻态,其实我们不去操作数据总线(最好不是复用的数据总线)也无大碍。因为这样简化了软硬件的设计。上面的时序图,我们也只要关心ADDR,DATA总线和WE信号。

    具体操作是这样的,我们要写数据,(我这里是相对与用HDL操作SRAM而言的,软件读写可能有时间顺序的问题需要注意),那么比较高效率的操作是同时把WE拉低,送数据送地址,然后延时>TWC,把WE拉高,这时就把数据写入了相应地址了,就这么简单。因为数据的锁存不是在WE的上升沿,所以WE拉高后也没有必要保持数据总线的数据(即THD=0)。读数据就更简单了,只要把送需要读出的地址,然后延时>TAA后就可以读出你要的数据了。确实很简单的。

    如果要高效的读写SRAM,那么对于FPGA/CPLD来说,我假设目前这个芯片是10ns(TWC)的读取速度,系统时钟50MHz(20ns),我第一个时钟周期送地址,拉高(读)或者拉低(写)WE信号,送数据(写操作,读就把数据总线置高阻态),然后第二个时钟周期可以改变地址做下一步操作(如果是读数据这个时候同时把数据读出),如此下去,可以做到沿着时钟周期流水线般的读写数据。

 

module sram_test(
                clk,rst_n,led,
                sram_addr,sram_wr_n,sram_data
            );

input clk;        // 50MHz
input rst_n;    //低电平复位
output led;        // LED1

    // FPGA与SRAM外部接口
output[17:0] sram_addr;    // SRAM地址总线
output sram_wr_n;        // SRAM写选通
inout[15:0] sram_data;    // SRAM数据总线

//-------------------------------------------------------
reg[25:0] delay;    //延时计数器

always @ (posedge clk or negedge rst_n)
    if(!rst_n) delay <= 26'd0;
    else delay <= delay+1;    //不断计数,周期约为1.28s
    
//-------------------------------------------------------
reg[15:0] wr_data;    // SRAM写入数据总线    
reg[15:0] rd_data;    // SRAM读出数据 
reg[17:0] addr_r;    // SRAM地址总线
wire sram_wr_req;    // SRAM写请求信号
wire sram_rd_req;    // SRAM读请求信号
reg led_r;            // LED寄存器

assign sram_wr_req = (delay == 26'd9999);    //产生写请求信号
assign sram_rd_req = (delay == 26'd19999);    //产生读请求信号
    
always @ (posedge clk or negedge rst_n)
    if(!rst_n) wr_data <= 16'd0;
    else if(delay == 26'd29999) wr_data <= wr_data+1'b1;    //写入数据每1.28s自增1
always @ (posedge clk or negedge rst_n)
    if(!rst_n) addr_r <= 18'd0;
    else if(delay == 26'd29999) addr_r <= addr_r+1'b1;    //写入地址每1.28s自增1
    
always @ (posedge clk or negedge rst_n)
    if(!rst_n) led_r <= 1'b0;
    else if(delay == 26'd20099) begin    //每1.28s比较一次同一地址写入和读出的数据
            if(wr_data == rd_data) led_r <= 1'b1;    //写入和读出数据一致,LED点亮
            else led_r <= 1'b0;                        //写入和读出数据不同,LED熄灭
        end
assign led = led_r;

//-------------------------------------------------------
`define    DELAY_80NS        (cnt==3'd7)

reg[2:0] cnt;    //延时计数器

always @ (posedge clk or negedge rst_n)
    if(!rst_n) cnt <= 3'd0;
    else if(cstate == IDLE) cnt <= 3'd0;
    else cnt <= cnt+1'b1;
            
//------------------------------------
parameter    IDLE    = 4'd0,
            WRT0    = 4'd1,
            WRT1    = 4'd2,
            REA0    = 4'd3,
            REA1    = 4'd4;

reg[3:0] cstate,nstate;

always @ (posedge clk or negedge rst_n)
    if(!rst_n) cstate <= IDLE;
    else cstate <= nstate;

always @ (cstate or sram_wr_req or sram_rd_req or cnt)
    case (cstate)
            IDLE: if(sram_wr_req) nstate <= WRT0;        //进入写状态
                  else if(sram_rd_req) nstate <= REA0;    //进入读状态
                  else nstate <= IDLE;
            WRT0: if(`DELAY_80NS) nstate <= WRT1;
                  else nstate <= WRT0;                //延时等待160ns    
            WRT1: nstate <= IDLE;            //写结束,返回
            REA0: if(`DELAY_80NS) nstate <= REA1;
                  else nstate <= REA0;                //延时等待160ns
            REA1: nstate <= IDLE;            //读结束,返回
        default: nstate <= IDLE;
        endcase
            
//-------------------------------------

assign sram_addr = addr_r;    // SRAM地址总线连接

//-------------------------------------            
reg sdlink;                // SRAM数据总线控制信号

always @ (posedge clk or negedge rst_n)
    if(!rst_n) rd_data <= 16'd0;
    else if(cstate == REA1) rd_data <= sram_data;        //读出数据

always @ (posedge clk or negedge rst_n)
    if(!rst_n) sdlink <=1'b0;
    else
        case (cstate)
            IDLE: if(sram_wr_req) sdlink <= 1'b1;        //进入连续写状态
                  else if(sram_rd_req) sdlink <= 1'b0;    //进入单字节读状态
                  else sdlink <= 1'b0;
            WRT0: sdlink <= 1'b1;
            default: sdlink <= 1'b0;
            endcase

assign sram_data = sdlink ? wr_data : 16'hzz;    // SRAM地址总线连接            
assign sram_wr_n = ~sdlink;
            
endmodule
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GJZGRB

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值