• 再战SDRAM与资料整理。


    串口传图写进SDRAM再读出

            为啥这样干:节省BRAM资源:X

                                 学习SRAM控制器写法:√

            实际上确实也不太够用就是了,A7100T的bram也只有1M多,存个一行数据得了。

    实现思路:

            1.串口发送图像数据进入rx模块,rx模块发给SDRAM写模块;

            细节:考虑到图像格式不一,本次使用的SDRAM的一个地址放16Bit数据,你需要额外准备一个FIFO来按SDRAM行的大小来存储,每发完一行数据把这部分写入SDRAM,比如SDRAM一行512个元素你就得设置一个读取位数和宽度分别为为16x1024的fifo,写入数据则是串口的8x2048。

            2.发完以后通知读模块,同样需要fifo,这次是写入位数和宽度分别为为16x1024的fifo,读取多少得看图像是几位的,读取完一行数据以后通知VGA模块可以输出图像,VGA读取图像的速率不算快,所以直接读就行了。

             这个显示分辨率只需要25MHZ左右,只需要约定FIFO内的数据小于一个数值,例如小于SDRAM的一行数据的时候就从SDRAM读取数据填补,便可以满足需求,因为SDRAM自身每次切换行都需要重新激活,所以每次读也就读一行数据,并不会导致FIFO的溢出。     

            3.这个项目最需要注意的就是约束好FIFO,不要出现读空了还在读,写满了还在写,唯一一次空信号应该出现在发送完一张图片到下一张图片的间隔。

    SDRAM控制器的编写方法

    总之只要阅读操作手册,按照时序来,完全不难!

            器件记录: 

    小梅哥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:(tRRC)

    一次自刷新需要的时间

    tREF

    Refresh Period,表示“刷新周期”。它指内存模块的刷新周期。

    tRAS

    激活行到预充电需要的时间

    tRCD:

    激活到读或写命令的延迟(激活行到列操作的时间),也是激活命令到读写操作的等待时间

    CL

    列选通潜伏期(读取指令到数据端口复现的时间)

    WL

    写入指令到输入数据端口的时间

    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却不需要,仅需要发送刷新指令然后等待刷新完成即可。

            后面的读写时序其实根据不同的器件来看还是有很多不一样的步骤的,请按照自己的芯片的操作手册来,应该不会有问题。

            比较重要的是仲裁器的写法,根据划定好的优先级来约束就好了。

            可参考:

    参数配置:

    1. //COMMAND = {CS_N,RAS_N,CAS_N,WE_N};
    2. parameter COMMAND_MRS = 4'b0000 ;
    3. parameter COMMAND_ARF = 4'b0001 ;
    4. parameter COMMAND_PRE = 4'b0010 ;
    5. parameter COMMAND_ACT = 4'b0011 ;
    6. parameter COMMAND_WRITE = 4'b0100 ;
    7. parameter COMMAND_READ = 4'b0101 ;
    8. parameter COMMAND_interrupt = 4'b0110 ;
    9. parameter COMMAND_NOP = 4'b0111 ;
    10. //time_wait
    11. parameter TIME_WAIT_ABOVE_100US = 10000 ;//wait_time > 100us set:200us Power up wait time
    12. parameter TIME_PRE_CHARGE = 2 ;//tRP > 18ns set:40ns; Precharge cost time
    13. parameter TIME_Auto_refresh = 5 ;//tRFC=TRRC > 60ns set:100ns ARF cost time
    14. parameter TIME_MRS_done_wait = 2 ;//During 2CLK following this command, the SDRAM cannot accept any other commands.
    15. //MRS_OPCODE
    16. parameter INIT_OPMODE_Brust_Mode = 1'b0 ;//A9
    17. parameter INIT_OPMODE_STANDRD = 2'b00 ;//A8 A7
    18. parameter INIT_CAS_Latency = 3 ;//A6 A5 A4 ;CAS Latency ( 2 & 3 )
    19. parameter INIT_Burst_type = 1'b0 ;//A3 0:Sequential 1:Interleave
    20. parameter INIT_Burst_length = 4 ;//A2 A1 A0 ;Burst Length ( 1, 2, 4, 8 & full page )
    21. parameter INIT_OPMODE_Brust_Length = (INIT_Burst_length == 1)?(3'b000):
    22. (INIT_Burst_length == 2)?(3'b001):
    23. (INIT_Burst_length == 4)?(3'b010):
    24. (INIT_Burst_length == 8)?(3'b011):(3'b111);//( 1, 2, 4, 8 & full page )
    25. parameter INIT_OPMODE_CL = (INIT_CAS_Latency == 2)?(3'b010):(3'b011);//A6 A5 A4 ;
    26. //auto refresh
    27. parameter ARF_PERIOD = 750;// ARF_period = Row_nums/64ms 64ms = 64_000us = 64_000_000ns = 3_200_000 cycles (1 ARF/782 cycles)
    28. //ACT
    29. parameter TIME_RCD = 3;//tRCD > 20ns act RAS to CAS delay

    主控制器和仲裁: 

            1.状态机的状态位宽要对齐。

            2.不同信号的优先级要提前约定好。

    1. module SDRAM_CTRL_TOP #(
    2. parameter SDRAM_DATA_WIDTH = 16,
    3. parameter SDRAM_BANK_WIDTH = 2 ,
    4. parameter SDRAM_ADDR_WIDTH = 12
    5. )(
    6. input wire Sys_clk,
    7. input wire Rst_n ,
    8. //PLL
    9. input wire VGA_CLOCK ,//25MHZ = 800X525X60
    10. //SDRAM
    11. //COMMAND
    12. output wire SDRAM_CS_N ,
    13. output wire SDRAM_RAS_N ,
    14. output wire SDRAM_CAS_N ,
    15. output wire SDRAM_WE_N ,
    16. output wire SDRAM_CKE ,
    17. output wire [1:0] SDRAM_DQM ,
    18. output wire SDRAM_CLK ,
    19. output reg [SDRAM_ADDR_WIDTH-1:0] SDRAM_A_ADDR ,
    20. output reg [SDRAM_BANK_WIDTH-1:0] SDRAM_BANK_ADDR ,
    21. //WR_FIFO
    22. input wire FIFO_WR_EN ,
    23. input wire [7:0] FIFO_WR_data ,
    24. //DATA
    25. inout [SDRAM_DATA_WIDTH-1:0] SDRAM_DQ ,
    26. //VGA
    27. output wire [2:0] red_sign ,
    28. output wire [2:0] grenn_sign ,
    29. output wire [1:0] blue_sign ,
    30. output wire H_Sync_sign ,
    31. output wire V_Sync_sign
    32. );
    33. `include "D:/three_verilog/SDRAM/SDRAM_init/rtl/sdram_param.h"
    34. localparam STATE_IDLE = 6'b00_0001;
    35. localparam STATE_INIT = 6'b00_0010;
    36. localparam STATE_ARB = 6'b00_0100;
    37. localparam STATE_ARF = 6'b00_1000;
    38. localparam STATE_RD = 6'b01_0000;
    39. localparam STATE_WE = 6'b10_0000;
    40. //Main
    41. reg [3:0] SDRAM_COMMAND_SEND;
    42. reg [5:0] STATE ;
    43. wire WR_avai ;
    44. wire [SDRAM_DATA_WIDTH-1:0] WR_SDRAM_DQ ;
    45. reg [SDRAM_DATA_WIDTH-1:0] READ_SDRAM_DQ ;
    46. //init
    47. wire INIT_DONE ;
    48. wire [3:0] COMMAND_INIT ;
    49. wire [SDRAM_ADDR_WIDTH-1:0] INIT_A_ADDR ;
    50. wire [SDRAM_BANK_WIDTH-1:0] INIT_BANK_ADDR ;
    51. //ARF
    52. wire ARF_access ;
    53. wire [3:0] COMMAND_REF ;
    54. wire [SDRAM_ADDR_WIDTH-1:0] ARF_A_ADDR ;
    55. wire [SDRAM_BANK_WIDTH-1:0] ARF_BANK_ADDR ;
    56. wire REF_DONE ;
    57. wire ARF_req ;
    58. //WR
    59. wire WR_req ;
    60. wire WR_access ;
    61. wire [3:0] COMMAND_RD ;
    62. wire [SDRAM_ADDR_WIDTH-1:0] RD_A_ADDR ;
    63. wire [SDRAM_BANK_WIDTH-1:0] RD_BANK_ADDR ;
    64. wire WR_data_done ;
    65. //RD
    66. wire RD_req ;
    67. wire RD_access ;
    68. wire RD_DATA_DONE ;
    69. wire [3:0] COMMAND_WR ;
    70. wire [SDRAM_ADDR_WIDTH-1:0] WR_A_ADDR ;
    71. wire [SDRAM_BANK_WIDTH-1:0] WR_BANK_ADDR ;
    72. //VGA
    73. wire VGA_START ;
    74. wire VGA_FIFO_RD_EN ;
    75. wire [7:0] VGA_FIFO_RD_DATA ;
    76. wire [9:0] H_addr ;
    77. wire [9:0] V_addr ;
    78. //break
    79. wire Break_WR_to_ARF ;
    80. wire Break_RD_other ;
    81. //DQ
    82. assign WR_avai = (STATE == STATE_WE)?1'b1:1'b0;
    83. always@(posedge Sys_clk) begin
    84. READ_SDRAM_DQ <= SDRAM_DQ;
    85. end
    86. assign SDRAM_DQ = (WR_avai == 1'b1)?WR_SDRAM_DQ :16'dz;
    87. assign SDRAM_DQM = 2'b00 ;
    88. assign SDRAM_CKE = 1'b1 ;
    89. assign SDRAM_CLK = Sys_clk;
    90. //COMMAND
    91. assign {SDRAM_CS_N,
    92. SDRAM_RAS_N,
    93. SDRAM_CAS_N,
    94. SDRAM_WE_N } = SDRAM_COMMAND_SEND;
    95. always@(*) begin
    96. if(STATE == STATE_INIT) begin
    97. SDRAM_COMMAND_SEND <= COMMAND_INIT ;
    98. SDRAM_A_ADDR <= INIT_A_ADDR ;
    99. SDRAM_BANK_ADDR <= INIT_BANK_ADDR;
    100. end else if(STATE == STATE_ARF) begin
    101. SDRAM_COMMAND_SEND <= COMMAND_REF ;
    102. SDRAM_A_ADDR <= ARF_A_ADDR ;
    103. SDRAM_BANK_ADDR <= ARF_BANK_ADDR ;
    104. end else if(STATE == STATE_WE) begin
    105. SDRAM_COMMAND_SEND <= COMMAND_WR ;
    106. SDRAM_A_ADDR <= WR_A_ADDR ;
    107. SDRAM_BANK_ADDR <= WR_BANK_ADDR ;
    108. end else if(STATE == STATE_RD) begin
    109. SDRAM_COMMAND_SEND <= COMMAND_RD ;
    110. SDRAM_A_ADDR <= RD_A_ADDR ;
    111. SDRAM_BANK_ADDR <= RD_BANK_ADDR ;
    112. end else begin
    113. SDRAM_COMMAND_SEND <= COMMAND_NOP ;
    114. SDRAM_A_ADDR <= 'd0 ;
    115. SDRAM_BANK_ADDR <= 'd0 ;
    116. end
    117. end
    118. //access
    119. assign ARF_access = (STATE == STATE_ARB) && (ARF_req == 1'b1);
    120. assign WR_access = (STATE == STATE_ARB) && (WR_req == 1'b1)
    121. && (ARF_req == 1'b0);
    122. assign RD_access = (STATE == STATE_ARB) && (RD_req == 1'b1)
    123. && (WR_req == 1'b0 ) && (ARF_req == 1'b0);
    124. //-------------------STATE MAIN-----------------------//
    125. always@(posedge Sys_clk or negedge Rst_n) begin
    126. if(Rst_n == 'd0) begin
    127. STATE <= STATE_IDLE;
    128. end else begin
    129. case (STATE) //ARG > WR > RD
    130. STATE_IDLE: begin
    131. STATE <= STATE_INIT;
    132. end
    133. STATE_INIT: begin
    134. if(INIT_DONE == 'd1) begin
    135. STATE <= STATE_ARB;
    136. end else begin
    137. STATE <= STATE_INIT;
    138. end
    139. end
    140. STATE_ARB: begin
    141. if(ARF_req == 1'b1) begin
    142. STATE <= STATE_ARF;
    143. end else if(WR_req == 1'b1 && ARF_req == 1'b0) begin
    144. STATE <= STATE_WE;
    145. end else if(RD_req == 1'b1 && WR_req == 1'b0 && ARF_req == 1'b0) begin
    146. STATE <= STATE_RD;
    147. end else begin
    148. STATE <= STATE_ARB;
    149. end
    150. end
    151. STATE_ARF: begin
    152. if(REF_DONE == 1'b1) begin
    153. STATE <= STATE_ARB;
    154. end else begin
    155. STATE <= STATE_ARF;
    156. end
    157. end
    158. STATE_WE: begin
    159. if(Break_WR_to_ARF == 1'b1) begin
    160. STATE <= STATE_ARB;
    161. end else if(WR_data_done == 1'b1) begin
    162. STATE <= STATE_ARB;
    163. end else begin
    164. STATE <= STATE_WE;
    165. end
    166. end
    167. STATE_RD: begin
    168. if(RD_DATA_DONE == 1'b1) begin
    169. STATE <= STATE_ARB;
    170. end else if(Break_RD_other == 1'b1) begin
    171. STATE <= STATE_ARB;
    172. end else begin
    173. STATE <= STATE_RD;
    174. end
    175. end
    176. default: begin
    177. STATE <= STATE_IDLE;
    178. end
    179. endcase
    180. end
    181. end
    182. //-------------------STATE END------------------------//
    183. /*-------------------instance begin---------------------------*/
    184. /*-------------------instance end-----------------------------*/
    185. endmodule

    初始化:

            1.初始化只需要进行一次。

            2.不同SDRAM的初始化步骤大同小异。

    1. module SDRAM_INIT(
    2. input wire Sys_clk ,
    3. input wire Rst_n ,
    4. output reg [ 3:0] COMMAND_INIT ,//COMMAND = {CS_N,RAS_N,CAS_N,WE_N}
    5. output reg [11:0] INIT_A_ADDR ,
    6. output reg [ 1:0] INIT_BANK_ADDR,
    7. output reg INIT_DONE
    8. );
    9. `include "D:/three_verilog/SDRAM/SDRAM_init/rtl/sdram_param.h"
    10. localparam TIME_TO_PRE = TIME_WAIT_ABOVE_100US;
    11. localparam TIME_TO_ARF = TIME_WAIT_ABOVE_100US + TIME_PRE_CHARGE;
    12. localparam TIME_TO_ARF_2 = TIME_WAIT_ABOVE_100US + TIME_PRE_CHARGE
    13. + TIME_Auto_refresh;
    14. localparam TIME_TO_MRS = TIME_WAIT_ABOVE_100US + TIME_PRE_CHARGE
    15. + TIME_Auto_refresh + TIME_Auto_refresh;
    16. localparam INIT_END = TIME_TO_MRS + TIME_MRS_done_wait ;
    17. reg [13:0] INIT_CNT ;
    18. reg INIT_DONE_NOW;
    19. always@(posedge Sys_clk or negedge Rst_n) begin
    20. if(Rst_n == 'd0) begin
    21. INIT_DONE <= 'd0;
    22. end else if(INIT_CNT == INIT_END) begin
    23. INIT_DONE <= 'd1;
    24. end else begin
    25. INIT_DONE <= 'd0;
    26. end
    27. end
    28. always@(posedge Sys_clk or negedge Rst_n) begin
    29. if(Rst_n == 'd0) begin
    30. INIT_DONE_NOW <= 1'b0;
    31. end else if(INIT_CNT == INIT_END) begin
    32. INIT_DONE_NOW <= 1'b1;
    33. end else begin
    34. INIT_DONE_NOW <= INIT_DONE_NOW;
    35. end
    36. end
    37. always @(posedge Sys_clk or negedge Rst_n) begin
    38. if(Rst_n == 'd0) begin
    39. INIT_CNT <= 'd0;
    40. end else if(INIT_DONE_NOW == 1'b0) begin
    41. if(INIT_CNT == INIT_END) begin
    42. INIT_CNT <= 'd0;
    43. end else begin
    44. INIT_CNT <= INIT_CNT + 1'b1;
    45. end
    46. end else begin
    47. INIT_CNT <= 'd0;
    48. end
    49. end
    50. always @(posedge Sys_clk or negedge Rst_n) begin
    51. if(Rst_n == 'd0) begin
    52. COMMAND_INIT <= COMMAND_NOP;
    53. INIT_A_ADDR <= 12'd0 ;
    54. INIT_BANK_ADDR <= 2'b00 ;
    55. end else begin
    56. case (INIT_CNT)
    57. TIME_TO_PRE: begin
    58. COMMAND_INIT <= COMMAND_PRE;
    59. INIT_A_ADDR[10] <= 1'b1;
    60. end
    61. TIME_TO_ARF: begin
    62. COMMAND_INIT <= COMMAND_ARF;
    63. end
    64. TIME_TO_ARF_2: begin
    65. COMMAND_INIT <= COMMAND_ARF;
    66. end
    67. TIME_TO_MRS: begin
    68. COMMAND_INIT <= COMMAND_MRS;
    69. INIT_A_ADDR <= {
    70. 2'b00 ,//A11 A10
    71. INIT_OPMODE_Brust_Mode ,//A9
    72. INIT_OPMODE_STANDRD ,//A8 A7
    73. INIT_OPMODE_CL ,//A6 A5 A4 ;CAS Latency ( 2 & 3 )
    74. INIT_Burst_type ,//A3 0:Sequential 1:Interleave
    75. INIT_OPMODE_Brust_Length //A2 A1 A0 ;Burst Length ( 1, 2, 4, 8 & full page )
    76. };
    77. end
    78. default:begin
    79. COMMAND_INIT <= COMMAND_NOP;
    80. INIT_A_ADDR <= 12'd0 ;
    81. INIT_BANK_ADDR <= 2'b00 ;
    82. end
    83. endcase
    84. end
    85. end
    86. endmodule

    刷新: 

            64ms刷新/row_num 此处4096行,按理说应该是780个cycle一次。

            我改成了750cycle一次,留点余量。

    1. module SDRAM_ARF #(
    2. )(
    3. input wire Sys_clk,
    4. input wire Rst_n ,
    5. //SDRAM
    6. input wire INIT_DONE ,
    7. output reg [3:0] COMMAND_REF ,
    8. output reg [11:0] ARF_A_ADDR ,
    9. output reg [ 1:0] ARF_BANK_ADDR ,
    10. output reg REF_DONE ,
    11. output reg ARF_req ,
    12. input wire ARF_access
    13. );
    14. `include "D:/three_verilog/SDRAM/SDRAM_init/rtl/sdram_param.h"
    15. localparam TIME_ARF_BEGIN = 1'b1 ;
    16. // localparam TIME_PRE_to_ARF = 1'b1 + TIME_PRE_CHARGE;
    17. // localparam TIME_ARF_to_done = 1'b1 + TIME_PRE_CHARGE + TIME_Auto_refresh;
    18. localparam TIME_ARF_to_done = 'd9;
    19. reg [9:0] ARF_CNT ;
    20. reg [3:0] COMMAND_CNT;
    21. //ARF_CNT
    22. always @(posedge Sys_clk or negedge Rst_n) begin
    23. if(Rst_n == 'd0) begin
    24. ARF_req <= 'd0;
    25. end else if(ARF_access == 1'b1) begin
    26. ARF_req <= 1'b0;
    27. end else if(ARF_CNT == ARF_PERIOD) begin
    28. ARF_req <= 1'b1;
    29. end
    30. end
    31. always@(posedge Sys_clk or negedge Rst_n) begin
    32. if(Rst_n == 'd0) begin
    33. ARF_CNT <= 'd0;
    34. end else if(INIT_DONE == 1'b1) begin
    35. ARF_CNT <= 'd1;
    36. end else if(ARF_CNT == ARF_PERIOD) begin
    37. ARF_CNT <= 'd1;
    38. end else if(ARF_CNT > 'd0) begin
    39. ARF_CNT <= ARF_CNT + 1'd1;
    40. end else begin
    41. ARF_CNT <= ARF_CNT;
    42. end
    43. end
    44. always@(posedge Sys_clk or negedge Rst_n) begin
    45. if(Rst_n == 'd0) begin
    46. REF_DONE <= 1'b0;
    47. end else if(COMMAND_CNT == TIME_ARF_to_done) begin
    48. REF_DONE <= 1'b1;
    49. end else begin
    50. REF_DONE <= 1'b0;
    51. end
    52. end
    53. //COMMAND_CNT
    54. always@(posedge Sys_clk or negedge Rst_n) begin
    55. if(Rst_n == 'd0) begin
    56. COMMAND_CNT <= 'd0;
    57. end else if(ARF_access == 1'b1) begin
    58. COMMAND_CNT <= 'd1;
    59. end else if(COMMAND_CNT == TIME_ARF_to_done) begin
    60. COMMAND_CNT <= 'd0;
    61. end else if(COMMAND_CNT > 'd0) begin
    62. COMMAND_CNT <= COMMAND_CNT + 1'b1;
    63. end else begin
    64. COMMAND_CNT <= COMMAND_CNT;
    65. end
    66. end
    67. //COMMAND
    68. always@(posedge Sys_clk or negedge Rst_n) begin
    69. if(Rst_n == 'd0) begin
    70. COMMAND_REF <= COMMAND_NOP;
    71. ARF_A_ADDR <= 12'd0 ;
    72. ARF_BANK_ADDR <= 2'b00 ;
    73. end else if(COMMAND_CNT == TIME_ARF_BEGIN) begin
    74. COMMAND_REF <= COMMAND_ARF;
    75. end else begin
    76. COMMAND_REF <= COMMAND_NOP;
    77. ARF_A_ADDR <= 12'd0 ;
    78. ARF_BANK_ADDR <= 2'b00 ;
    79. end
    80. end
    81. endmodule

    写入:

            1.注意每一行结束以后要重新激活。

            2.写完了就不要继续req了。

            此处写请求产生条件:

    1. //WR_req
    2. always @(posedge Sys_clk or negedge Rst_n) begin
    3. if(Rst_n == 'd0) begin
    4. WR_req <= 'd0;
    5. end else if(FIFO_RD_cnt >= 512 && STATE == STATE_WR_wait) begin
    6. WR_req <= 1'b1;
    7. end else if(Break_WR_to_ARF
    8. && CNT_SDRAM_ROWS == IMAGE_NEED_ROW - 1'b1
    9. && ((FIFO_RD_cnt >>2'd2) >= (SDRAM_COLS_MAX - CNT_SDRAM_COLS))) begin
    10. WR_req <= 1'd1;
    11. end else if(Done_image == 1'b1 || WR_access == 1'b1 || STATE != STATE_WR_wait) begin
    12. WR_req <= 'd0;
    13. end else begin
    14. WR_req <= WR_req;
    15. end
    16. end

            是由于我发现在最后一行的时候如果遭遇刷新时刻, 则会导致读不完的情况,但是直接使用打断标注来拉高读请求,又会出现读到FIFO为空的情况,设置某个具体的值的话,原定这个模块是通过串口来发送的,即使是115200速率,在SDRAM的写入速度下依然会出现跟不上的情况(根本不是一个量级),所以我使用了:

            “当前FIFO内可读取数据个数等于当前距离行满的列个数”来判别,其实是很合理的!

            Done_image    的拉低让多次传入图像成为了可能。

    1. //SDRAM SIZE = 8192X512X16
    2. //8192ROWS 512COLS 16BITS
    3. module SDRAM_WR #(
    4. parameter SDRAM_COLS_MAX = 128,
    5. parameter IMAGE_NEED_ROW = 300, //300 = 640*480*8/16*512
    6. parameter TIME_PRE_CHARGE_long = 8
    7. )(
    8. input wire Sys_clk,
    9. input wire Rst_n ,
    10. //FIFO
    11. input wire FIFO_WR_EN ,//8bits
    12. input wire [ 7:0] FIFO_WR_data ,
    13. //SDRAM
    14. input wire INIT_DONE ,
    15. output reg [ 3:0] COMMAND_WR ,
    16. output reg [11:0] WR_A_ADDR ,
    17. output reg [ 1:0] WR_BANK_ADDR ,
    18. output wire WR_data_done ,
    19. output reg WR_req ,
    20. input wire ARF_req ,
    21. output reg Break_WR_to_ARF,
    22. input wire WR_access ,
    23. output wire [15:0] WRITE_SDRAM_DQ
    24. );
    25. `include "D:/three_verilog/SDRAM/SDRAM_init/rtl/sdram_param.h"
    26. localparam STATE_IDLE = 5'b0_0001;
    27. localparam STATE_WR_wait = 5'b0_0010;
    28. localparam STATE_ACT = 5'b0_0100;
    29. localparam STATE_WR_NOW = 5'b0_1000;
    30. localparam STATE_Precharge = 5'b1_0000;
    31. reg [ 4:0] STATE ;
    32. reg [ 1:0] CNT_ACT ;
    33. reg [ 9:0] CNT_SDRAM_COLS;
    34. reg [12:0] CNT_SDRAM_ROWS;
    35. wire ROWS_END_Flag ;
    36. reg [ 1:0] CNT_Brust ;
    37. reg [ 3:0] CNT_Precharge ;
    38. reg Done_image ;
    39. //FIFO
    40. wire FIFO_FULL ;
    41. wire FIFO_EMPTY ;
    42. wire [10:0] FIFO_RD_cnt ;
    43. reg FIFO_RD_EN ;
    44. wire [15:0] FIFO_RD_DATA ;
    45. assign WRITE_SDRAM_DQ = FIFO_RD_DATA;
    46. //FIFO_RD_EN
    47. always @(posedge Sys_clk or negedge Rst_n) begin
    48. if(Rst_n == 'd0) begin
    49. FIFO_RD_EN <= 'd0;
    50. end else if(STATE == STATE_WR_NOW) begin
    51. FIFO_RD_EN <= 1'b1;
    52. end else begin
    53. FIFO_RD_EN <= 'd0;
    54. end
    55. end
    56. //WR_req
    57. always @(posedge Sys_clk or negedge Rst_n) begin
    58. if(Rst_n == 'd0) begin
    59. WR_req <= 'd0;
    60. end else if(FIFO_RD_cnt >= 512 && STATE == STATE_WR_wait) begin
    61. WR_req <= 1'b1;
    62. end else if(Break_WR_to_ARF
    63. && CNT_SDRAM_ROWS == IMAGE_NEED_ROW - 1'b1
    64. && ((FIFO_RD_cnt >>2'd2) >= (SDRAM_COLS_MAX - CNT_SDRAM_COLS))) begin
    65. WR_req <= 1'd1;
    66. end else if(Done_image == 1'b1 || WR_access == 1'b1 || STATE != STATE_WR_wait) begin
    67. WR_req <= 'd0;
    68. end else begin
    69. WR_req <= WR_req;
    70. end
    71. end
    72. //Done_image
    73. always @(posedge Sys_clk or negedge Rst_n) begin
    74. if(Rst_n == 'd0) begin
    75. Done_image <= 'd0;
    76. end else if(STATE == STATE_WR_NOW
    77. && (CNT_SDRAM_ROWS == IMAGE_NEED_ROW - 1'b1 )
    78. && (CNT_SDRAM_COLS == SDRAM_COLS_MAX - 1'b1)
    79. && (CNT_Brust == INIT_Burst_length -2'd2)) begin
    80. Done_image <= 1'b1;
    81. end else if(STATE == STATE_Precharge
    82. && CNT_Precharge == TIME_PRE_CHARGE_long) begin
    83. Done_image <= 'd0;
    84. end else begin
    85. Done_image <= Done_image;
    86. end
    87. end
    88. //WR_data_done
    89. assign WR_data_done = (STATE == STATE_Precharge
    90. && CNT_Precharge == TIME_PRE_CHARGE_long
    91. && Done_image == 1'b1);
    92. //Break_WR_to_ARF
    93. always @(posedge Sys_clk or negedge Rst_n) begin
    94. if(Rst_n == 'd0) begin
    95. Break_WR_to_ARF <= 'd0;
    96. end else if(STATE == STATE_Precharge
    97. && CNT_Precharge == TIME_PRE_CHARGE_long
    98. && Done_image == 1'b0) begin
    99. Break_WR_to_ARF <= 'd1;
    100. end else if(WR_req == 1'b1)begin
    101. Break_WR_to_ARF <= 'd0;
    102. end else begin
    103. Break_WR_to_ARF <= Break_WR_to_ARF;
    104. end
    105. end
    106. //CNT_ACT
    107. always @(posedge Sys_clk or negedge Rst_n) begin
    108. if(Rst_n == 'd0) begin
    109. CNT_ACT <= 'd0;
    110. end else if(STATE == STATE_ACT) begin
    111. if(CNT_ACT == TIME_RCD) begin
    112. CNT_ACT <= 'd0;
    113. end else begin
    114. CNT_ACT <= CNT_ACT + 1'b1;
    115. end
    116. end else begin
    117. CNT_ACT <= 'd0;
    118. end
    119. end
    120. //CNT_Brust
    121. always @(posedge Sys_clk or negedge Rst_n) begin
    122. if(Rst_n == 'd0) begin
    123. CNT_Brust <= 'd0;
    124. end else if(STATE == STATE_WR_NOW) begin
    125. if(CNT_Brust == INIT_Burst_length -1'b1) begin
    126. CNT_Brust <= 'd0;
    127. end else begin
    128. CNT_Brust <= CNT_Brust + 1'b1;
    129. end
    130. end else begin
    131. CNT_Brust <= 'd0;
    132. end
    133. end
    134. //CNT_SDRAM_ROWS
    135. always @(posedge Sys_clk or negedge Rst_n) begin
    136. if(Rst_n == 'd0) begin
    137. CNT_SDRAM_ROWS <= 'd0;
    138. end else if(STATE == STATE_WR_NOW) begin
    139. if (CNT_SDRAM_ROWS == IMAGE_NEED_ROW - 1'b1
    140. && (CNT_SDRAM_COLS == SDRAM_COLS_MAX - 1'b1)
    141. && (CNT_Brust == INIT_Burst_length -1'b1)) begin
    142. CNT_SDRAM_ROWS <= 'd0;
    143. end else if((CNT_SDRAM_COLS == SDRAM_COLS_MAX - 1'b1)
    144. && (CNT_Brust == INIT_Burst_length -1'b1)) begin
    145. CNT_SDRAM_ROWS <= CNT_SDRAM_ROWS + 1'b1;
    146. end else begin
    147. CNT_SDRAM_ROWS <= CNT_SDRAM_ROWS;
    148. end
    149. end else begin
    150. CNT_SDRAM_ROWS <= CNT_SDRAM_ROWS;
    151. end
    152. end
    153. //CNT_SDRAM_COLS
    154. always @(posedge Sys_clk or negedge Rst_n) begin
    155. if(Rst_n == 'd0) begin
    156. CNT_SDRAM_COLS <= 'd0;
    157. end else if(STATE == STATE_WR_NOW) begin
    158. if((CNT_SDRAM_COLS == SDRAM_COLS_MAX - 1'b1)
    159. && (CNT_Brust == INIT_Burst_length -1'b1)) begin
    160. CNT_SDRAM_COLS <= 'd0;
    161. end else if(CNT_Brust == INIT_Burst_length -1'b1) begin
    162. CNT_SDRAM_COLS <= CNT_SDRAM_COLS + 1'b1;
    163. end else begin
    164. CNT_SDRAM_COLS <= CNT_SDRAM_COLS;
    165. end
    166. end else begin
    167. CNT_SDRAM_COLS <= CNT_SDRAM_COLS;
    168. end
    169. end
    170. assign ROWS_END_Flag = (STATE == STATE_WR_NOW) && (CNT_SDRAM_COLS == SDRAM_COLS_MAX - 1'b1) && (CNT_Brust == INIT_Burst_length -1'b1);
    171. //CNT_Precharge
    172. always @(posedge Sys_clk or negedge Rst_n) begin
    173. if(Rst_n == 'd0) begin
    174. CNT_Precharge <= 'd0;
    175. end else if(STATE == STATE_Precharge && CNT_Precharge == TIME_PRE_CHARGE_long) begin
    176. CNT_Precharge <= 'd0;
    177. end else if(STATE == STATE_Precharge) begin
    178. CNT_Precharge <= CNT_Precharge + 1'b1;
    179. end else begin
    180. CNT_Precharge <= CNT_Precharge;
    181. end
    182. end
    183. //COMMAND
    184. always @(posedge Sys_clk or negedge Rst_n) begin
    185. if(Rst_n == 'd0) begin
    186. COMMAND_WR <= COMMAND_NOP;
    187. WR_A_ADDR <= 12'd0 ;
    188. WR_BANK_ADDR <= 2'b00 ;
    189. end else if(STATE == STATE_WR_wait && WR_access == 1'b1) begin
    190. COMMAND_WR <= COMMAND_ACT;
    191. WR_A_ADDR <= CNT_SDRAM_ROWS;//row_addr
    192. WR_BANK_ADDR <= 2'b00 ;
    193. end else if(STATE == STATE_WR_NOW && CNT_Brust == 'd0) begin
    194. COMMAND_WR <= COMMAND_WRITE;
    195. WR_A_ADDR <= CNT_SDRAM_COLS<<2'd2;
    196. WR_BANK_ADDR <= 2'b00 ;
    197. end else if(STATE == STATE_Precharge && CNT_Precharge == 'd0) begin
    198. COMMAND_WR <= COMMAND_PRE;
    199. WR_A_ADDR[10]<= 1'b1 ;
    200. WR_BANK_ADDR <= 2'b00 ;
    201. end else begin
    202. COMMAND_WR <= COMMAND_NOP;
    203. WR_A_ADDR <= 12'd0 ;
    204. WR_BANK_ADDR <= 2'b00 ;
    205. end
    206. end
    207. //STATE
    208. always @(posedge Sys_clk or negedge Rst_n) begin
    209. if(Rst_n == 'd0) begin
    210. STATE <= STATE_IDLE;
    211. end else begin
    212. case (STATE)
    213. STATE_IDLE: begin
    214. if(INIT_DONE == 1'b1) begin
    215. STATE <= STATE_WR_wait;
    216. end else begin
    217. STATE <= STATE_IDLE;
    218. end
    219. end
    220. STATE_WR_wait: begin
    221. if(WR_access == 1'b1) begin
    222. STATE <= STATE_ACT;
    223. end else begin
    224. STATE <= STATE_WR_wait;
    225. end
    226. end
    227. STATE_ACT: begin
    228. if(ARF_req == 1'b1 && CNT_ACT == TIME_RCD) begin
    229. STATE <= STATE_Precharge;
    230. end else if(CNT_ACT == TIME_RCD) begin
    231. STATE <= STATE_WR_NOW;
    232. end else begin
    233. STATE <= STATE_ACT;
    234. end
    235. end
    236. STATE_WR_NOW:begin
    237. if(ARF_req == 1'b1 && CNT_Brust == INIT_Burst_length - 1'b1) begin
    238. STATE <= STATE_Precharge;
    239. end else if(ROWS_END_Flag == 1'b1) begin
    240. STATE <= STATE_Precharge;
    241. end else if(Done_image == 1'b1) begin
    242. STATE <= STATE_Precharge;
    243. end else begin
    244. STATE <= STATE_WR_NOW;
    245. end
    246. end
    247. STATE_Precharge: begin
    248. if(CNT_Precharge == TIME_PRE_CHARGE_long) begin
    249. STATE <= STATE_WR_wait;
    250. end else begin
    251. STATE <= STATE_Precharge;
    252. end
    253. end
    254. default: begin
    255. STATE <= STATE_IDLE;
    256. end
    257. endcase
    258. end
    259. end
    260. /*------------------------------------------------------------------------*/
    261. AS_FIFO_w2048x8_r1024x16 INST0_AS_FIFO_w2048x8_r1024x16 (
    262. .wr_clk ( Sys_clk ), // input wr_clk
    263. .rd_clk ( Sys_clk ), // input rd_clk
    264. .din ( FIFO_WR_data ), // input [7 : 0] din
    265. .wr_en ( FIFO_WR_EN ), // input wr_en
    266. .rd_en ( FIFO_RD_EN ), // input rd_en
    267. .dout ( FIFO_RD_DATA ), // output [15 : 0] dout
    268. .full ( FIFO_FULL ), // output full
    269. .empty ( FIFO_EMPTY ), // output empty
    270. .rd_data_count( FIFO_RD_cnt ) // output [9 : 0] rd_data_count
    271. /*------------------------------------------------------------------------*/
    272. );
    273. endmodule

    读取:

    SDRAM读写时序介绍(配时序图) - 知乎 (zhihu.com)

            读命令从输入信号BA0、BA1中选取要进行读数据操作的BANK,并在已激活的行中进行突发读操作。输入的A0-A7用来进行列寻址。在选定列地址后,就已经确定了具体的存储单元,剩下的事情就是数据通过数据I/O通道(DQ)输出到内存总线上了。但是在CAS (列地址选通脉冲)发出之后,仍要经过一定的时间才能有数据输出,从CAS与读取命令发出到第一个数据输出的这段时间,被定义为CL(CAS Latency,CAS潜伏期)。由于CL只在读取时出现,所以CL又被称为读取潜伏期(RL,ReadLatency)。CL的单位与tRCD一样,为时钟周期数,具体耗时由时钟频率决定。CAS并不是在经过CL 周期之后才送达存储单元。实际上CAS与RAS一样是瞬间到达的,但CAS的响应时间要更快一些。下图展示了CAS=3时的读时序:

    图4 CAS Latency=3的示意图

            由于存储体中晶体管存在反应时间,从而造成数据不可能与CAS在同一上升沿触发,因此要延后至少一个时钟周期。考虑到芯片体积较小的因素,存储单元中的电容容量很小,所以信号要经过放大来保证其有效的识别性,这个放大/驱动工作由S-AMP负责,一个存储体对应一个S-AMP通道。但它要有一个准备时间才能保证信号的发送强度(事前还要进行电压比较以进行逻辑电平的判断),因此从数据I/O总线上有数据输出之前的一个时钟上升沿开始,数据即已传向S-AMP,也就是说此时数据已经被触发,经过一定的驱动时间最终传向数据I/O 总线进行输出,这段时间我们称之为tAC(Access-Time-from-CLK,时钟触发后的访问时间),单位是ns。在突发读操作完成后,如果选择了自动预充电模式,那么该行就会直接进入充电。如果没有选择此模式,那么该行将保持打开状态,供后续访问。自动预充电模式的选择与A10的值有关,A10为高时为自动预充电命令模式。

    读取:

             小总结:列选通时间

             CAS Latency=3的时候,可以视为RD_COMMAND发出后的第四个时钟周期才有数据浮现在端口上。(中间隔了三个时钟周期)

            为此:FIFO_WR_EN 可以用RD_COMMAND产生的那个时刻延四拍得到(包括其本身的一个周期+中间隔了三个时钟周期)。

            其实三拍也行,用ASSIGN存输入数据就行,但是会看到更多高阻态,很不好。

    1. //FIFO_WR_EN INIT_CAS_Latency = 3
    2. always @(posedge Sys_clk or negedge Rst_n) begin
    3. if(Rst_n == 'd0) begin
    4. FIFO_WR_EN <= 'd0;
    5. end else if(STATE == STATE_RD_NOW) begin
    6. FIFO_WR_EN <= 1'b1;
    7. end else begin
    8. FIFO_WR_EN <= 'd0;
    9. end
    10. end
    11. always @(posedge Sys_clk or negedge Rst_n) begin
    12. if(Rst_n == 'd0) begin
    13. FIFO_WR_delay <= 'd0;
    14. end else begin
    15. FIFO_WR_delay <= {FIFO_WR_delay[2:0],FIFO_WR_EN};
    16. end
    17. end

            因为是预备传图640x480的SDRAM,每次打算使用SDRAM读出一行数据进FIFO,再由FIFO发给VGA控制器显示数据,所以定义一个能放得下相应数据的FIFO。

            SDRAM_RD的时序和WR时序差不多,唯一要注意的只有上面提过的列选通时间。

    此外:这里PRE命令的发出时间点纯粹是因为我喜欢,

            如果感兴趣为什么在这个时间点才发送可以仿真试试看。

                    (其实是不影响整体的,但是会好看一些哦)

    1. //COMMAND
    2. always @(posedge Sys_clk or negedge Rst_n) begin
    3. if(Rst_n == 'd0) begin
    4. COMMAND_RD <= COMMAND_NOP;
    5. RD_A_ADDR <= 12'd0 ;
    6. RD_BANK_ADDR <= 2'b00 ;
    7. end else if(STATE == STATE_RD_WAIT && RD_access == 1'b1) begin
    8. COMMAND_RD <= COMMAND_ACT;
    9. RD_A_ADDR <= CNT_SDRAM_ROWS;//row_addr
    10. RD_BANK_ADDR <= 2'b00 ;
    11. end else if(STATE == STATE_RD_NOW && CNT_Brust == 'd0 && ROWS_END_Flag == 'd0) begin
    12. COMMAND_RD <= COMMAND_READ;
    13. RD_A_ADDR <= CNT_SDRAM_COLS<<2'd2;
    14. RD_BANK_ADDR <= 2'b00 ;
    15. end else if(STATE == STATE_Precharge && CNT_Precharge == 'd2) begin
    16. COMMAND_RD <= COMMAND_PRE;
    17. RD_A_ADDR[10]<= 1'b1 ;
    18. RD_BANK_ADDR <= 2'b00 ;
    19. end else begin
    20. COMMAND_RD <= COMMAND_NOP;
    21. RD_A_ADDR <= 12'd0 ;
    22. RD_BANK_ADDR <= 2'b00 ;
    23. end
    24. end

            

    1. //SDRAM SIZE = 8192X512X16
    2. //8192ROWS 512COLS 16BITS
    3. module SDRAM_RD #(
    4. parameter SDRAM_COLS_MAX = 128,
    5. parameter IMAGE_NEED_ROW = 300, //300 = 640*480*8/16*512
    6. parameter TIME_PRE_CHARGE_long = 10
    7. )(
    8. input wire Sys_clk,
    9. input wire Rst_n ,
    10. //VGA 640x480x60hz
    11. input wire VGA_CLOCK ,
    12. output reg VGA_START ,
    13. //FIFO
    14. input wire VGA_FIFO_RD_EN ,
    15. output wire [ 7:0] VGA_FIFO_RD_DATA,
    16. //CTRL
    17. input wire WR_data_done ,
    18. //SDRAM
    19. input wire INIT_DONE ,
    20. output reg [ 3:0] COMMAND_RD ,
    21. output reg [11:0] RD_A_ADDR ,
    22. output reg [ 1:0] RD_BANK_ADDR ,
    23. output wire RD_DATA_DONE ,
    24. output reg RD_req ,
    25. input wire WR_req ,
    26. input wire ARF_req ,
    27. output reg Break_RD_other ,
    28. input wire RD_access ,
    29. input wire [15:0] READ_SDRAM_DQ
    30. );
    31. `include "D:/three_verilog/SDRAM/SDRAM_init/rtl/sdram_param.h"
    32. localparam STATE_IDLE = 5'b0_0001;
    33. localparam STATE_RD_WAIT = 5'b0_0010;
    34. localparam STATE_ACT = 5'b0_0100;
    35. localparam STATE_RD_NOW = 5'b0_1000;
    36. localparam STATE_Precharge = 5'b1_0000;
    37. reg [ 4:0] STATE ;
    38. reg [ 1:0] CNT_ACT ;
    39. reg [ 9:0] CNT_SDRAM_COLS;
    40. reg [12:0] CNT_SDRAM_ROWS;
    41. wire ROWS_END_Flag ;
    42. reg [ 1:0] CNT_Brust ;
    43. reg [ 3:0] CNT_Precharge ;
    44. reg Done_image ;
    45. //FIFO
    46. wire FIFO_FULL ;
    47. wire FIFO_EMPTY ;
    48. wire [11:0] FIFO_RD_cnt ;
    49. wire [10:0] FIFO_WR_cnt ;
    50. wire [15:0] FIFO_WR_data ;
    51. reg FIFO_WR_EN ;
    52. reg [ 3:0] FIFO_WR_delay ;
    53. //SIM
    54. reg Time_to_Read ;
    55. assign FIFO_WR_data = READ_SDRAM_DQ;
    56. always @(posedge Sys_clk or negedge Rst_n) begin
    57. if(Rst_n == 'd0) begin
    58. Time_to_Read <= 'd0;
    59. end else if(WR_data_done == 'd1) begin
    60. Time_to_Read <= 'd1;
    61. end else begin
    62. Time_to_Read <= Time_to_Read;
    63. end
    64. end
    65. //FIFO_WR_EN INIT_CAS_Latency = 3
    66. always @(posedge Sys_clk or negedge Rst_n) begin
    67. if(Rst_n == 'd0) begin
    68. FIFO_WR_EN <= 'd0;
    69. end else if(STATE == STATE_RD_NOW) begin
    70. FIFO_WR_EN <= 1'b1;
    71. end else begin
    72. FIFO_WR_EN <= 'd0;
    73. end
    74. end
    75. always @(posedge Sys_clk or negedge Rst_n) begin
    76. if(Rst_n == 'd0) begin
    77. FIFO_WR_delay <= 'd0;
    78. end else begin
    79. FIFO_WR_delay <= {FIFO_WR_delay[2:0],FIFO_WR_EN};
    80. end
    81. end
    82. //VGA_START
    83. always @(posedge VGA_CLOCK) begin
    84. if(Rst_n == 'd0) begin
    85. VGA_START <= 'd0;
    86. end else if(FIFO_RD_cnt >= 'd640) begin
    87. VGA_START <= 'd1;
    88. end else begin
    89. VGA_START <= VGA_START;
    90. end
    91. end
    92. //RD_req:FIFO_WR_cnt <= 'd320时,从SDRAM读取数据给FIFO
    93. //640x480 一行为640x8bits数据
    94. always @(posedge Sys_clk or negedge Rst_n) begin
    95. if(Rst_n == 'd0) begin
    96. RD_req <= 'd0;
    97. end else if(FIFO_WR_cnt <= 'd512
    98. && STATE == STATE_RD_WAIT
    99. && Time_to_Read ==1
    100. && Done_image == 'd0) begin
    101. RD_req <= 1'b1;
    102. end else if(Break_RD_other == 1'b1
    103. && STATE == STATE_RD_WAIT
    104. && FIFO_WR_cnt <= 'd512) begin
    105. RD_req <= 1'd1;
    106. end else if(Done_image == 1'b1 || RD_access == 1'b1 || STATE != STATE_RD_WAIT) begin
    107. RD_req <= 'd0;
    108. end else begin
    109. RD_req <= RD_req;
    110. end
    111. end
    112. //Done_image
    113. always @(posedge Sys_clk or negedge Rst_n) begin
    114. if(Rst_n == 'd0) begin
    115. Done_image <= 'd0;
    116. end else if(STATE == STATE_RD_NOW
    117. && (CNT_SDRAM_ROWS == IMAGE_NEED_ROW - 1'b1 )
    118. && (CNT_SDRAM_COLS == SDRAM_COLS_MAX - 1'b1)
    119. && (CNT_Brust == INIT_Burst_length -2'd2)) begin
    120. Done_image <= 1'b1;
    121. end else if(STATE == STATE_Precharge
    122. && CNT_Precharge == TIME_PRE_CHARGE_long) begin
    123. Done_image <= 'd0;
    124. end else begin
    125. Done_image <= Done_image;
    126. end
    127. end
    128. //RD_DATA_DONE
    129. assign RD_DATA_DONE = (STATE == STATE_Precharge
    130. && CNT_Precharge == TIME_PRE_CHARGE_long
    131. && Done_image == 1'b1);
    132. //Break_RD_other
    133. always @(posedge Sys_clk or negedge Rst_n) begin
    134. if(Rst_n == 'd0) begin
    135. Break_RD_other <= 'd0;
    136. end else if(STATE == STATE_Precharge
    137. && CNT_Precharge == TIME_PRE_CHARGE_long
    138. && Done_image == 1'b0) begin
    139. Break_RD_other <= 'd1;
    140. end else if(RD_req == 1'b1)begin
    141. Break_RD_other <= 'd0;
    142. end else begin
    143. Break_RD_other <= Break_RD_other;
    144. end
    145. end
    146. //CNT_ACT
    147. always @(posedge Sys_clk or negedge Rst_n) begin
    148. if(Rst_n == 'd0) begin
    149. CNT_ACT <= 'd0;
    150. end else if(STATE == STATE_ACT) begin
    151. if(CNT_ACT == TIME_RCD) begin
    152. CNT_ACT <= 'd0;
    153. end else begin
    154. CNT_ACT <= CNT_ACT + 1'b1;
    155. end
    156. end else begin
    157. CNT_ACT <= 'd0;
    158. end
    159. end
    160. //CNT_Brust
    161. always @(posedge Sys_clk or negedge Rst_n) begin
    162. if(Rst_n == 'd0) begin
    163. CNT_Brust <= 'd0;
    164. end else if(STATE == STATE_RD_NOW) begin
    165. if(CNT_Brust == INIT_Burst_length -1'b1) begin
    166. CNT_Brust <= 'd0;
    167. end else begin
    168. CNT_Brust <= CNT_Brust + 1'b1;
    169. end
    170. end else begin
    171. CNT_Brust <= 'd0;
    172. end
    173. end
    174. //CNT_SDRAM_ROWS
    175. always @(posedge Sys_clk or negedge Rst_n) begin
    176. if(Rst_n == 'd0) begin
    177. CNT_SDRAM_ROWS <= 'd0;
    178. end else if(STATE == STATE_RD_NOW) begin
    179. if (CNT_SDRAM_ROWS == IMAGE_NEED_ROW - 1'b1
    180. && (CNT_SDRAM_COLS == SDRAM_COLS_MAX - 1'b1)
    181. && (CNT_Brust == INIT_Burst_length -1'b1)) begin
    182. CNT_SDRAM_ROWS <= 'd0;
    183. end else if((CNT_SDRAM_COLS == SDRAM_COLS_MAX - 1'b1)
    184. && (CNT_Brust == INIT_Burst_length -1'b1)) begin
    185. CNT_SDRAM_ROWS <= CNT_SDRAM_ROWS + 1'b1;
    186. end else begin
    187. CNT_SDRAM_ROWS <= CNT_SDRAM_ROWS;
    188. end
    189. end else begin
    190. CNT_SDRAM_ROWS <= CNT_SDRAM_ROWS;
    191. end
    192. end
    193. //CNT_SDRAM_COLS
    194. always @(posedge Sys_clk or negedge Rst_n) begin
    195. if(Rst_n == 'd0) begin
    196. CNT_SDRAM_COLS <= 'd0;
    197. end else if(STATE == STATE_RD_NOW) begin
    198. if((CNT_SDRAM_COLS == SDRAM_COLS_MAX - 1'b1)
    199. && (CNT_Brust == INIT_Burst_length -1'b1)) begin
    200. CNT_SDRAM_COLS <= 'd0;
    201. end else if(CNT_Brust == INIT_Burst_length -1'b1) begin
    202. CNT_SDRAM_COLS <= CNT_SDRAM_COLS + 1'b1;
    203. end else begin
    204. CNT_SDRAM_COLS <= CNT_SDRAM_COLS;
    205. end
    206. end else begin
    207. CNT_SDRAM_COLS <= CNT_SDRAM_COLS;
    208. end
    209. end
    210. assign ROWS_END_Flag = (STATE == STATE_RD_NOW)
    211. && (CNT_SDRAM_COLS == SDRAM_COLS_MAX - 1'b1)
    212. && (CNT_Brust == INIT_Burst_length -1'b1);
    213. //CNT_Precharge
    214. always @(posedge Sys_clk or negedge Rst_n) begin
    215. if(Rst_n == 'd0) begin
    216. CNT_Precharge <= 'd0;
    217. end else if(STATE == STATE_Precharge && CNT_Precharge == TIME_PRE_CHARGE_long) begin
    218. CNT_Precharge <= 'd0;
    219. end else if(STATE == STATE_Precharge) begin
    220. CNT_Precharge <= CNT_Precharge + 1'b1;
    221. end else begin
    222. CNT_Precharge <= CNT_Precharge;
    223. end
    224. end
    225. //COMMAND
    226. always @(posedge Sys_clk or negedge Rst_n) begin
    227. if(Rst_n == 'd0) begin
    228. COMMAND_RD <= COMMAND_NOP;
    229. RD_A_ADDR <= 12'd0 ;
    230. RD_BANK_ADDR <= 2'b00 ;
    231. end else if(STATE == STATE_RD_WAIT && RD_access == 1'b1) begin
    232. COMMAND_RD <= COMMAND_ACT;
    233. RD_A_ADDR <= CNT_SDRAM_ROWS;//row_addr
    234. RD_BANK_ADDR <= 2'b00 ;
    235. end else if(STATE == STATE_RD_NOW && CNT_Brust == 'd0 && ROWS_END_Flag == 'd0) begin
    236. COMMAND_RD <= COMMAND_READ;
    237. RD_A_ADDR <= CNT_SDRAM_COLS<<2'd2;
    238. RD_BANK_ADDR <= 2'b00 ;
    239. end else if(STATE == STATE_Precharge && CNT_Precharge == 'd2) begin
    240. COMMAND_RD <= COMMAND_PRE;
    241. RD_A_ADDR[10]<= 1'b1 ;
    242. RD_BANK_ADDR <= 2'b00 ;
    243. end else begin
    244. COMMAND_RD <= COMMAND_NOP;
    245. RD_A_ADDR <= 12'd0 ;
    246. RD_BANK_ADDR <= 2'b00 ;
    247. end
    248. end
    249. //STATE
    250. always @(posedge Sys_clk or negedge Rst_n) begin
    251. if(Rst_n == 'd0) begin
    252. STATE <= STATE_IDLE;
    253. end else begin
    254. case (STATE)
    255. STATE_IDLE: begin
    256. if(INIT_DONE == 1'b1) begin
    257. STATE <= STATE_RD_WAIT;
    258. end else begin
    259. STATE <= STATE_IDLE;
    260. end
    261. end
    262. STATE_RD_WAIT: begin
    263. if(RD_access == 1'b1) begin
    264. STATE <= STATE_ACT;
    265. end else begin
    266. STATE <= STATE_RD_WAIT;
    267. end
    268. end
    269. STATE_ACT: begin
    270. if((ARF_req == 1'b1 || WR_req == 1'b1) && CNT_ACT == TIME_RCD) begin
    271. STATE <= STATE_Precharge;
    272. end else if(CNT_ACT == TIME_RCD) begin
    273. STATE <= STATE_RD_NOW;
    274. end else begin
    275. STATE <= STATE_ACT;
    276. end
    277. end
    278. STATE_RD_NOW:begin
    279. if((ARF_req == 1'b1 || WR_req == 1'b1)
    280. && CNT_Brust == INIT_Burst_length - 1'b1) begin
    281. STATE <= STATE_Precharge;
    282. end else if(ROWS_END_Flag == 1'b1) begin
    283. STATE <= STATE_Precharge;
    284. end else if(Done_image == 1'b1) begin
    285. STATE <= STATE_Precharge;
    286. end else begin
    287. STATE <= STATE_RD_NOW;
    288. end
    289. end
    290. STATE_Precharge: begin
    291. if(CNT_Precharge == TIME_PRE_CHARGE_long) begin
    292. STATE <= STATE_RD_WAIT;
    293. end else begin
    294. STATE <= STATE_Precharge;
    295. end
    296. end
    297. default: begin
    298. STATE <= STATE_IDLE;
    299. end
    300. endcase
    301. end
    302. end
    303. /*------------------------------------------------------------------------*/
    304. AS_FIFO_w2048x16_r4096x8 Inst_AS_FIFO_w2048x16_r4096x8 (
    305. .wr_clk ( Sys_clk ), // input wr_clk
    306. .rd_clk ( VGA_CLOCK ), // input rd_clk
    307. .din ( FIFO_WR_data ), // input [15 : 0] din
    308. .wr_en ( FIFO_WR_delay[3]), // input wr_en
    309. .rd_en ( VGA_FIFO_RD_EN ), // input rd_en
    310. .dout ( VGA_FIFO_RD_DATA), // output [7 : 0] dout
    311. .full ( FIFO_FULL ), // output full
    312. .empty ( FIFO_EMPTY ), // output empty
    313. .rd_data_count( FIFO_RD_cnt ), // output [11 : 0] rd_data_count
    314. .wr_data_count( FIFO_WR_cnt ) // output [10 : 0] wr_data_count
    315. );
    316. /*------------------------------------------------------------------------*/
    317. endmodule

    串口传图的VGA部分可由 串口传图并图像处理(sobel)的简单实现_串口图像传输_NoNoUnknow的博客-CSDN博客

    取得,展示视频:

    想起来再拍。

    参考资料:

    [1]威三学院FPGA教程

    [2]小梅哥AC620V2教程

    [3]SDRAM读写时序介绍(配时序图) - 知乎 (zhihu.com)

  • 相关阅读:
    从大龄程序员现状聊聊出路
    分布式应用程序协调服务软件--zookeeper
    FANUC机器人防干涉区域的使用方法和设置步骤
    Kotlin编程实战——类与对象(05)
    面向对象、方法重写、重载(overload)与重写(override)的区别、super关键字、构造方法的特殊性
    flutter移植arm32位板子
    【Redis】Redis介绍
    SpringBoot和SpringCloud的区别,使用微服务的好处和缺点
    docker 安装 superset
    React Native 技术选型分析
  • 原文地址:https://blog.csdn.net/NoNoUnknow/article/details/132782290