基于FPGA完整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 Interfacesinput                   sclk            ,input                   rst_n           ,//SDRAM Interfacesoutput  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 Interfacesinput                   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;elsestate           <=      state;AREF    :   if(aref_end == 1'b1)state           <=      ARBIT;elsestate           <=      state;WRITE   :   if(wr_end == 1'b1)state           <=      ARBIT;else state           <=      state;READ    :   if(rd_end == 1'b1)state           <=      ARBIT;elsestate           <=      state;                        default :   state           <=      IDLE;endcasealways @(*)case(state)IDLE    :   beginsdram_addr      =      init_addr;{sdram_cs_n, sdram_ras_n, sdram_cas_n, sdram_we_n}      =       init_cmd;sdram_dq_en     =       1'b0;endAREF    :   beginsdram_addr      =      aref_addr;{sdram_cs_n, sdram_ras_n, sdram_cas_n, sdram_we_n}      =       aref_cmd;endWRITE   :   beginsdram_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;endREAD    :   beginsdram_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;  enddefault :   beginsdram_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;endendcasealways @(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;elsearef_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;elsewr_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;elserd_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 Interfacesinput                   sclk            ,input                   rst_n           ,//SDRAM Interfacesoutput  reg     [ 3:0]  sdram_cmd       ,output  reg     [11:0]  sdram_addr      ,//Othersoutput  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;elsecnt_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;elseflag_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;endcasealways @(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;elsesdram_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;elseinit_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 Interfacesinput                   sclk            ,input                   rst_n           ,//SDRAM Interfacesoutput  reg     [ 3:0]  aref_cmd        ,output  wire    [11:0]  aref_addr       ,//Othersinput                   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;elsearef_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;endcasealways @(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;elsearef_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;elsecnt_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;elsearef_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 signalsinput                   rst_n                   ,       // wfifoinput                   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                 ,// rfifoinput                   rfifo_wclk              ,       // 100MHzinput                   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 interfacesoutput  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;elserfifo_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;elseflag_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;elserd_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;elsewr_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 Interfacesinput                   sclk            ,input                   rst_n           ,//SDRAM Interfacesoutput  reg     [ 3:0]  wr_cmd          ,output  reg     [11:0]  wr_addr         ,output  wire    [ 1:0]  bank_addr       ,output  wire    [15:0]  wr_data         ,     //Communication Interfacesinput                   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;elsestate           <=      state;                        S_REQ   :   if(wr_en == 1'b1)state           <=      S_ACT;elsestate           <=      state;                        S_ACT   :   if(flag_act_end == 1'b1)state           <=      S_WR;elsestate           <=      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;elsestate           <=      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;endcasealways @(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;elseflag_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;elserow_end         <=      1'b0;always @(posedge sclk)beginrow_end_r   <=      row_end;row_end_r2  <=      row_end_r;
endalways @(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;elseburst_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;elsedata_end    <=      1'b0;always @(posedge sclk)begindata_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;elseflag_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;elsecol_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;elserow_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;elsewr_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;elsewr_cmd          <=      CMD_NOP; S_PRE   :   if(wr_cmd != CMD_PRE)wr_cmd          <=      CMD_PRE;else wr_cmd          <=      CMD_NOP;default :   wr_cmd          <=      CMD_NOP;endcasealways @(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;elsewr_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};elsewr_addr         <=      12'd0; S_PRE   :   wr_addr         <=      12'b0100_0000_0000;default :   wr_addr         <=      12'd0;endcasealways @(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;elsewfifo_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;elsewr_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;elsewr_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 Interfacesinput                   sclk            ,input                   rst_n           ,//SDRAM Interfacesoutput  reg     [ 3:0]  rd_cmd          ,output  reg     [11:0]  rd_addr         ,output  wire    [ 1:0]  bank_addr       ,    //Communication Interfacesinput                   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;elsestate           <=      state;                        S_REQ   :   if(rd_en == 1'b1)state           <=      S_ACT;elsestate           <=      state;                        S_ACT   :   if(flag_act_end == 1'b1)state           <=      S_RD;elsestate           <=      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;elsestate           <=      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;endcasealways @(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;elseflag_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;elserow_end         <=      1'b0;always @(posedge sclk)beginrow_end_r   <=      row_end;row_end_r2  <=      row_end_r;
endalways @(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;elseburst_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;elsedata_end    <=      1'b0;always @(posedge sclk)begindata_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;elseflag_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;elsecol_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;elserow_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;elserd_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;elserd_cmd          <=      CMD_NOP; S_PRE   :   if(rd_cmd != CMD_PRE)rd_cmd          <=      CMD_PRE;else rd_cmd          <=      CMD_NOP;default :   rd_cmd          <=      CMD_NOP;endcasealways @(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;elserd_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};elserd_addr         <=      12'd0; S_PRE   :   rd_addr         <=      12'b0100_0000_0000;default :   rd_addr         <=      12'd0;endcasealways @(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;elserd_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;elserd_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;elserfifo_wd_en_r1  <=      1'b0;  always @(posedge sclk)beginrfifo_wd_en_r2      <=      rfifo_wd_en_r1;rfifo_wd_en_r3      <=      rfifo_wd_en_r2;
endalways @(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 beginsclk        =       1'b0;rst_n       <=      1'b0;#(200*`CLOCK)rst_n       <=      1'b1;
end
always  #(`CLOCK/2)     sclk        =       ~sclk; initial beginclk_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;elsewfifo_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;elserfifo_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;elseerr_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;            // 2Msdram_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,证明了我们模块设计的正确性。

总结

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

基于FPGA的SDRAM控制器设计(4)相关推荐

  1. 基于FPGA的SDRAM控制器设计(二)

    基于FPGA的SDRAM控制器设计(二) 1. SDRAM理论基础 2. SDRAM初始化模块以及仿真 3.TOP模块的仲裁机制 4. SDRAM刷新模块代码以及仿真 5.代码 6.参考资料 1. S ...

  2. 基于FPGA的SDRAM控制器设计(1)

    基于FPGA的SDRAM初始化配置 SDRAM简述 SDRAM的引脚及作用 SDRAM初始化时序控制 SDRAM上电时序代码 SDRAM测试模块的代码 仿真测试结果 参考文献 总结 SDRAM简述 S ...

  3. 基于FPGA的SDRAM控制器设计(2)

    基于FPGA的SDRAM的自刷新操作 SDRAM自刷新简述 SDRAM自刷新时序图 SDRAM自刷新代码 仿真模块的代码 仿真结果测试 参考文献 总结 SDRAM自刷新简述 SDRAM作为一个RAM并 ...

  4. 基于FPGA的SDRAM控制器设计(一)----------SDRAM初始化

    本文设计思路与讲解于参考邓堪文老师的视频,感谢-(不太适合一点基础都没有的小白) SDRAM简介 SDRAM(synchronous Dynamic Random ),同步动态随机存储器,同步指内存工 ...

  5. FPGA之SDRAM控制器设计(三)

    FPGA之SDRAM控制器设计(三):写 由于已经涉及了上电刷新,写三个大的状态转移,先把状态转移图给出.主控状态转移图是基于手册上描述来的.在代码注释中会给出每个状态的意义解释. 写时序图 写状态转 ...

  6. 基于 FPGA 的 UART 控制器设计(VHDL)(下)

    今天给大侠带来基于FPGA的 UART 控制器设计(VHDL)(下),由于篇幅较长,分三篇.今天带来第三篇,下篇,使用 FPGA 实现 UART.话不多说,上货. 之前有关于 Veriliog HDL ...

  7. 七、基于FPGA的Flash控制器设计

    根据项目需求,设计一个Flash控制器.以便将完成低速数据的存储.Flash选用了S25FL032.使用单线SPI接口,接线如图: 1,Flash S25fl032介绍 1.1 IO描述 1.2 相关 ...

  8. 基于FPGA的PID控制器设计

    1 知识背景 PID控制应该算是应用非常广泛的控制算法了.常见的比如控制环境温度,控制无人机飞行高度速度等.PID我们将其分成三个参数,如下: P-比例控制,基本作用就是控制对象以线性的方式增加,在一 ...

  9. 基于FPGA的以太网控制器(MAC)设计(中)

    今天给大侠带来基于FPGA的以太网控制器(MAC)设计,由于篇幅较长,分三篇.今天带来第二篇,中篇,以太网控制器(MAC)程序的实现.话不多说,上货. 导读 当前,互联网已经极大地改变了我们的生产和生 ...

  10. 基于FPGA的以太网控制器(MAC)设计(下)

    今天给大侠带来基于FPGA的以太网控制器(MAC)设计,由于篇幅较长,分三篇.今天带来第三篇,下篇,程序的仿真与测试和总结.话不多说,上货. 导读 当前,互联网已经极大地改变了我们的生产和生活.与之相 ...

最新文章

  1. WiresShark 使用方法
  2. 应用Java程序片段动态生成下拉列表
  3. 改造消费方解决地址硬编码问题
  4. flink-jdbc-driver和flink-sql-gateway的作用
  5. 博客园代码黑色主题高亮设置
  6. 那些地方会用C语言多线程,如何用C语言实现多线程
  7. Sharepoint 2013默认dll部署位置
  8. 内部存储_Mongodb存储特性与内部原理
  9. 快速开发基于 HTML5 网络拓扑图应用--入门篇(一)
  10. 安装配置Greenplum
  11. zabbix自定义SNMP监控项
  12. 图像处理之对BMP图片的认识
  13. css绘制一个动态雷达图
  14. 使用计算机辅助翻译,计算机辅助翻译方法
  15. Android Studio系统盘瘦身
  16. cad怎么画立体图形教学_怎么在CAD中绘制三维立体图
  17. i9 10900k和i7 9700k的区别大吗
  18. API管理平台,管理企业所有API资产
  19. uniApp和微信小程序好看的我的页面(有源码)
  20. windows 定时任务:schtasks,定时关闭网易云音乐

热门文章

  1. swconfig iwpriv iwinfo iwlist iwconfig
  2. Matlab Coder将m文件转换成C/C++
  3. mysql间隙锁_mysql的间隙锁
  4. 小波去噪程序c语言,小波去噪c语言程序
  5. LaTeX 绘制思维导图
  6. 5G啊5G,你是不是只比4G多一G?
  7. Ruby语言入门之Hello world
  8. 2019最新《web前端课程+项目实践课程》高清无拼凑
  9. android dagger2 讲解,dagger 2 详解
  10. 计算机本科毕设答辩经验