使用FPGA读写SDRAM,SDRAM跑100M时钟

使用FPGA读写SDRAM,SDRAM跑100M时钟

author:ANGRY_KUA_MAX

QQ     :2518383357

Time  :2018-07-23

淘宝   : https://item.taobao.com/item.htm?spm=a230r.1.14.19.19b35e63Ew9sFv&id=574113974305&ns=1&abbucket=14#detail

作者承接FPGA工程项目,单片机项目开发,付费解决各种疑难杂症。

 

 

作者亲自调试编写,并进行长时间测试,无Bug,Sdram为256Mbit,HY57V281620ETP-H,也可以兼容128Mbit,管脚变更后直接使用即可;

程序读写均采用Fifo方式,读写完均可以通过状态查看,速度基本可以保证100M*16bit速度。

工程模块接口如下:

module SDRAM_Project

(

//global clock 50MHz

input      clk,                                //50MHz

input      rst_n, //global reset

input      key1,

output    led,

//sdram control

output     sdram_clk, //sdram clock

output     sdram_cke, //sdram clock enable

output     sdram_cs_n, //sdram chip select

output     sdram_we_n, //sdram write enable

output     sdram_cas_n, //sdram column address strobe

output     sdram_ras_n, //sdram row address strobe

output [1:0]   sdram_dqm, //sdram data enable

output [1:0]   sdram_ba, //sdram bank address

output [12:0]  sdram_addr, //sdram address

inout   [15:0] sdram_data,  //sdram data

);

 

工程测试,从指定地址写入数据,然后读出来,若读写数据不一样,则停止操作,并将将状态变更为错误状态:

 

always @(posedge clk_ref or negedge sys_rst_n)

  if(!sys_rst_n) begin

    sdram_wrdata  <=  0;

    sdram_wrreq   <=  0;

    sdram_wrstate <=  0;

    sdram_wrcount <=  0;

    sdram_teststate <= 0;

    sdram_rdreq   <=  0;

    RD_ENABLE     <=  0;

    RD_ADDR       <=  0;

    WR_ADDR       <=  0;

    end

  else begin

    if((!key1)& (sdram_teststate == STATE_IDLE)) begin

      sdram_teststate <=  STATE_WR;  

      sdram_wrdata  <=  0;

      sdram_wrcount <=  0;

      WR_ADDR       <=  10;

      RD_ADDR       <=  10;

      end

    else begin

      case (sdram_teststate)

      STATE_WR: begin

        sdram_teststate <= sys_empty?STATE_WREND:sdram_teststate;

        sdram_wrcount <=  0;

        RD_ENABLE     <=  0;

        end

      STATE_WREND: begin

        if(sdram_wrcount == WRLEN) begin

          sdram_wrreq   <=  1'd0;

          if(WR_FINISHED) begin

            sdram_teststate <=  STATE_RD;

            RD_ENABLE     <=  1'd1;

            sdram_rdcount <=  0;

            sdram_wrdata  <=  0;

            end

          end

        else begin

          sdram_wrreq   <=  1'd1;

          sdram_wrcount <=  sdram_wrcount + 1'd1;

          sdram_wrdata  <=  sdram_wrdata + 1'd1;

          end

        end

      STATE_RD:  begin

          RD_ENABLE       <= (RD_USIZE != 0)?1'd0:RD_ENABLE;

          sdram_teststate <= (RD_USIZE != 0)?STATE_RDEND:sdram_teststate;

          end

      STATE_RDEND: begin

          if(sdram_rdcount == WRLEN) begin

            if(RD_USIZE == 0) begin

              sdram_teststate <=  STATE_WR;

              end

            sdram_rdreq   <=  1'd0;

            end

          else begin

            sdram_rdreq   <=  1'd1;

            sdram_rdcount <=  sdram_rdcount + 1'd1;

            if((sdram_rdcount != sys_data_out) && sdram_rdreq) begin

              sdram_teststate <=  STATE_ERR;

              end

            end

          end

      default:;

      endcase

      end

end

 

SDRAM例化的模块接口

 

 Sdram_Control_2Port u_Sdram_Control_2Port

(

// HOST Side

.REF_CLK        (clk_ref),      //100M,sdram module clock       

.OUT_CLK        (clk_refout),      //100M,sdram clock input

.RESET_N        (sys_rst_n),      //sdram module reset

 

// SDRAM Side,管脚接口

.SDR_CLK           (sdram_clk),      //sdram clock

.CKE          (sdram_cke),      //sdram clock enable

.CS_N                   (sdram_cs_n),      //sdram chip select

.WE_N                  (sdram_we_n),      //sdram write enable

.CAS_N                 (sdram_cas_n),    //sdram column address strobe

.RAS_N           (sdram_ras_n),    //sdram row address strobe

.DQM                    (sdram_dqm),      //sdram data output enable

.BA                       (sdram_ba),      //sdram bank address

.SA                         (sdram_addr),      //sdram address

.DQ                        (sdram_data),      //sdram data

.Sdram_Init_Done    (sdram_init_done)  //SDRAM init done signal

// FIFO Write Side

.WR_CLK               (clk_write),      //write fifo clock

.WR_RESET                (!sys_rst_n),    //write register load & fifo clear

.WR_DATA                 (sys_data_in),    //write data input

.WR                           (sys_we),        //write data request

.WR_ADDR                 (WR_ADDR),        //write start address

.WR_LENGTH              (WRLEN),        //write burst length

.WR_EMPTY                (sys_empty),

.WR_FINISHED            (WR_FINISHED),

// FIFO Read Side

.RD_CLK        (clk_read),      //read fifo clock

.RD_ENABLE               (RD_ENABLE),

.RD_RESET        (!sys_rst_n),    //read fifo clear

 

.RD_DATA                 (sys_data_out),    //read data output

.RD                           (sys_rd),        //read request

.RD_ADDR                (RD_ADDR),        //read start address

.RD_LENGTH             (WRLEN),        //read length

.RD_USIZE                (RD_USIZE) //

);

 

//状态指示灯/

reg [26:0]  led_count; 

reg            led_run;

 

always @(posedge clk_ref or negedge sys_rst_n)

  if(!sys_rst_n) begin

    led_count <=  0;

    led_run   <=  0;

    end

  else begin

    if((led_count >= 99999999 && sdram_teststate != STATE_IDLE) || (sdram_teststate ==  STATE_ERR && led_count >= 4999999)) begin

      led_count <=  0;

      led_run   <=  !led_run;

      end

    else begin

      led_count <= led_count + 1'd1;

      end

    end

 

assign led = led_run;

 

***********华丽风隔线******************

 

对初次使用SDRAM的工程师或者学生,可以具有非常不错的参考价值,作者可以手把手教使用signal tap抓取程序读写数据,分析程序逻辑。

 

 

 

 

 

 

你可能感兴趣的:(随手log)