总之只要阅读操作手册,按照时序来,完全不难!
器件记录:
小梅哥AC620上SDRAM:M12L2561616A-6TG2T
其的存储空间为16M*16=256MB,第二行的数字则与其速度等级有关;其分为:
4bank*16bit*4M 即:8192*512 = 2^13 * 2^9 = 2^22 = 4M
bank数目*数据位宽*存储深度
HY57V281620F,所以其具备的是
4bank*16bits*2M 即 2^12 * 2^9 = 2^21 = 2M
SDRAM原理:
SDRAM 存储数据是利用了电容能够保持电荷以及其充放电特性。一位数据的存取电路 如图 所示,该存储单元主要由行列选通三极管,存储电容,刷新放大器组成。对于这 一位的数据,首先需要打开行地址,然后打开列地址,则电容的电平状态就能呈现在数据线 (data_bit)上,即实现了读取。 或者,数据线上的电平值被送到电容上,从而实现写入数据。
但是,打开行地址(激活行)是需要一定时间的,即从打开行地址到可以打开列地址进 行数据读/写,这之间有一定的时间间隔,这个间隔叫做 tRCD(ACTIVE-to-READ or WRITE delay),对于不同型号或不同速度等级的器件,这个值是不一样的。
需要自行查阅产品手册获得这个速度等级,而M12L2561616A-6则对应的是速度等级6,其tRCD等于18ns。
当列地址被打开后,数据并不是立即出现在最终的数据总线引脚上,而是有若干个时钟 的延迟,这个延迟叫做列选通潜伏期(CL,CL = CAS (READ) latency)。如图 32.3 为不同速 度等级的器件的列选通潜伏期值,速度等级不一样,其值也是不一样的。
用户手册原文:
Bank activate 命令用于在空闲 Bank 中选择随机行。通过将 RAS 和 CS 以及所需的行和存储体地址置为低电平,即可启动行访问。从存储体激活时间起,经过 tRCD(min) 的时间延迟后,可以进行读或写操作。 tRCD是SDRAM的内部时序参数,因此它取决于工作时钟频率。
SDRAM命令
不同的SDRAM命令是一样的,如果不一样说明可能使用的命令不是低有效吧。(或者有额外的命令控制)
执行时间
除了在指定的命令外,我们还需要关心执行命令所需的时间。
例如:
M12L2561616A-6TG2T:
初始化时序(小梅哥文档):
tRP :预充电需要时间;
tRFC:自刷新需要的周期
tRAS:激活行需要的时间
tRCD:激活到读或写命令的延迟(激活行到列操作的时间)
HY57V281620F:
Brust length
对于SDRAM来说,区分于RAM和FIFO的读写方法,并不是连续地给出读写使能和地址,而是一次读写操作"Brust length"长度的数据。
SDRAM的读指令都是默认突发的,但是写指令可以不突发,直接写一整行。
自动刷新:
自动刷新(AUTO REFRESH)一般用于对 SDRAM 进行常规操作的 过程中。该命令是非持续性的,即每次需要时,都需要发送此命令。在执 行自动刷新命令之前,所有的 BANK 必须被预充电(关闭)。在自动刷新 和预充电命令之间,必须间隔最少 tRP 时间。自动刷新时,行地址由 SDRAM 芯片内部的刷新控制器自动更新,因此,在执行自动刷新命令时, 用户不需要关心地址总线上的值。不管器件的数据位宽是多少,对于 256Mbit 的 SDRAM,在商业和工业级的器件中,每 64ms 内需要执行 8192 次自动刷新操作,即每 7.813us 执行一次;在汽车级的器件中,每 16ms 内 执行 8192 次自动刷新操作,即每 1.953us 执行一次。另外,自动刷新操作 也可以采用突发的方式执行,即每 64ms(商业和工业级)/16ms(汽车级) 都连续不间断的执行 8192 次自动刷新命令,然后其他时间再执行读写或 者其他命令。如图 32.10 为刷新过程示意图。
一些差别:
M12L2561616A-6TG2T的自动刷新需要先发送预充电命令(ALL BANK),而且需要发送两次刷新指令,即需要一个tRP和两个tRFC的时间,而HY57V281620F却不需要,仅需要发送刷新指令然后等待刷新完成即可。
后面的读写时序其实根据不同的器件来看还是有很多不一样的步骤的,请按照自己的芯片的操作手册来,应该不会有问题。
比较重要的是仲裁器的写法,根据划定好的优先级来约束就好了。
可参考:
参数配置:
//COMMAND = {CS_N,RAS_N,CAS_N,WE_N};
parameter COMMAND_MRS = 4'b0000 ;
parameter COMMAND_ARF = 4'b0001 ;
parameter COMMAND_PRE = 4'b0010 ;
parameter COMMAND_ACT = 4'b0011 ;
parameter COMMAND_WRITE = 4'b0100 ;
parameter COMMAND_READ = 4'b0101 ;
parameter COMMAND_interrupt = 4'b0110 ;
parameter COMMAND_NOP = 4'b0111 ;
//time_wait
parameter TIME_WAIT_ABOVE_100US = 10000 ;//wait_time > 100us set:200us Power up wait time
parameter TIME_PRE_CHARGE = 2 ;//tRP > 18ns set:40ns; Precharge cost time
parameter TIME_Auto_refresh = 5 ;//tRFC=TRRC > 60ns set:100ns ARF cost time
parameter TIME_MRS_done_wait = 2 ;//During 2CLK following this command, the SDRAM cannot accept any other commands.
//MRS_OPCODE
parameter INIT_OPMODE_Brust_Mode = 1'b0 ;//A9
parameter INIT_OPMODE_STANDRD = 2'b00 ;//A8 A7
parameter INIT_CAS_Latency = 3 ;//A6 A5 A4 ;CAS Latency ( 2 & 3 )
parameter INIT_Burst_type = 1'b0 ;//A3 0:Sequential 1:Interleave
parameter INIT_Burst_length = 4 ;//A2 A1 A0 ;Burst Length ( 1, 2, 4, 8 & full page )
parameter INIT_OPMODE_Brust_Length = (INIT_Burst_length == 1)?(3'b000):
(INIT_Burst_length == 2)?(3'b001):
(INIT_Burst_length == 4)?(3'b010):
(INIT_Burst_length == 8)?(3'b011):(3'b111);//( 1, 2, 4, 8 & full page )
parameter INIT_OPMODE_CL = (INIT_CAS_Latency == 2)?(3'b010):(3'b011);//A6 A5 A4 ;
//auto refresh
parameter ARF_PERIOD = 750;// ARF_period = Row_nums/64ms 64ms = 64_000us = 64_000_000ns = 3_200_000 cycles (1 ARF/782 cycles)
//ACT
parameter TIME_RCD = 3;//tRCD > 20ns act RAS to CAS delay
主控制器和仲裁:
1.状态机的状态位宽要对齐。
module SDRAM_CTRL_TOP #(
parameter SDRAM_DATA_WIDTH = 16,
parameter SDRAM_BANK_WIDTH = 2 ,
parameter SDRAM_ADDR_WIDTH = 12
)(
input wire Sys_clk,
input wire Rst_n ,
//SDRAM
//COMMAND
output wire SDRAM_CS_N ,
output wire SDRAM_RAS_N ,
output wire SDRAM_CAS_N ,
output wire SDRAM_WE_N ,
output wire SDRAM_CKE ,
output wire [1:0] SDRAM_DQM ,
output wire SDRAM_CLK ,
output reg [SDRAM_ADDR_WIDTH-1:0] SDRAM_A_ADDR ,
output reg [SDRAM_BANK_WIDTH-1:0] SDRAM_BANK_ADDR ,
//DATA
inout [SDRAM_DATA_WIDTH-1:0] SDRAM_DQ
);
`include "D:/three_verilog/SDRAM/SDRAM_init/rtl/sdram_param.h"
localparam STATE_IDLE = 6'b00_0001;
localparam STATE_INIT = 6'b00_0010;
localparam STATE_ARB = 6'b00_0100;
localparam STATE_ARF = 6'b00_1000;
localparam STATE_RD = 6'b01_0000;
localparam STATE_WE = 6'b10_0000;
//Main
reg [3:0] SDRAM_COMMAND_SEND;
reg [5:0] STATE ;
wire [SDRAM_DATA_WIDTH-1:0] WR_SDRAM_DQ ;
wire WR_avai ;
//init
wire INIT_DONE ;
wire [3:0] COMMAND_INIT ;
wire [SDRAM_ADDR_WIDTH-1:0] INIT_A_ADDR ;
wire [SDRAM_BANK_WIDTH-1:0] INIT_BANK_ADDR ;
//ARF
wire ARF_access ;
wire [3:0] COMMAND_REF ;
wire [SDRAM_ADDR_WIDTH-1:0] ARF_A_ADDR ;
wire [SDRAM_BANK_WIDTH-1:0] ARF_BANK_ADDR ;
wire REF_DONE ;
wire ARF_req ;
//WR
wire WR_req ;
wire WR_access ;
wire [3:0] COMMAND_WR ;
wire [SDRAM_ADDR_WIDTH-1:0] WR_A_ADDR ;
wire [SDRAM_BANK_WIDTH-1:0] WR_BANK_ADDR ;
wire WR_data_done ;
wire FIFO_WR_EN ;
wire [7:0] FIFO_WR_data ;
//RD
wire RD_req ;
wire RD_access ;
wire RD_data_done ;
//break
wire Break_WR_to_ARF ;
wire Break_RD_to_ARF ;
wire Break_RD_to_WR ;
assign WR_avai = (STATE == STATE_WE)?1'b1:1'b0;
assign SDRAM_DQ = (WR_avai == 1'b1)?WR_SDRAM_DQ :16'dz;
assign SDRAM_DQM = 2'b00 ;
assign SDRAM_CKE = 1'b1 ;
assign SDRAM_CLK = Sys_clk;
assign {SDRAM_CS_N,
SDRAM_RAS_N,
SDRAM_CAS_N,
SDRAM_WE_N } = SDRAM_COMMAND_SEND;
always@(posedge Sys_clk or negedge Rst_n) begin
if(Rst_n == 'd0) begin
SDRAM_COMMAND_SEND <= COMMAND_NOP;
end else if(STATE == STATE_INIT) begin
SDRAM_COMMAND_SEND <= COMMAND_INIT ;
SDRAM_A_ADDR <= INIT_A_ADDR ;
SDRAM_BANK_ADDR <= INIT_BANK_ADDR;
end else if(STATE == STATE_ARF) begin
SDRAM_COMMAND_SEND <= COMMAND_REF ;
SDRAM_A_ADDR <= ARF_A_ADDR ;
SDRAM_BANK_ADDR <= ARF_BANK_ADDR ;
end else if(STATE == STATE_WE) begin
SDRAM_COMMAND_SEND <= COMMAND_WR ;
SDRAM_A_ADDR <= WR_A_ADDR ;
SDRAM_BANK_ADDR <= WR_BANK_ADDR ;
end
end
//access
assign ARF_access = (STATE == STATE_ARB) && (ARF_req == 1'b1);
assign WR_access = (STATE == STATE_ARB) && (WR_req == 1'b1)
&& (ARF_req == 1'b0);
assign RD_access = (STATE == STATE_ARB) && (RD_req == 1'b1)
&& (WR_req == 1'b0 ) && (ARF_req == 1'b0);
//-------------------STATE MAIN-----------------------//
always@(posedge Sys_clk or negedge Rst_n) begin
if(Rst_n == 'd0) begin
STATE <= STATE_IDLE;
end else begin
case (STATE) //ARG > WR > RD
STATE_IDLE: begin
STATE <= STATE_INIT;
end
STATE_INIT: begin
if(INIT_DONE == 'd1) begin
STATE <= STATE_ARB;
end else begin
STATE <= STATE_INIT;
end
end
STATE_ARB: begin
if(ARF_req == 1'b1) begin
STATE <= STATE_ARF;
end else if(WR_req == 1'b1 && ARF_req == 1'b0) begin
STATE <= STATE_WE;
end else if(RD_req == 1'b1 && WR_req == 1'b0 && ARF_req == 1'b0) begin
STATE <= STATE_RD;
end else begin
STATE <= STATE_ARB;
end
end
STATE_ARF: begin
if(REF_DONE == 1'b1) begin
STATE <= STATE_ARB;
end else begin
STATE <= STATE_ARF;
end
end
STATE_WE: begin
if(Break_WR_to_ARF == 1'b1) begin
STATE <= STATE_ARB;
end else if(WR_data_done == 1'b1) begin
STATE <= STATE_ARB;
end else begin
STATE <= STATE_WE;
end
end
STATE_RD: begin
if(RD_data_done == 1'b1) begin
STATE <= STATE_ARB;
end else if(Break_RD_to_WR == 1'b1) begin
STATE <= STATE_ARB;
end else if(Break_RD_to_ARF == 1'b1) begin
STATE <= STATE_ARB;
end else begin
STATE <= STATE_RD;
end
end
default: begin
STATE <= STATE_IDLE;
end
endcase
end
end
/*-------------------instance begin---------------------------*/
SDRAM_INIT INST0_SDRAM_INIT(
//input
.Sys_clk ( Sys_clk ),
.Rst_n ( Rst_n ),
//output
.COMMAND_INIT ( COMMAND_INIT ),
.INIT_A_ADDR ( INIT_A_ADDR ),
.INIT_BANK_ADDR ( INIT_BANK_ADDR ),
.INIT_DONE ( INIT_DONE )
);
SDRAM_ARF INST0_SDRAM_ARF (
.Sys_clk ( Sys_clk ),
.Rst_n ( Rst_n ),
.INIT_DONE ( INIT_DONE ),
.ARF_access ( ARF_access ),
.COMMAND_REF ( COMMAND_REF ),
.ARF_A_ADDR ( ARF_A_ADDR ),
.ARF_BANK_ADDR ( ARF_BANK_ADDR ),
.REF_DONE ( REF_DONE ),
.ARF_req ( ARF_req )
);
SDRAM_WR INST0_SDRAM_WR(
.Sys_clk ( Sys_clk ),
.Rst_n ( Rst_n ),
.FIFO_WR_EN ( FIFO_WR_EN ),
.FIFO_WR_data ( FIFO_WR_data ),
.INIT_DONE ( INIT_DONE ),
.ARF_req ( ARF_req ),
.WR_access ( WR_access ),
.COMMAND_WR ( COMMAND_WR ),
.WR_A_ADDR ( WR_A_ADDR ),
.WR_BANK_ADDR ( WR_BANK_ADDR ),
.WR_data_done ( WR_data_done ),
.WR_req ( WR_req ),
.Break_WR_to_ARF ( Break_WR_to_ARF ),
.WRITE_SDRAM_DQ ( WR_SDRAM_DQ )
);
/*-------------------instance end-----------------------------*/
endmodule
初始化:
1.初始化只需要进行一次。
module SDRAM_INIT(
input wire Sys_clk ,
input wire Rst_n ,
output reg [ 3:0] COMMAND_INIT ,//COMMAND = {CS_N,RAS_N,CAS_N,WE_N}
output reg [11:0] INIT_A_ADDR ,
output reg [ 1:0] INIT_BANK_ADDR,
output reg INIT_DONE
);
`include "D:/three_verilog/SDRAM/SDRAM_init/rtl/sdram_param.h"
localparam TIME_TO_PRE = TIME_WAIT_ABOVE_100US;
localparam TIME_TO_ARF = TIME_WAIT_ABOVE_100US + TIME_PRE_CHARGE;
localparam TIME_TO_ARF_2 = TIME_WAIT_ABOVE_100US + TIME_PRE_CHARGE
+ TIME_Auto_refresh;
localparam TIME_TO_MRS = TIME_WAIT_ABOVE_100US + TIME_PRE_CHARGE
+ TIME_Auto_refresh + TIME_Auto_refresh;
localparam INIT_END = TIME_TO_MRS + TIME_MRS_done_wait ;
reg [13:0] INIT_CNT ;
reg INIT_DONE_NOW;
always@(posedge Sys_clk or negedge Rst_n) begin
if(Rst_n == 'd0) begin
INIT_DONE <= 'd0;
end else if(INIT_CNT == INIT_END) begin
INIT_DONE <= 'd1;
end else begin
INIT_DONE <= 'd0;
end
end
always@(posedge Sys_clk or negedge Rst_n) begin
if(Rst_n == 'd0) begin
INIT_DONE_NOW <= 1'b0;
end else if(INIT_CNT == INIT_END) begin
INIT_DONE_NOW <= 1'b1;
end else begin
INIT_DONE_NOW <= INIT_DONE_NOW;
end
end
always @(posedge Sys_clk or negedge Rst_n) begin
if(Rst_n == 'd0) begin
INIT_CNT <= 'd0;
end else if(INIT_DONE_NOW == 1'b0) begin
if(INIT_CNT == INIT_END) begin
INIT_CNT <= 'd0;
end else begin
INIT_CNT <= INIT_CNT + 1'b1;
end
end else begin
INIT_CNT <= 'd0;
end
end
always @(posedge Sys_clk or negedge Rst_n) begin
if(Rst_n == 'd0) begin
COMMAND_INIT <= COMMAND_NOP;
INIT_A_ADDR <= 12'd0 ;
INIT_BANK_ADDR <= 2'b00 ;
end else begin
case (INIT_CNT)
TIME_TO_PRE: begin
COMMAND_INIT <= COMMAND_PRE;
INIT_A_ADDR[10] <= 1'b1;
end
TIME_TO_ARF: begin
COMMAND_INIT <= COMMAND_ARF;
end
TIME_TO_ARF_2: begin
COMMAND_INIT <= COMMAND_ARF;
end
TIME_TO_MRS: begin
COMMAND_INIT <= COMMAND_MRS;
INIT_A_ADDR <= {
2'b00 ,//A11 A10
INIT_OPMODE_Brust_Mode ,//A9
INIT_OPMODE_STANDRD ,//A8 A7
INIT_OPMODE_CL ,//A6 A5 A4 ;CAS Latency ( 2 & 3 )
INIT_Burst_type ,//A3 0:Sequential 1:Interleave
INIT_OPMODE_Brust_Length //A2 A1 A0 ;Burst Length ( 1, 2, 4, 8 & full page )
};
end
default:begin
COMMAND_INIT <= COMMAND_NOP;
INIT_A_ADDR <= 12'd0 ;
INIT_BANK_ADDR <= 2'b00 ;
end
endcase
end
end
endmodule
刷新:
module SDRAM_ARF #(
)(
input wire Sys_clk,
input wire Rst_n ,
//SDRAM
input wire INIT_DONE ,
output reg [3:0] COMMAND_REF ,
output reg [11:0] ARF_A_ADDR ,
output reg [ 1:0] ARF_BANK_ADDR ,
output reg REF_DONE ,
output reg ARF_req ,
input wire ARF_access
);
`include "D:/three_verilog/SDRAM/SDRAM_init/rtl/sdram_param.h"
localparam TIME_ARF_BEGIN = 1'b1 ;
// localparam TIME_PRE_to_ARF = 1'b1 + TIME_PRE_CHARGE;
// localparam TIME_ARF_to_done = 1'b1 + TIME_PRE_CHARGE + TIME_Auto_refresh;
localparam TIME_ARF_to_done = 'd9;
reg [9:0] ARF_CNT ;
reg [3:0] COMMAND_CNT;
//ARF_CNT
always @(posedge Sys_clk or negedge Rst_n) begin
if(Rst_n == 'd0) begin
ARF_req <= 'd0;
end else if(ARF_access == 1'b1) begin
ARF_req <= 1'b0;
end else if(ARF_CNT == ARF_PERIOD) begin
ARF_req <= 1'b1;
end
end
always@(posedge Sys_clk or negedge Rst_n) begin
if(Rst_n == 'd0) begin
ARF_CNT <= 'd0;
end else if(INIT_DONE == 1'b1) begin
ARF_CNT <= 'd1;
end else if(ARF_CNT == ARF_PERIOD) begin
ARF_CNT <= 'd1;
end else if(ARF_CNT > 'd0) begin
ARF_CNT <= ARF_CNT + 1'd1;
end else begin
ARF_CNT <= ARF_CNT;
end
end
always@(posedge Sys_clk or negedge Rst_n) begin
if(Rst_n == 'd0) begin
REF_DONE <= 1'b0;
end else if(COMMAND_CNT == TIME_ARF_to_done) begin
REF_DONE <= 1'b1;
end else begin
REF_DONE <= 1'b0;
end
end
//COMMAND_CNT
always@(posedge Sys_clk or negedge Rst_n) begin
if(Rst_n == 'd0) begin
COMMAND_CNT <= 'd0;
end else if(ARF_access == 1'b1) begin
COMMAND_CNT <= 'd1;
end else if(COMMAND_CNT == TIME_ARF_to_done) begin
COMMAND_CNT <= 'd0;
end else if(COMMAND_CNT > 'd0) begin
COMMAND_CNT <= COMMAND_CNT + 1'b1;
end else begin
COMMAND_CNT <= COMMAND_CNT;
end
end
//COMMAND
always@(posedge Sys_clk or negedge Rst_n) begin
if(Rst_n == 'd0) begin
COMMAND_REF <= COMMAND_NOP;
ARF_A_ADDR <= 12'd0 ;
ARF_BANK_ADDR <= 2'b00 ;
end else if(COMMAND_CNT == TIME_ARF_BEGIN) begin
COMMAND_REF <= COMMAND_ARF;
end else begin
COMMAND_REF <= COMMAND_NOP;
ARF_A_ADDR <= 12'd0 ;
ARF_BANK_ADDR <= 2'b00 ;
end
end
//COMMAND other SDRAM
// always@(posedge Sys_clk or negedge Rst_n) begin
// if(Rst_n == 'd0) begin
// COMMAND_REF <= COMMAND_NOP;
// ARF_A_ADDR <= 12'd0 ;
// ARF_BANK_ADDR <= 2'b00 ;
// end else begin
// case (COMMAND_CNT)
// TIME_ARF_BEGIN: begin
// COMMAND_REF <= COMMAND_PRE;
// ARF_A_ADDR[10] <= 1'b1 ;
// end
// TIME_PRE_to_ARF: begin
// COMMAND_REF <= COMMAND_ARF;
// end
// default: begin
// COMMAND_REF <= COMMAND_NOP;
// ARF_A_ADDR <= 12'd0 ;
// ARF_BANK_ADDR <= 2'b00 ;
// end
// endcase
// end
// end
endmodule
写入:
1.注意每一行结束以后要重新激活。
2.写完了就不要继续req了。
//SDRAM SIZE = 8192X512X16
//8192ROWS 512COLS 16BITS
module SDRAM_WR #(
parameter SDRAM_COLS_MAX = 128,
parameter IMAGE_NEED_ROW = 300, //300 = 640*480*8/16*512
parameter TIME_PRE_CHARGE_long = 8
)(
input wire Sys_clk,
input wire Rst_n ,
//FIFO
input wire FIFO_WR_EN ,//8bits
input wire [ 7:0] FIFO_WR_data ,
//SDRAM
input wire INIT_DONE ,
output reg [ 3:0] COMMAND_WR ,
output reg [11:0] WR_A_ADDR ,
output reg [ 1:0] WR_BANK_ADDR ,
output wire WR_data_done ,
output reg WR_req ,
input wire ARF_req ,
output reg Break_WR_to_ARF,
input wire WR_access ,
output wire [15:0] WRITE_SDRAM_DQ
);
`include "D:/three_verilog/SDRAM/SDRAM_init/rtl/sdram_param.h"
localparam STATE_IDLE = 5'b0_0001;
localparam STATE_WR_wait = 5'b0_0010;
localparam STATE_ACT = 5'b0_0100;
localparam STATE_WR_NOW = 5'b0_1000;
localparam STATE_Precharge = 5'b1_0000;
reg [ 4:0] STATE ;
reg [ 1:0] CNT_ACT ;
reg [ 9:0] CNT_SDRAM_COLS;
reg [12:0] CNT_SDRAM_ROWS;
wire ROWS_END_Flag ;
reg [ 1:0] CNT_Brust ;
reg [ 3:0] CNT_Precharge ;
reg Done_image ;
//FIFO
wire FIFO_FULL ;
wire FIFO_EMPTY ;
wire [ 9:0] FIFO_RD_cnt ;
reg FIFO_RD_EN ;
wire [15:0] FIFO_RD_DATA ;
assign WRITE_SDRAM_DQ = FIFO_RD_DATA;
//FIFO_RD_EN
always @(posedge Sys_clk or negedge Rst_n) begin
if(Rst_n == 'd0) begin
FIFO_RD_EN <= 'd0;
end else if(STATE == STATE_WR_NOW) begin
FIFO_RD_EN <= 1'b1;
end else begin
FIFO_RD_EN <= 'd0;
end
end
//WR_req
always @(posedge Sys_clk or negedge Rst_n) begin
if(Rst_n == 'd0) begin
WR_req <= 'd0;
end else if(FIFO_RD_cnt >= 512 && STATE == STATE_WR_wait && Done_image == 'd0) begin
WR_req <= 1'b1;
end else if(WR_access == 1'b1 && STATE == STATE_WR_wait) begin
WR_req <= 'd0;
// end else if(Break_WR_to_ARF == 1'b1 && Done_image == 'd0) begin //通过uart写入FIFO的数据速度太慢了,SDRAM的写入速度非常快,这行会导致读出大量的重复数据写入SDRAM
// WR_req <= 1'b1;
end else if(Done_image == 1'b1) begin
WR_req <= 'd0;
end else begin
WR_req <= WR_req;
end
end
//Done_image
// always @(posedge Sys_clk or negedge Rst_n) begin
// if(Rst_n == 'd0) begin
// Done_image <= 'd0;
// end else if(STATE == STATE_WR_NOW
// && (CNT_SDRAM_ROWS == IMAGE_NEED_ROW - 1'b1 )
// && (CNT_SDRAM_COLS == SDRAM_COLS_MAX - 1'b1)
// && (CNT_Brust == INIT_Burst_length -1'b1)) begin
// Done_image <= 1'b1;
// end else if(STATE == STATE_Precharge && CNT_Precharge == TIME_PRE_CHARGE_long) begin
// Done_image <= 'd0;
// end else begin
// Done_image <= Done_image;
// end
// end
always @(posedge Sys_clk or negedge Rst_n) begin
if(Rst_n == 'd0) begin
Done_image <= 'd0;
end else if(STATE == STATE_WR_NOW
&& (CNT_SDRAM_ROWS == IMAGE_NEED_ROW - 1'b1 )
&& (CNT_SDRAM_COLS == SDRAM_COLS_MAX - 1'b1)
&& (CNT_Brust == INIT_Burst_length -1'b1)) begin
Done_image <= 1'b1;
end else begin
Done_image <= Done_image;
end
end
//WR_data_done
assign WR_data_done = (STATE == STATE_Precharge
&& CNT_Precharge == TIME_PRE_CHARGE_long
&& Done_image == 1'b1);
// always @(posedge Sys_clk or negedge Rst_n) begin
// if(Rst_n == 'd0) begin
// WR_data_done <= 'd0;
// end else if(STATE == STATE_Precharge
// && CNT_Precharge == TIME_PRE_CHARGE_long
// && Done_image == 1'b1) begin
// WR_data_done <= 1'b1;
// end else begin
// WR_data_done <= 'd0;
// end
// end
//Break_WR_to_ARF
always @(posedge Sys_clk or negedge Rst_n) begin
if(Rst_n == 'd0) begin
Break_WR_to_ARF <= 'd0;
end else if(STATE == STATE_Precharge
&& CNT_Precharge == TIME_PRE_CHARGE_long
&& Done_image == 1'b0) begin
Break_WR_to_ARF <= 'd1;
end else begin
Break_WR_to_ARF <= 'd0;
end
end
//CNT_ACT
always @(posedge Sys_clk or negedge Rst_n) begin
if(Rst_n == 'd0) begin
CNT_ACT <= 'd0;
end else if(STATE == STATE_ACT) begin
if(CNT_ACT == TIME_RCD) begin
CNT_ACT <= 'd0;
end else begin
CNT_ACT <= CNT_ACT + 1'b1;
end
end else begin
CNT_ACT <= 'd0;
end
end
//CNT_Brust
always @(posedge Sys_clk or negedge Rst_n) begin
if(Rst_n == 'd0) begin
CNT_Brust <= 'd0;
end else if(STATE == STATE_WR_NOW) begin
if(CNT_Brust == INIT_Burst_length -1'b1) begin
CNT_Brust <= 'd0;
end else begin
CNT_Brust <= CNT_Brust + 1'b1;
end
end else begin
CNT_Brust <= 'd0;
end
end
//CNT_SDRAM_ROWS
always @(posedge Sys_clk or negedge Rst_n) begin
if(Rst_n == 'd0) begin
CNT_SDRAM_ROWS <= 'd0;
end else if(STATE == STATE_WR_NOW) begin
if (CNT_SDRAM_ROWS == IMAGE_NEED_ROW - 1'b1
&& (CNT_SDRAM_COLS == SDRAM_COLS_MAX - 1'b1)
&& (CNT_Brust == INIT_Burst_length -1'b1)) begin
CNT_SDRAM_ROWS <= 'd0;
end else if((CNT_SDRAM_COLS == SDRAM_COLS_MAX - 1'b1)
&& (CNT_Brust == INIT_Burst_length -1'b1)) begin
CNT_SDRAM_ROWS <= CNT_SDRAM_ROWS + 1'b1;
end else begin
CNT_SDRAM_ROWS <= CNT_SDRAM_ROWS;
end
end else begin
CNT_SDRAM_ROWS <= CNT_SDRAM_ROWS;
end
end
//CNT_SDRAM_COLS
always @(posedge Sys_clk or negedge Rst_n) begin
if(Rst_n == 'd0) begin
CNT_SDRAM_COLS <= 'd0;
end else if(STATE == STATE_WR_NOW) begin
if((CNT_SDRAM_COLS == SDRAM_COLS_MAX - 1'b1)
&& (CNT_Brust == INIT_Burst_length -1'b1)) begin
CNT_SDRAM_COLS <= 'd0;
end else if(CNT_Brust == INIT_Burst_length -1'b1) begin
CNT_SDRAM_COLS <= CNT_SDRAM_COLS + 1'b1;
end else begin
CNT_SDRAM_COLS <= CNT_SDRAM_COLS;
end
end else begin
CNT_SDRAM_COLS <= CNT_SDRAM_COLS;
end
end
assign ROWS_END_Flag = (STATE == STATE_WR_NOW) && (CNT_SDRAM_COLS == SDRAM_COLS_MAX - 1'b1) && (CNT_Brust == INIT_Burst_length -1'b1);
//CNT_Precharge
always @(posedge Sys_clk or negedge Rst_n) begin
if(Rst_n == 'd0) begin
CNT_Precharge <= 'd0;
end else if(STATE == STATE_Precharge && CNT_Precharge == TIME_PRE_CHARGE_long) begin
CNT_Precharge <= 'd0;
end else if(STATE == STATE_Precharge) begin
CNT_Precharge <= CNT_Precharge + 1'b1;
end else begin
CNT_Precharge <= CNT_Precharge;
end
end
//COMMAND
always @(posedge Sys_clk or negedge Rst_n) begin
if(Rst_n == 'd0) begin
COMMAND_WR <= COMMAND_NOP;
WR_A_ADDR <= 12'd0 ;
WR_BANK_ADDR <= 2'b00 ;
end else if(STATE == STATE_WR_wait && WR_access == 1'b1) begin
COMMAND_WR <= COMMAND_ACT;
WR_A_ADDR <= CNT_SDRAM_ROWS;//row_addr
WR_BANK_ADDR <= 2'b00 ;
end else if(STATE == STATE_WR_NOW && CNT_Brust == 'd0) begin
COMMAND_WR <= COMMAND_WRITE;
WR_A_ADDR <= CNT_SDRAM_COLS<<2'd2;
WR_BANK_ADDR <= 2'b00 ;
end else if(STATE == STATE_Precharge && CNT_Precharge == 'd0) begin
COMMAND_WR <= COMMAND_PRE;
WR_A_ADDR[10]<= 1'b1 ;
WR_BANK_ADDR <= 2'b00 ;
end else begin
COMMAND_WR <= COMMAND_NOP;
WR_A_ADDR <= 12'd0 ;
WR_BANK_ADDR <= 2'b00 ;
end
end
//STATE
always @(posedge Sys_clk or negedge Rst_n) begin
if(Rst_n == 'd0) begin
STATE <= STATE_IDLE;
end else begin
case (STATE)
STATE_IDLE: begin
if(INIT_DONE == 1'b1) begin
STATE <= STATE_WR_wait;
end else begin
STATE <= STATE_IDLE;
end
end
STATE_WR_wait: begin
if(WR_access == 1'b1) begin
STATE <= STATE_ACT;
end else begin
STATE <= STATE_WR_wait;
end
end
STATE_ACT: begin
if(ARF_req == 1'b1 && CNT_ACT == TIME_RCD) begin
STATE <= STATE_Precharge;
end else if(CNT_ACT == TIME_RCD) begin
STATE <= STATE_WR_NOW;
end else begin
STATE <= STATE_ACT;
end
end
STATE_WR_NOW:begin
if(ARF_req == 1'b1 && CNT_Brust == INIT_Burst_length - 1'b1) begin
STATE <= STATE_Precharge;
end else if(ROWS_END_Flag == 1'b1) begin
STATE <= STATE_Precharge;
end else if(Done_image == 1'b1) begin
STATE <= STATE_Precharge;
end else begin
STATE <= STATE_WR_NOW;
end
end
STATE_Precharge: begin
if(CNT_Precharge == TIME_PRE_CHARGE_long) begin
STATE <= STATE_WR_wait;
end else begin
STATE <= STATE_Precharge;
end
end
default: begin
STATE <= STATE_IDLE;
end
endcase
end
end
/*------------------------------------------------------------------------*/
AS_FIFO_w2048x8_r1024x16 INST0_AS_FIFO_w2048x8_r1024x16 (
.wr_clk ( Sys_clk ), // input wr_clk
.rd_clk ( Sys_clk ), // input rd_clk
.din ( FIFO_WR_data ), // input [7 : 0] din
.wr_en ( FIFO_WR_EN ), // input wr_en
.rd_en ( FIFO_RD_EN ), // input rd_en
.dout ( FIFO_RD_DATA ), // output [15 : 0] dout
.full ( FIFO_FULL ), // output full
.empty ( FIFO_EMPTY ), // output empty
.rd_data_count( FIFO_RD_cnt ) // output [9 : 0] rd_data_count
/*------------------------------------------------------------------------*/
);
endmodule