基于FPGA的SDRAM控制器设计(4)[通俗易懂]

基于FPGA完整SDRAM控制器SDRAM控制器接口简述自动读写模块的框图SDRAM控制器完整代码SDRAM控制器的测试代码仿真结果SDRAM控制器接口简述完整的SDRAM控制器的模块框图如下:前面的三篇文章,我们已经简述了基本的SDRAM的基本操作。这里总结一下SDRAM的几个模块,SDRAM的上电初始化,自刷新、读写模块、顶层仲裁控制。了解了上面的操作,我们已经可以完成SDRAM控制器…

大家好,又见面了,我是你们的朋友全栈君。

SDRAM控制器接口简述

完整的SDRAM控制器的模块框图如下:
在这里插入图片描述
前面的三篇文章,我们已经简述了基本的SDRAM的基本操作。这里总结一下SDRAM的几个模块,SDRAM的上电初始化,自刷新、读写模块、顶层仲裁控制。了解了上面的操作,我们已经可以完成SDRAM控制器的代码完成,接下来我们便完善SDRAM控制器的接口,简化该SDRAM控制器设计,使得该SDRAM控制器可以很容易的使用。下面的接口定义如下:
在这里插入图片描述
顶层模块的接口主要时上面的接口,我们把SDRAM做成了FIFO类型的接口。
其中1时系统接口:
sclk:是100MHz的时钟,
rst_n:是系统复位信号,
2是SDRAM硬件的接口信号,连接到SDRAM硬件上。
3是SDRAM写FIFO的信号
4是SDRAM读FIFO的信号
5是SDRAM最大的读地址信号,
RROW_ADDR_END是SDRAM的FIFO接口最大的行地址,
RCOL_MADDR_END是SDRAM最大的列地址,超过上面的信号便会清零,注意RCOL_MADDR_END信号必须是4的倍数,因为我们SDRAM中是4突发的。
6是SDRAM最大FIFO接口最大的写地址信号,与5的描述相同。

自动读写模块的框图

这里为了方便同学们理解,我们给出自动读写模块的框图,也是仿照开源骚客的文章设计:
在这里插入图片描述
在这里插入图片描述

SDRAM控制器完整代码

