我们分两条主线来介绍SDRAM的读写:地址线和数据线
首先地址线上,在FPGA启动,延时500微妙。然后地址计数器cntwr每等到延时500us加1
(else if(delay_done) cntwr <=cntwr+1‘b1)
直到加到63,然后让地址寄存器addr加1。
(else if(!wr_done && cntwr ==6‘h3f) addr <= addr+1‘b1)
也就是说,32毫秒,地址线加1,但是这个地址线并不是最终送到SDRAM上的,只是产生的暂时地址信息。
----------------------------------------------------------------------------------------------------------
在数据线,FPGA启动,延时500微妙。为了写数据到写FIFO(写是名词,表示这个FIFO是用来写进数据的)而设定的计数器cnt于5时拉高写有效引脚,同时此时让数据寄存器wr_dinr加1,cnt与0d时,拉低写有效引脚,同时数据寄存器停止加1,结束数据写入,共写入8个数据。如此8个8个的往复写入!
(else if(!wr_done && ((cntwr >6‘h05) && (cntwr <= 6‘h0d)))begin
wrf_dinr <= wrf_dinr+1‘b1)
------------------------------------------------------------------------------------------------------------------------------
一旦数据写入FIFO达到8个,则激活系统写SDRAM请求信号sdram_wr_req,使之有效(高)
(assign sdram_wr_req = ((wrf_use >=9‘d8) & ~syswr_done))。
而sdram_wr_req有效,进而使读写状态机运行到`W_ACTIVE状态
(elseif(sdram_wr_req & sdram_init_done) begin
work_state_r <= `W_ACTIVE)。
从而顺势走向`W_WRITE状态。而一旦进入这个状态,将激活sdram_wr_ack信号
(assign sdram_wr_ack = (work_state ==`W_WRITE) | ((work_state == `W_WD) & (cnt_clk_r < 9‘d8)& (cnt_clk_r>= 9‘d0));)
这个信号控制着写FIFO内的数据是否传输到q引脚,所以sdram_wr_ack有效后,写FIFO的数据就会传输到q进而传输到与其相连的sys_data_in数据寄存器。由于进入了`W_WRITE状态,就会启动写数据模块sdram_wr_data,把数据送到SDRAM芯片的数据端口
(elseif((work_state == `W_WRITE) | ((work_state == `W_WD)&(cnt_clk <9‘d8)& (cnt_clk >= 9‘d0)))
sdr_din<=sys_data_in;)
(此状态完成一次后,进入等待状态IDEL,重新判断当前信息,如果满足,再次进入此状态,不满足此状态要求,进入其他状态)
-----------------------------------------------------------------------------------------------------------------------------------
再看地址线,在进入`W_WRITE状态时,我们是不知道此时addr已经计数到哪了,但是无论如何,到达`W_WRITE时,我们会把当前addr所形成的sys_addr的拆分成行,列数值数值传送到SDRAM的地址线上
(sdram_addr_r <= {
4‘b0010,
sys_addr[8:0] };
)
在传送地址的同时,数据也就跟着写进去了!就这样不停的传送地址,直到地址线加满。我们往SDRAM中写数据的时代也就过了
(else if(addr == 22‘h3fffff)
wr_done <= 1‘b1)。
---------------------------------------------------------------------------------------------------------------------------------------
这个时候地线写满标志syswr_done被激活
(assign syswr_done = wr_done)
同时由于读FIFO储存器之中数据为0,也就激活了往读FIFO储存器中写数据的信号线sdram_rd_req
(assign sdram_rd_req = ((rdf_use <=9‘d256) & syswr_done))
此信号一有效,状态机即进入读SDRAM数据的状态`W_READ
(else if(sdram_rd_req &&sdram_init_done) begin
work_state_r <= `W_ACTIVE;//读SDRAM
sys_r_wn <= 1‘b1;
)
在此状态下,会激活读数据请求信号sdram_rd_ack
(assign sdram_rd_ack = (work_state_r ==`W_RD) & (cnt_clk_r >= 9‘d0) & (cnt_clk_r < 9‘d8);)
这个信号有效则会使地址线由0开始自加1
(else if(wr_done && neg_rdack)
addr <=addr+1‘b1;)//neg_rdack是sdram_rd_ack有效后产生的脉冲
同时送到SDRAM地址线(此状态完成一次后,进入等待状态IDEL,重新判断当前信息,如果满足,再次进入此状态,不满足此状态要求,进入其他状态)
(sdram_addr_r <= {
4‘b0010, //A10=1,设置写完成允许预充电
sys_addr[8:0] //列地址
};
)
也就是说每次这个状态来临时,SDRAM地址线会更新加1。相比于写数据的时候,读数据的时候,地址是连续的,相当于遍历一遍所有地址。每次SDRAM地址线更新后,SDRAM的数据总线上的数据就会更新。把此数据传递给串口发送模块
(else if((work_state == `W_RD) &(cnt_clk >=9‘d0) & (cnt_clk < 9‘d8))
sdr_dout <= sdram_data; )
发给电脑上位机(关于串口发送模块,自行补脑)