经过前面三篇文章的学习,我们这里不在给出原理,直接给出使用的SDRAM的代码:
sdram_top模块:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website : 
// Module Name : sdram_top.v
// Create Time : 2020-02-09 17:22:24
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
// 
// *********************************************************************************
module sdram_top(
//System Interfaces
input                   sclk            ,
input                   rst_n           ,
//SDRAM Interfaces
output  wire            sdram_clk       ,
output  wire            sdram_cke       ,
output  reg             sdram_cs_n      ,
output  reg             sdram_cas_n     ,
output  reg             sdram_ras_n     ,
output  reg             sdram_we_n      ,
output  reg     [ 1:0]  sdram_bank      ,
output  reg     [11:0]  sdram_addr      ,
output  wire    [ 1:0]  sdram_dqm       ,
inout           [15:0]  sdram_dq        ,
//User Interfaces
input                   wfifo_wclk      ,
input                   wfifo_wr_en     ,
input           [15:0]  wfifo_wr_data   ,
input                   rfifo_rclk      ,
input                   rfifo_rd_en     ,
output  wire    [15:0]  rfifo_rd_data   ,
output  wire            rfifo_rd_ready            
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
parameter  RROW_ADDR_END    =   937         ;
parameter  RCOL_MADDR_END   =   256         ;
parameter  WROW_ADDR_END    =   937         ;
parameter  WCOL_MADDR_END   =   256         ;
localparam      NOP     =   4'b0111         ;
localparam      IDLE    =   5'b0_0001       ;
localparam      ARBIT   =   5'b0_0010       ;
localparam      AREF    =   5'b0_0100       ;
localparam      WRITE   =   5'b0_1000       ;
localparam      READ    =   5'b1_0000       ;
//sdram_init
wire                [ 3:0]  init_cmd        ;
wire                [11:0]  init_addr       ;
wire                        init_done       ;
//AREF
wire                        aref_req        ;
reg                         aref_en         ;
wire                        aref_end        ;
wire                [ 3:0]  aref_cmd        ;
wire                [11:0]  aref_addr       ;
//WRITE
wire                [ 3:0]  wr_cmd          ;
wire                [11:0]  wr_addr         ;
wire                [ 1:0]  wr_bank_addr    ;
wire                [15:0]  wr_data         ;    
reg                         wr_en           ;
wire                        wr_end          ;
wire                        wr_req          ;
wire                        wr_trig         ;
//READ
wire                [ 3:0]  rd_cmd          ;
wire                [11:0]  rd_addr         ;
wire                [ 1:0]  rd_bank_addr    ;
reg                         rd_en           ;
wire                        rd_end          ;
wire                        rd_req          ;
wire                        rd_trig         ;
//sdram_auto_write_read
wire                        wfifo_rd_en     ;       
wire                [15:0]  wfifo_rd_data   ;
wire                        rfifo_wr_en     ;      
wire                [15:0]  rfifo_wr_data   ;
//ARBIT
reg                 [ 4:0]  state           ;
//Others
reg                 [15:0]  sdram_dq1       ;
reg                         sdram_dq_en     ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
assign      sdram_dqm       =       2'b00;
assign      sdram_clk       =       ~sclk;
assign      sdram_cke       =       1'b1;
assign      sdram_dq        =       sdram_dq_en == 1'b1 ? sdram_dq1 : 16'hzzzz;
assign      rfifo_wr_data   =       sdram_dq;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
state       <=      IDLE;
else case(state)
IDLE    :   if(init_done == 1'b1)
state           <=      ARBIT;
else 
state           <=      state;
ARBIT   :   if(aref_req == 1'b1)
state           <=      AREF;
else if(wr_req == 1'b1)
state           <=      WRITE;
else if(rd_req == 1'b1)
state           <=      READ;
else
state           <=      state;
AREF    :   if(aref_end == 1'b1)
state           <=      ARBIT;
else
state           <=      state;
WRITE   :   if(wr_end == 1'b1)
state           <=      ARBIT;
else 
state           <=      state;
READ    :   if(rd_end == 1'b1)
state           <=      ARBIT;
else
state           <=      state;                        
default :   state           <=      IDLE;
endcase
always @(*)
case(state)
IDLE    :   begin
sdram_addr      =      init_addr;
{ 
sdram_cs_n, sdram_ras_n, sdram_cas_n, sdram_we_n}      =       init_cmd;
sdram_dq_en     =       1'b0;
end
AREF    :   begin
sdram_addr      =      aref_addr;
{ 
sdram_cs_n, sdram_ras_n, sdram_cas_n, sdram_we_n}      =       aref_cmd;
end
WRITE   :   begin
sdram_addr      =      wr_addr;
{ 
sdram_cs_n, sdram_ras_n, sdram_cas_n, sdram_we_n}      =       wr_cmd;
sdram_dq1       =      wr_data;
sdram_bank      =      wr_bank_addr;
sdram_dq_en     =      1'b1;
end
READ    :   begin
sdram_addr      =      rd_addr;
{ 
sdram_cs_n, sdram_ras_n, sdram_cas_n, sdram_we_n}      =       rd_cmd;
sdram_bank      =      rd_bank_addr;
sdram_dq_en     =      1'b0;  
end
default :   begin
sdram_addr      =      12'd0;
{ 
sdram_cs_n, sdram_ras_n, sdram_cas_n, sdram_we_n}      =       NOP;
sdram_dq1       =      16'd0;
sdram_bank      =      2'b00;
sdram_dq_en     =      1'b0;
end
endcase
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
aref_en             <=      1'b0;
else if(state == ARBIT && aref_req == 1'b1) 
aref_en             <=      1'b1;
else
aref_en             <=      1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
wr_en               <=      1'b0;
else if(state == ARBIT && aref_req == 1'b1) 
wr_en               <=      1'b0;
else if(state == ARBIT && wr_req == 1'b1) 
wr_en               <=      1'b1;
else
wr_en               <=      1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
rd_en               <=      1'b0;
else if(state == ARBIT && aref_req == 1'b1) 
rd_en               <=      1'b0;
else if(state == ARBIT && wr_req == 1'b1)
rd_en               <=      1'b0;
else if(state == ARBIT && rd_req == 1'b1)
rd_en               <=      1'b1;
else
rd_en               <=      1'b0;
sdram_init sdram_init_inst(
//System Interfaces
.sclk                   (sclk                   ),
.rst_n                  (rst_n                  ),
//SDRAM Interfaces
.sdram_cmd              (init_cmd               ),
.sdram_addr             (init_addr              ),
//Others
.init_done              (init_done              )
);
sdram_aref sdram_aref_inst(
//Sysytem Interfaces
.sclk                   (sclk                   ),
.rst_n                  (rst_n                  ),
//SDRAM Interfaces
.aref_cmd               (aref_cmd               ),
.aref_addr              (aref_addr              ),
//Others
.aref_req               (aref_req               ),
.aref_end               (aref_end               ),
.aref_en                (aref_en                ),
.init_done              (init_done              )
);
sdram_auto_write_read sdram_auto_write_read_inst(
// system signals
.rst_n                  (rst_n                  ),       
// wfifo
.wfifo_wclk             (wfifo_wclk             ),
.wfifo_wr_en            (wfifo_wr_en            ),       
.wfifo_wr_data          (wfifo_wr_data          ),
.wfifo_rclk             (sclk                   ),
.wfifo_rd_en            (wfifo_rd_en            ),       
.wfifo_rd_data          (wfifo_rd_data          ),
.wr_trig                (wr_trig                ),
// rfifo
.rfifo_wclk             (~sclk                  ),       // 100MHz
.rfifo_wr_en            (rfifo_wr_en            ),       
.rfifo_wr_data          (rfifo_wr_data          ),
.rfifo_rclk             (rfifo_rclk             ),
.rfifo_rd_en            (rfifo_rd_en            ),       
.rfifo_rd_data          (rfifo_rd_data          ),
.rd_trig                (rd_trig                ),
// user interfaces
.rfifo_rd_ready         (rfifo_rd_ready         )
);
sdram_write #(
.WROW_ADDR_END          (WROW_ADDR_END          ),
.WCOL_MADDR_END         (WCOL_MADDR_END         )
) sdram_write_inst(
//System Interfaces
.sclk                   (sclk                   ),
.rst_n                  (rst_n                  ),
//SDRAM Interfaces
.wr_cmd                 (wr_cmd                 ),
.wr_addr                (wr_addr                ),
.bank_addr              (wr_bank_addr           ),
.wr_data                (wr_data                ), 
//Communication Interfaces
.wr_trig                (wr_trig                ),
.wr_en                  (wr_en                  ),
.wr_end                 (wr_end                 ),
.wr_req                 (wr_req                 ),
.aref_req               (aref_req               ),
.wfifo_rd_en            (wfifo_rd_en            ),
.wfifo_rd_data          (wfifo_rd_data          )    
);
sdram_read #(
.RROW_ADDR_END          (RROW_ADDR_END          ),
.RCOL_MADDR_END         (RCOL_MADDR_END         )
) sdram_read_inst(
//System Interfaces
.sclk                   (sclk                   ),
.rst_n                  (rst_n                  ),
//SDRAM Interfaces
.rd_cmd                 (rd_cmd                 ),
.rd_addr                (rd_addr                ),
.bank_addr              (rd_bank_addr           ),    
//Communication Interfaces
.rd_trig                (rd_trig                ),
.rd_en                  (rd_en                  ),
.rd_end                 (rd_end                 ),
.rd_req                 (rd_req                 ),
.aref_req               (aref_req               ),
.rd_data_en             (rfifo_wr_en            )
);
endmodule

sdram_init模块:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website : 
// Module Name : sdram_init.v
// Create Time : 2020-02-09 16:20:31
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
// 
// *********************************************************************************
module sdram_init(
//System Interfaces
input                   sclk            ,
input                   rst_n           ,
//SDRAM Interfaces
output  reg     [ 3:0]  sdram_cmd       ,
output  reg     [11:0]  sdram_addr      ,
//Others
output  reg             init_done  
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
localparam  DELAY_200US =  20000           ;
//SDRAM Command
localparam  NOP         =  4'b0111          ;
localparam  PRE         =  4'b0010          ;
localparam  AREF        =  4'b0001          ;
localparam  MSET        =  4'b0000          ;
reg                 [14:0]  cnt_200us       ;
reg                         flag_200us      ;
reg                 [ 4:0]  cnt_cmd         ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
cnt_200us       <=      11'd0;
else if(flag_200us == 1'b0)
cnt_200us       <=      cnt_200us + 1'b1;
else
cnt_200us       <=      cnt_200us;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
flag_200us      <=      1'b0;
else if(cnt_200us >= DELAY_200US) 
flag_200us      <=      1'b1;
else
flag_200us      <=      flag_200us;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
cnt_cmd         <=      5'd0;
else if(flag_200us == 1'b1 && cnt_cmd <= 5'd19)
cnt_cmd         <=      cnt_cmd + 1'b1;
else 
cnt_cmd         <=      cnt_cmd;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
sdram_cmd       <=      NOP;
else case(cnt_cmd)
1       :   sdram_cmd       <=      PRE;
3       :   sdram_cmd       <=      AREF;
11      :   sdram_cmd       <=      AREF;
19      :   sdram_cmd       <=      MSET;
default :   sdram_cmd       <=      NOP;
endcase
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
sdram_addr      <=      12'b0100_0000_0000;
else if(cnt_cmd == 5'd19) 
sdram_addr      <=      12'b0000_0011_0010;
else
sdram_addr      <=      12'b0100_0000_0000;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
init_done       <=      1'b0; 
else if(cnt_cmd > 5'd19) 
init_done       <=      1'b1;
else
init_done       <=      init_done;
endmodule

sdram_aref模块:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website : 
// Module Name : sdram_aref.v
// Create Time : 2020-02-10 13:34:03
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
// 
// *********************************************************************************
module sdram_aref(
//Sysytem Interfaces
input                   sclk            ,
input                   rst_n           ,
//SDRAM Interfaces
output  reg     [ 3:0]  aref_cmd        ,
output  wire    [11:0]  aref_addr       ,
//Others
input                   init_done       ,
output  reg             aref_req        ,
output  reg             aref_end        ,
input                   aref_en         
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
localparam  NOP         =   4'b0111         ;
localparam  PRE         =   4'b0010         ;
localparam  AREF        =   4'b0001         ;
localparam  DELAY_15US  =   11'd1500        ;
reg                         aref_flag       ;
reg             [ 2:0]      cnt_cmd         ;
reg             [10:0]      cnt_15ms        ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
assign  aref_addr           =       12'b0100_0000_0000;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
aref_flag           <=      1'b0; 
else if(cnt_cmd >= 3'd7)
aref_flag           <=      1'b0;
else if(aref_en == 1'b1)
aref_flag           <=      1'b1;
else
aref_flag           <=      aref_flag;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
cnt_cmd             <=      3'd0;
else if(cnt_cmd >= 3'd7)
cnt_cmd             <=      3'd0;
else if(aref_flag == 1'b1)
cnt_cmd             <=      cnt_cmd + 1'b1; 
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
aref_cmd            <=      NOP;    
else case(cnt_cmd)
1       :   aref_cmd            <=      PRE;
4       :   aref_cmd            <=      AREF;
default :   aref_cmd            <=      NOP;
endcase
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
aref_end            <=      1'b0;
else if(cnt_cmd >= 3'd7)
aref_end            <=      1'b1;
else
aref_end            <=      1'b0;   
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
cnt_15ms            <=      20'd0;
else if(cnt_15ms == DELAY_15US)
cnt_15ms            <=      20'd0;
else if(init_done == 1'b1) 
cnt_15ms            <=      cnt_15ms + 1'b1;
else
cnt_15ms            <=      20'd0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
aref_req            <=      1'b0; 
else if(cnt_15ms == DELAY_15US)
aref_req            <=      1'b1;
else if(aref_en == 1'b1)
aref_req            <=      1'b0;
else
aref_req            <=      aref_req;
endmodule

sdram_auto_write_read模块:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website : 
// Module Name : sdram_auto_write_read.v
// Create Time : 2020-02-15 11:26:21
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
// 
// *********************************************************************************
module sdram_auto_write_read(
// system signals
input                   rst_n                   ,       
// wfifo
input                   wfifo_wclk              ,
input                   wfifo_wr_en             ,       
input           [15:0]  wfifo_wr_data           ,
input                   wfifo_rclk              ,
input                   wfifo_rd_en             ,       
output  wire    [15:0]  wfifo_rd_data           ,
output  reg             wr_trig                 ,
// rfifo
input                   rfifo_wclk              ,       // 100MHz
input                   rfifo_wr_en             ,       
input           [15:0]  rfifo_wr_data           ,
input                   rfifo_rclk              ,
input                   rfifo_rd_en             ,       
output  wire    [15:0]  rfifo_rd_data           ,
output  reg             rd_trig                 ,
// user interfaces
output  reg             rfifo_rd_ready      
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
parameter   WFIFO_RD_CNT    =       256             ;
parameter   RFIFO_WR_CNT    =       250             ;
wire                [10:0]  wfifo_rd_count          ;
wire                [10:0]  rfifo_wr_count          ;
reg                         flag_rd                 ;   
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
always @(posedge rfifo_wclk or negedge rst_n)
if(rst_n == 1'b0)
rfifo_rd_ready      <=      1'b0;
else if(rfifo_wr_count >= RFIFO_WR_CNT)
rfifo_rd_ready      <=      1'b1;
else
rfifo_rd_ready      <=      rfifo_rd_ready;
always @(posedge wfifo_rclk or negedge rst_n)
if(rst_n == 1'b0)
flag_rd             <=      1'b0; 
else if(wfifo_rd_count >= WFIFO_RD_CNT)
flag_rd             <=      1'b1;
else
flag_rd             <=      flag_rd;
always @(posedge rfifo_wclk or negedge rst_n)
if(rst_n == 1'b0)
rd_trig             <=      1'b0;
else if(rfifo_wr_count < RFIFO_WR_CNT && flag_rd == 1'b1)
rd_trig             <=      1'b1;
else
rd_trig             <=      1'b0; 
always @(posedge wfifo_rclk or negedge rst_n)
if(rst_n == 1'b0)
wr_trig             <=      1'b0;
else if(wfifo_rd_count >= WFIFO_RD_CNT)
wr_trig             <=      1'b1;
else
wr_trig             <=      1'b0;
//wfifo
fifo_generator_0 wfifo_inst(
.rst                      (~rst_n                     ),                      // input wire rst
.wr_clk                   (wfifo_wclk                 ),                // input wire wr_clk
.rd_clk                   (wfifo_rclk                 ),                // input wire rd_clk
.din                      (wfifo_wr_data              ),                      // input wire [15 : 0] din
.wr_en                    (wfifo_wr_en                ),                  // input wire wr_en
.rd_en                    (wfifo_rd_en                ),                  // input wire rd_en
.dout                     (wfifo_rd_data              ),                    // output wire [15 : 0] dout
.full                     (                           ),                    // output wire full
.empty                    (                           ),                  // output wire empty
.rd_data_count            (wfifo_rd_count             ),  // output wire [10 : 0] rd_data_count
.wr_data_count            (                           )  // output wire [10 : 0] wr_data_count
);
//rfifo
fifo_generator_0 rfifo_inst(
.rst                      (~rst_n                     ),                      // input wire rst
.wr_clk                   (rfifo_wclk                 ),                // input wire wr_clk
.rd_clk                   (rfifo_rclk                 ),                // input wire rd_clk
.din                      (rfifo_wr_data              ),                      // input wire [15 : 0] din
.wr_en                    (rfifo_wr_en                ),                  // input wire wr_en
.rd_en                    (rfifo_rd_en                ),                  // input wire rd_en
.dout                     (rfifo_rd_data              ),                    // output wire [15 : 0] dout
.full                     (                           ),                    // output wire full
.empty                    (                           ),                  // output wire empty
.rd_data_count            (                           ),  // output wire [10 : 0] rd_data_count
.wr_data_count            (rfifo_wr_count             )  // output wire [10 : 0] wr_data_count
);
endmodule

sdram_write模块:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website : 
// Module Name : sdram_write.v
// Create Time : 2020-02-10 20:05:26
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
// 
// *********************************************************************************
module sdram_write(
//System Interfaces
input                   sclk            ,
input                   rst_n           ,
//SDRAM Interfaces
output  reg     [ 3:0]  wr_cmd          ,
output  reg     [11:0]  wr_addr         ,
output  wire    [ 1:0]  bank_addr       ,
output  wire    [15:0]  wr_data         ,     
//Communication Interfaces
input                   wr_trig         ,
input                   wr_en           ,
output  reg             wr_end          ,
output  reg             wr_req          ,
input                   aref_req        ,
output  reg             wfifo_rd_en     ,
input           [15:0]  wfifo_rd_data      
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
parameter  WROW_ADDR_END    =   937         ;
parameter  WCOL_MADDR_END   =   256         ;
parameter  WCOL_FADDR_END   =   512         ;
// Define State
localparam  S_IDLE      =   5'b0_0001       ;
localparam  S_REQ       =   5'b0_0010       ;
localparam  S_ACT       =   5'b0_0100       ;
localparam  S_WR        =   5'b0_1000       ;
localparam  S_PRE       =   5'b1_0000       ;
// SDRAM Command
localparam  CMD_NOP     =   4'b0111         ;
localparam  CMD_PRE     =   4'b0010         ;
localparam  CMD_AREF    =   4'b0001         ;
localparam  CMD_ACT     =   4'b0011         ;
localparam  CMD_WR      =   4'b0100         ;
reg                 [ 4:0]  state           ;
reg                         flag_act_end    ;
reg                         row_end         ;
reg                 [ 1:0]  burst_cnt       ;
reg                         data_end        ;
reg                         flag_row_end    ;
reg                         flag_data_end   ;
reg                         flag_aref_req   ;
reg                 [ 8:0]  col_addr        ;
reg                 [ 1:0]  burst_cnt_r     ;
reg                 [11:0]  row_addr        ;
reg                         data_end_r      ;
reg                         data_end_r2     ;
reg                         row_end_r       ;
reg                         row_end_r2      ; 
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
assign      bank_addr       =       2'b00;
assign      wr_data         =       wfifo_rd_data;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
state           <=      S_IDLE;
else case(state)
S_IDLE    :   if(wr_trig == 1'b1)
state           <=      S_REQ;
else
state           <=      state;                        
S_REQ   :   if(wr_en == 1'b1)
state           <=      S_ACT;
else
state           <=      state;                        
S_ACT   :   if(flag_act_end == 1'b1)
state           <=      S_WR;
else
state           <=      state;                        
S_WR    :   if(data_end_r == 1'b1 || row_end_r == 1'b1)
state           <=      S_PRE;
else if(burst_cnt_r == 2'd2 && aref_req == 1'b1)
state           <=      S_PRE;
else
state           <=      state;                        
S_PRE   :   if(flag_data_end == 1'b1)
state           <=      S_IDLE;
else if(flag_aref_req == 1'b1)
state           <=      S_REQ;
else if(flag_row_end == 1'b1)
state           <=      S_ACT;
else 
state           <=      state;
default :   state           <=      S_IDLE;
endcase
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
flag_aref_req       <=      1'b0;
else if(state == S_PRE && aref_req == 1'b1)
flag_aref_req       <=      1'b1;
else
flag_aref_req       <=      1'b0; 
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
flag_act_end    <=      1'b0;    
else if(state == S_ACT && wr_cmd == CMD_ACT)
flag_act_end    <=      1'b1;
else 
flag_act_end    <=      1'b0; 
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
row_end         <=      1'b0;
else if(col_addr == 9'd508 && burst_cnt == 2'd1)
row_end         <=      1'b1;
else
row_end         <=      1'b0;
always @(posedge sclk)begin
row_end_r   <=      row_end;
row_end_r2  <=      row_end_r;
end
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
burst_cnt       <=      2'd0;
else if(state == S_WR)
burst_cnt       <=      burst_cnt + 1'b1;
else
burst_cnt       <=      2'd0;
always @(posedge sclk)
burst_cnt_r     <=      burst_cnt;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
data_end    <=      1'b0;     
else if(state == S_WR && wr_cmd == CMD_WR && col_addr == WCOL_MADDR_END - 4 && row_addr == WROW_ADDR_END)
data_end    <=      1'b1;
else if((col_addr == 'd252 || col_addr == 508) && burst_cnt == 2'd1)
data_end    <=      1'b1;
else
data_end    <=      1'b0;
always @(posedge sclk)begin
data_end_r      <=      data_end;
data_end_r2     <=      data_end_r;  
end  
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
flag_row_end    <=      1'b0;   
else if(state == S_PRE && row_end_r2 == 1'b1)
flag_row_end    <=      1'b1;
else 
flag_row_end    <=      1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
flag_data_end   <=      1'b0;  
else if(state == S_PRE && data_end_r2 == 1'b1) 
flag_data_end   <=      1'b1;
else
flag_data_end   <=      1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
col_addr        <=      9'd0;
else if(state == S_WR && wr_cmd == CMD_WR && col_addr == WCOL_MADDR_END - 4 && row_addr == WROW_ADDR_END)
col_addr        <=      9'd0;
else if(state == S_WR && wr_cmd == CMD_WR && col_addr == 'd508)
col_addr        <=      9'd0;   
else if(state == S_WR && wr_cmd == CMD_WR)
col_addr        <=      col_addr + 3'd4;
else
col_addr        <=      col_addr;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
row_addr        <=      12'd0;  
else if(state == S_WR && wr_cmd == CMD_WR && col_addr == WCOL_MADDR_END - 4 && row_addr == WROW_ADDR_END)
row_addr        <=      12'd0;
else if(state == S_WR && wr_cmd == CMD_WR && col_addr == 'd508)
row_addr        <=      row_addr + 1'b1;
else
row_addr        <=      row_addr;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
wr_cmd          <=      CMD_NOP;    
else case(state)
S_ACT   :   if(wr_cmd != CMD_ACT && flag_act_end == 1'b0)
wr_cmd          <=      CMD_ACT;
else
wr_cmd          <=      CMD_NOP;
S_WR    :   if(data_end == 1'b1 || row_end == 1'b1)
wr_cmd          <=      CMD_NOP;
else if(burst_cnt_r == 2'd2 && aref_req == 1'b1)
wr_cmd          <=      CMD_NOP;
else if(burst_cnt == 2'd0)
wr_cmd          <=      CMD_WR;
else
wr_cmd          <=      CMD_NOP; 
S_PRE   :   if(wr_cmd != CMD_PRE)
wr_cmd          <=      CMD_PRE;
else 
wr_cmd          <=      CMD_NOP;
default :   wr_cmd          <=      CMD_NOP;
endcase
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
wr_addr         <=      12'd0;    
else case(state)
S_ACT   :   if(wr_cmd != CMD_ACT)
wr_addr         <=      row_addr;
else
wr_addr         <=      12'd0;
S_WR    :   if(data_end == 1'b1 || row_end == 1'b1)
wr_addr         <=      12'd0;
else if(burst_cnt_r == 2'd2 && aref_req == 1'b1)
wr_addr         <=      12'd0;
else if(burst_cnt == 2'd0)
wr_addr         <=      { 
3'b000,col_addr};
else
wr_addr         <=      12'd0; 
S_PRE   :   wr_addr         <=      12'b0100_0000_0000;
default :   wr_addr         <=      12'd0;
endcase
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
wfifo_rd_en     <=      1'b0;    
else if(state == S_WR)
wfifo_rd_en     <=      1'b1;
else
wfifo_rd_en     <=      1'b0;    
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
wr_end          <=      1'b0;   
else if(flag_data_end == 1'b1)
wr_end          <=      1'b1;
else if(state != S_IDLE && flag_aref_req == 1'b1 && wr_end == 1'b0)
wr_end          <=      1'b1;
else
wr_end          <=      1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
wr_req          <=      1'b0;  
else if(wr_en == 1'b1)
wr_req          <=      1'b0;
else if(state == S_REQ)
wr_req          <=      1'b1;
else
wr_req          <=      wr_req;
endmodule

sdram_read模块:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website : 
// Module Name : sdram_read.v
// Create Time : 2020-02-11 20:48:41
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
// 
// *********************************************************************************
module sdram_read(
//System Interfaces
input                   sclk            ,
input                   rst_n           ,
//SDRAM Interfaces
output  reg     [ 3:0]  rd_cmd          ,
output  reg     [11:0]  rd_addr         ,
output  wire    [ 1:0]  bank_addr       ,    
//Communication Interfaces
input                   rd_trig         ,
input                   rd_en           ,
output  reg             rd_end          ,
output  reg             rd_req          ,
input                   aref_req        ,
output  reg             rd_data_en      
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
parameter  RROW_ADDR_END    =   937         ;
parameter  RCOL_MADDR_END   =   256         ;
// Define State
localparam  S_IDLE      =   5'b0_0001       ;
localparam  S_REQ       =   5'b0_0010       ;
localparam  S_ACT       =   5'b0_0100       ;
localparam  S_RD        =   5'b0_1000       ;
localparam  S_PRE       =   5'b1_0000       ;
// SDRAM Command
localparam  CMD_NOP     =   4'b0111         ;
localparam  CMD_PRE     =   4'b0010         ;
localparam  CMD_AREF    =   4'b0001         ;
localparam  CMD_ACT     =   4'b0011         ;
localparam  CMD_RD      =   4'b0101         ;
reg                 [ 4:0]  state           ;
reg                         flag_act_end    ;
reg                         row_end         ;
reg                 [ 1:0]  burst_cnt       ;
reg                         data_end        ;
reg                         flag_row_end    ;
reg                         flag_data_end   ;
reg                         flag_aref_req   ;
reg                 [ 8:0]  col_addr        ;
reg                 [ 1:0]  burst_cnt_r     ;
reg                 [11:0]  row_addr        ;
reg                         data_end_r      ;
reg                         data_end_r2     ;
reg                         row_end_r       ;
reg                         row_end_r2      ; 
reg                         rfifo_wd_en_r1  ;
reg                         rfifo_wd_en_r2  ;
reg                         rfifo_wd_en_r3  ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
assign      bank_addr       =       2'b00;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
state           <=      S_IDLE;
else case(state)
S_IDLE    :   if(rd_trig == 1'b1)
state           <=      S_REQ;
else
state           <=      state;                        
S_REQ   :   if(rd_en == 1'b1)
state           <=      S_ACT;
else
state           <=      state;                        
S_ACT   :   if(flag_act_end == 1'b1)
state           <=      S_RD;
else
state           <=      state;                        
S_RD    :   if(data_end_r == 1'b1 || row_end_r == 1'b1)
state           <=      S_PRE;
else if(burst_cnt_r == 2'd2 && aref_req == 1'b1)
state           <=      S_PRE;
else
state           <=      state;                        
S_PRE   :   if(flag_data_end == 1'b1)
state           <=      S_IDLE;
else if(flag_aref_req == 1'b1)
state           <=      S_REQ;
else if(flag_row_end == 1'b1)
state           <=      S_ACT;
else 
state           <=      state;
default :   state           <=      S_IDLE;
endcase
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
flag_aref_req       <=      1'b0;
else if(state == S_PRE && aref_req == 1'b1)
flag_aref_req       <=      1'b1;
else
flag_aref_req       <=      1'b0; 
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
flag_act_end    <=      1'b0;    
else if(state == S_ACT && rd_cmd == CMD_ACT)
flag_act_end    <=      1'b1;
else 
flag_act_end    <=      1'b0; 
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
row_end         <=      1'b0;
else if(col_addr == 9'd508 && burst_cnt == 2'd1)
row_end         <=      1'b1;
else
row_end         <=      1'b0;
always @(posedge sclk)begin
row_end_r   <=      row_end;
row_end_r2  <=      row_end_r;
end
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
burst_cnt       <=      2'd0;
else if(state == S_RD)
burst_cnt       <=      burst_cnt + 1'b1;
else
burst_cnt       <=      2'd0;
always @(posedge sclk)
burst_cnt_r     <=      burst_cnt;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
data_end    <=      1'b0; 
else if(state == S_RD && rd_cmd == CMD_RD && col_addr == RCOL_MADDR_END - 4 && row_addr == RROW_ADDR_END)
data_end    <=      1'b1;    
else if((col_addr == 'd252 || col_addr == 508) && burst_cnt == 2'd1)
data_end    <=      1'b1;
else
data_end    <=      1'b0;
always @(posedge sclk)begin
data_end_r      <=      data_end;
data_end_r2     <=      data_end_r;  
end  
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
flag_row_end    <=      1'b0;   
else if(state == S_PRE && row_end_r2 == 1'b1)
flag_row_end    <=      1'b1;
else 
flag_row_end    <=      1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
flag_data_end   <=      1'b0;  
else if(state == S_PRE && data_end_r2 == 1'b1) 
flag_data_end   <=      1'b1;
else
flag_data_end   <=      1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
col_addr        <=      12'd0;
else if(state == S_RD && rd_cmd == CMD_RD && col_addr == RCOL_MADDR_END - 4 && row_addr == RROW_ADDR_END)
col_addr        <=      9'd0;
else if(state == S_RD && rd_cmd == CMD_RD && col_addr == 'd508)
col_addr        <=      12'd0;   
else if(state == S_RD && rd_cmd == CMD_RD)
col_addr        <=      col_addr + 3'd4;
else
col_addr        <=      col_addr;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
row_addr        <=      12'd0;  
else if(state == S_RD && rd_cmd == CMD_RD && col_addr == RCOL_MADDR_END - 4 && row_addr == RROW_ADDR_END)
row_addr        <=      12'd0;
else if(state == S_RD && rd_cmd == CMD_RD && col_addr == 'd508)
row_addr        <=      row_addr + 1'b1;
else
row_addr        <=      row_addr;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
rd_cmd          <=      CMD_NOP;    
else case(state)
S_ACT   :   if(rd_cmd != CMD_ACT && flag_act_end == 1'b0)
rd_cmd          <=      CMD_ACT;
else
rd_cmd          <=      CMD_NOP;
S_RD    :   if(data_end == 1'b1 || row_end == 1'b1)
rd_cmd          <=      CMD_NOP;
else if(burst_cnt_r == 2'd2 && aref_req == 1'b1)
rd_cmd          <=      CMD_NOP;
else if(burst_cnt == 2'd0)
rd_cmd          <=      CMD_RD;
else
rd_cmd          <=      CMD_NOP; 
S_PRE   :   if(rd_cmd != CMD_PRE)
rd_cmd          <=      CMD_PRE;
else 
rd_cmd          <=      CMD_NOP;
default :   rd_cmd          <=      CMD_NOP;
endcase
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
rd_addr         <=      12'd0;    
else case(state)
S_ACT   :   if(rd_cmd != CMD_ACT)
rd_addr         <=      row_addr;
else
rd_addr         <=      12'd0;
S_RD    :   if(data_end == 1'b1 || row_end == 1'b1)
rd_addr         <=      12'd0;
else if(burst_cnt_r == 2'd2 && aref_req == 1'b1)
rd_addr         <=      12'd0;
else if(burst_cnt == 2'd0)
rd_addr         <=      { 
3'b000,col_addr};
else
rd_addr         <=      12'd0; 
S_PRE   :   rd_addr         <=      12'b0100_0000_0000;
default :   rd_addr         <=      12'd0;
endcase
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
rd_end          <=      1'b0;   
else if(flag_data_end == 1'b1)
rd_end          <=      1'b1;
else if(state != S_IDLE && flag_aref_req == 1'b1 && rd_end == 1'b0)
rd_end          <=      1'b1;
else
rd_end          <=      1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
rd_req          <=      1'b0;  
else if(rd_en == 1'b1)
rd_req          <=      1'b0;
else if(state == S_REQ)
rd_req          <=      1'b1;
else
rd_req          <=      rd_req;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
rfifo_wd_en_r1  <=      1'b0;    
else if(state == S_RD)
rfifo_wd_en_r1  <=      1'b1;
else
rfifo_wd_en_r1  <=      1'b0;  
always @(posedge sclk)begin
rfifo_wd_en_r2      <=      rfifo_wd_en_r1;
rfifo_wd_en_r3      <=      rfifo_wd_en_r2;
end
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
rd_data_en      <=      1'b0;
else 
rd_data_en      <=      rfifo_wd_en_r3;
endmodule

SDRAM控制器完整的模块代码如上,一共五个模块,其中SDRAM上电初始化、自刷新与前面的模块一摸一样,SDRAM读写模块只是更改了一小部分内容,又在前面基础上添加了sdram_auto_write_read自动读写模块。

SDRAM控制器的测试代码

这里我们给出顶层测试模块的代码,如下:

`timescale 1ns / 1ps
`define CLOCK    10
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website : 
// Module Name : sdram_init_tb.v
// Create Time : 2020-02-09 17:10:08
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
// 
// *********************************************************************************
module sdram_init_tb;
reg                         sclk            ;
reg                         clk_50m         ;
reg                         rst_n           ;
wire                        sdram_clk       ;
wire                        sdram_cke       ;
wire                        sdram_cs_n      ;
wire                        sdram_cas_n     ;
wire                        sdram_ras_n     ;
wire                        sdram_we_n      ;
wire    [ 1:0]              sdram_bank      ;
wire    [11:0]              sdram_addr      ;
wire    [ 1:0]              sdram_dqm       ;
wire    [15:0]              sdram_dq        ;
reg                         wfifo_wr_en     ;
reg    [15:0]               wfifo_wr_data   ;
wire   [15:0]               rfifo_rd_data   ;
wire                        rfifo_rd_ready  ;
reg    [15:0]               rfifo_test_data ; 
reg    [20:0]               err_cnt         ;
reg                         rfifo_rd_en     ;
initial begin
sclk        =       1'b0;
rst_n       <=      1'b0;
#(200*`CLOCK)
rst_n       <=      1'b1;
end
always  #(`CLOCK/2)     sclk        =       ~sclk; 
initial begin
clk_50m     =       1'b0;
wfifo_wr_en <=      1'b0;
rfifo_rd_en <=      1'b0;
#(250_000)
wfifo_wr_en <=      1'b1;
#(5_000_000)
rfifo_rd_en <=      1'b1;
#(459_852_690-250_000);
wfifo_wr_en <=      1'b0;
rfifo_rd_en <=      1'b0;
// #(9_863_860-250_000);
// wfifo_wr_en <= 1'b0;
// rfifo_rd_en <= 1'b1;
end
always  #(`CLOCK*5)       clk_50m      =       ~clk_50m; 
always @(posedge clk_50m or negedge rst_n)
if(rst_n == 1'b0)
wfifo_wr_data       <=      16'd0;
else if(wfifo_wr_en == 1'b1)
wfifo_wr_data       <=      wfifo_wr_data + 1'b1;
else
wfifo_wr_data       <=      wfifo_wr_data;
always @(posedge clk_50m or negedge rst_n)
if(rst_n == 1'b0)
rfifo_test_data      <=      16'd0; 
else if(rfifo_rd_en == 1'b1)
rfifo_test_data     <=      rfifo_test_data + 1'b1;
else
rfifo_test_data     <=      rfifo_test_data;
always @(posedge clk_50m or negedge rst_n)
if(rst_n == 1'b0)
err_cnt             <=      21'd0;
else if(rfifo_rd_en == 1'b1 && rfifo_test_data != rfifo_rd_data) 
err_cnt             <=      err_cnt + 1'b1;
else
err_cnt             <=      err_cnt;         
sdram_top sdram_top_inst(
//System Interfaces
.sclk                   (sclk                   ),
.rst_n                  (rst_n                  ),
//SDRAM Interfaces
.sdram_clk              (sdram_clk              ),
.sdram_cke              (sdram_cke              ),
.sdram_cs_n             (sdram_cs_n             ),
.sdram_cas_n            (sdram_cas_n            ),
.sdram_ras_n            (sdram_ras_n            ),
.sdram_we_n             (sdram_we_n             ),
.sdram_bank             (sdram_bank             ),
.sdram_addr             (sdram_addr             ),
.sdram_dqm              (sdram_dqm              ),
.sdram_dq               (sdram_dq               ),
//User Interfaces
.wfifo_wclk             (clk_50m                ),
.wfifo_wr_en            (wfifo_wr_en            ),
.wfifo_wr_data          (wfifo_wr_data          ),
.rfifo_rclk             (clk_50m                ),
.rfifo_rd_en            (rfifo_rd_en            ),
.rfifo_rd_data          (rfifo_rd_data          ),
.rfifo_rd_ready         (rfifo_rd_ready         )
);
defparam        sdram_model_plus_inst.addr_bits =       12;
defparam        sdram_model_plus_inst.data_bits =       16;
defparam        sdram_model_plus_inst.col_bits  =       9;
defparam        sdram_model_plus_inst.mem_sizes =       2*1024*1024;            // 2M
sdram_model_plus sdram_model_plus_inst(
.Dq                     (sdram_dq               ), 
.Addr                   (sdram_addr             ), 
.Ba                     (sdram_bank             ), 
.Clk                    (sdram_clk              ), 
.Cke                    (sdram_cke              ), 
.Cs_n                   (sdram_cs_n             ), 
.Ras_n                  (sdram_ras_n            ), 
.Cas_n                  (sdram_cas_n            ), 
.We_n                   (sdram_we_n             ), 
.Dqm                    (sdram_dqm              ),
.Debug                  (1'b1                   )
);
endmodule

测试模型的代码,我们为了简单起见不再给出,有需要的同学可以去前面的文章中自取。

仿真结果

在这里插入图片描述
细看我们的测试模块,我们编写的是循环测试的代码,运行了一段时间后,err_cnt依旧是0,证明了我们模块设计的正确性。

总结

创作不易,认为文章有帮助的同学们可以关注点赞支持。(工程也都在群中)对文章有什么看法或者需要更近一步交流的同学,可以加入下面的群:
在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/129040.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • Hadoop、Yarn和vcpu资源的配置

    Hadoop、Yarn和vcpu资源的配置

  • Python字符串操作之字符串分割与组合「建议收藏」

    Python字符串操作之字符串分割与组合「建议收藏」12、字符串的分割和组合str.split():字符串分割函数通过指定分隔符对字符串进行切片,并返回分割后的字符串列表。语法:os.path.split():路径文件分割函数join(seq):将序列组合成字符串函数

  • 【ztree系列】树节点的模糊查询

    【ztree系列】树节点的模糊查询以前设计模糊查询的功能,一般都是针对表格来做的,还真没考虑过对tree进行模糊查询,也可能是因为遇到的数据量还没到头疼的程度吧。为了完美的实现模糊查询的效果,搞了半天css,对输入框显示效果的设置更是修改了n多次,什么半圆角、边框、光影。。。真佩服我这颗屡试屡换的小心脏啊一、页面设计对于搜索功能,首先要有输入框,用于接收输入内容;然后就是显示搜索结果用的标签,控制焦点用的上移下动按钮。其实

  • Linux设备树详解(一) 基础知识

    Linux设备树详解(一) 基础知识1.前言关于设备树,之前就经过详细的系统培训,但是本着会用就行的原则,对各个知识点都没有进行系统的总结。都是用到哪里学哪里,时间长了,基本也忘记了。所以对于后期知识各个知识点进行总结。2.为什么要引入DTS在传统Linux内核中,ARM架构的板极硬件细节过多地被硬编码在arch/arm/plat-xxx和arch/arm/mach-xxx,比如板上的platform设备、resource…

  • hive、hadoop面试题

    hive、hadoop面试题有如下hive记录表records,记录车辆的过车信息:createtablerecords(idstring,//记录编号indatestring,//过车记录时间plate_nostring,//车辆号牌device_idint,//经过的设备编号)partitionedby(monthstring,daystring)rowformatdelimitedfieldsterminatedby’\t’storedasORC;1…

  • vi常用命令

    vi常用命令[toc]一、关于vi==========vi是最强大的文本编辑器,没有之一。尽管vi已经是古董级的软件,但还是有无数新人迎着困难去学习,可见其经典与受欢迎的程度。无论是小说中还是电视剧,真

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号