• FPGA 基于ISE的USB芯片写入DDR的数据处理方法(9)


             上一节已经成功地测试了DDR的各个链路以及各个地址的读写操作,这一节就来完成模拟从PC端发出数据经过USB最终给到DDR端口,之前已经实现了DDR的各个链路的验证,同时也实现了数据的读写。先看一下本次实验要实现的链路结构。

    框图:

      

         在之前的文章中已经指出,我们所做的实验USB的写入和读出的数据宽度为16bit,但是我们所i设计的DDR的突发长度为64,,两者的数据宽度不一致,如果是直接这样使用的话会导致DDR的高48bit的浪费,所以要先把usb端输出的16bit的数据宽度,通过拼接的方法拼接城64bit 的宽度再发送到DDR中。 

    USB端数据拼接的时序设计:

     USB端数据拼接的代码:

     1 // *********************************************************************************
     2 // Project Name : OSXXXX
     3 // Author       : 李国勇
     4 // weixin       : li15226499835
     5 // Website      : https://www.cnblogs.com/lgy-gdeu/
     6 // Create Time  : 2019-10-30
     7 // File Name    : .v
     8 // Module Name  : 
     9 // Called By    :
    10 // Abstract     :
    11 //
    12 // CopyRight(c) 2018, OpenSoc Studio.. 
    13 // All Rights Reserved
    14 //
    15 // *********************************************************************************
    16 // Modification History:
    17 // Date         By              Version                 Change Description
    18 // -----------------------------------------------------------------------
    19 // 2019/10/30   李国勇           1.0                     Original
    20 //  
    21 // *********************************************************************************
    22 `timescale      1ns/1ns
    23 
    24 module  usb_read(
    25         // system signals
    26         input                   s_rst_n                 ,       
    27         // system signals
    28         input                   usb_ifclk               ,       
    29         input                   usb_full                ,       
    30         input                   usb_empty               ,       
    31         output  wire            usb_slcs                ,       
    32         output  wire            usb_slwr                ,       
    33         output  wire            usb_slrd                ,       
    34         output  wire            usb_sloe                ,       
    35         output  wire    [ 1:0]  usb_fifoadr             ,
    36         input           [15:0]  usb_fdata               ,
    37         // User Data
    38         output  reg             usb_wr_en               ,
    39         output  reg     [63:0]  usb_wr_data             
    40 );
    41 
    42 //========================================================================
    43 // =========== Define Parameter and Internal signals =========== 
    44 //========================================================================/
    45 
    46 reg                             usb_slrd_reg                    ;   
    47 reg     [ 1:0]                  data_cnt                        ;
    48     
    49 
    50 //=============================================================================
    51 //**************    Main Code   **************
    52 //=============================================================================
    53 assign  usb_slcs        =       1'b0;
    54 assign  usb_slrd        =       (usb_empty == 1'b1 && usb_slrd_reg == 1'b0) ? 1'b0 : 1'b1;
    55 assign  usb_slwr        =       1'b1;
    56 assign  usb_sloe        =       1'b0;
    57 assign  usb_fifoadr     =       2'b00;  // 2,4,6,8
    58 
    59 
    60 always  @(posedge usb_ifclk or negedge s_rst_n) begin
    61         if(s_rst_n == 1'b0)
    62                 usb_slrd_reg    <=      1'b1;
    63         else if(usb_empty == 1'b1)
    64                 usb_slrd_reg    <=      1'b0;
    65         else 
    66                 usb_slrd_reg    <=      1'b1;
    67 end
    68 
    69 always  @(posedge usb_ifclk or negedge s_rst_n) begin
    70         if(s_rst_n == 1'b0)
    71                 usb_wr_data     <=       64'h0;
    72         else if(usb_slrd == 1'b0)
    73                 usb_wr_data     <=      {usb_wr_data[47:0], usb_fdata};
    74 end
    75 
    76 always  @(posedge usb_ifclk or negedge s_rst_n) begin
    77         if(s_rst_n == 1'b0)
    78                 data_cnt        <=      'd0;
    79         else if(usb_slrd == 1'b0)
    80                 data_cnt        <=      data_cnt + 1'b1;
    81 end
    82 
    83 always  @(posedge usb_ifclk or negedge s_rst_n) begin
    84         if(s_rst_n == 1'b0)
    85                 usb_wr_en       <=      1'b0;
    86         else if(usb_slrd == 1'b0 && data_cnt == 'd3)
    87                 usb_wr_en       <=      1'b1;
    88         else
    89                 usb_wr_en       <=      1'b0;
    90 end
    91 
    92 endmodule

           那么处理完USB端的数据位宽的问题了,接下来就是DDR的驱动端吧,在之前的学习中我们就已经了解到,在DDR开始写入数据的时候,必须已经有数据存在书存储端了,不然一开始就给DDR写数据的命令的话,容易造成对数据的读空。所以还是按照之前的时序来给DDR的系数据命令。

    DDR端的时序图:

     我在本次实验中准备传递一幅640*480的图片,一个像素点是16bit,

                 total:480*640=307200

                 突发次数:307200/4/16=4800

    DDR端的数据处理代码:

     1 module  ddr3_drive(
     2         // system signals
     3         input                   wr_clk                  ,       
     4         input                   s_rst_n                 ,       
     5         // DDR3 User Interfaces
     6         input                   p0_wr_en                ,
     7         output  reg             p0_cmd_en               ,       
     8         output  wire    [ 2:0]  p0_cmd_instr            ,       
     9         output  wire    [ 5:0]  p0_cmd_bl               ,       
    10         output  reg     [29:0]  p0_byte_addr            , 
    11         output  wire    [ 7:0]  p0_wr_mask              ,       
    12         output  reg             p1_cmd_en               ,       
    13         output  wire    [ 2:0]  p1_cmd_instr            ,       
    14         output  wire    [ 5:0]  p1_cmd_bl               ,       
    15         output  reg     [29:0]  p1_byte_addr            ,
    16         output  reg             p1_rd_en                ,       
    17         input           [63:0]  p1_rd_data                            
    18 );
    19 
    20 //========================================================================
    21 // =========== Define Parameter and Internal signals =========== 
    22 //========================================================================/
    23 localparam      BURST_END       =       'd10                    ;
    24 // localparam      BURST_END       =       4800                    ;
    25 
    26 reg     [ 3:0]                  wr_cnt                          ;
    27 reg     [15:0]                  wr_bl_cnt                       ;
    28 
    29 //=============================================================================
    30 //**************    Main Code   **************
    31 //=============================================================================
    32 assign  p0_cmd_instr    =       3'b000;
    33 assign  p0_cmd_bl       =       'd15;
    34 assign  p0_wr_mask      =       8'h0;
    35 assign  p1_cmd_instr    =       3'b001;
    36 assign  p1_cmd_bl       =       'd15;
    37 
    38 always  @(posedge wr_clk or negedge s_rst_n) begin
    39         if(s_rst_n == 1'b0)
    40                 wr_cnt  <=      'd0;
    41         else if(p0_wr_en == 1'b1)
    42                 wr_cnt  <=      wr_cnt + 1'b1;
    43 end
    44 
    45 always  @(posedge wr_clk or negedge s_rst_n) begin
    46         if(s_rst_n == 1'b0)
    47                 p0_cmd_en       <=      1'b0;
    48         else if(p0_wr_en == 1'b1 && wr_cnt == 'd15)
    49                 p0_cmd_en       <=      1'b1;
    50         else
    51                 p0_cmd_en       <=      1'b0;
    52 end
    53 
    54 always  @(posedge wr_clk or negedge s_rst_n) begin
    55         if(s_rst_n == 1'b0)
    56                 p0_byte_addr    <=      'd0;
    57         else if(p0_cmd_en == 1'b1 && wr_bl_cnt >= (BURST_END-1))
    58                 p0_byte_addr    <=      'd0;
    59         else if(p0_cmd_en == 1'b1)
    60                 p0_byte_addr    <=      p0_byte_addr + 'd128;        
    61 end
    62 
    63 always  @(posedge wr_clk or negedge s_rst_n) begin
    64         if(s_rst_n == 1'b0)
    65                 wr_bl_cnt       <=      'd0;
    66         else if(p0_cmd_en == 1'b1 && wr_bl_cnt >= (BURST_END-1))
    67                 wr_bl_cnt       <=      'd0;
    68         else if(p0_cmd_en == 1'b1)
    69                 wr_bl_cnt       <=      wr_bl_cnt + 1'b1;
    70 end
    71 
    72 endmodule

       在联调的时候注意时钟的统一,有问题欢迎微信一起探讨:

     

    总体的代码:

    TB:

      1 `timescale      1ps/1ps
      2 
      3 module  tb_top;
      4 
      5 parameter C3_MEMCLK_PERIOD     = 20000;
      6 
      7 
      8 reg             ddr3_ref_clk;
      9 reg             usb_ifclk;
     10 reg             ddr3_rst_n;
     11 wire            c3_calib_done;
     12 reg             wr_trig;
     13 wire            usb_slrd;
     14 reg     [15:0]  usb_fdata;
     15 
     16 
     17 initial begin
     18         ddr3_ref_clk    =       1;
     19         usb_ifclk       =       1;
     20         ddr3_rst_n      <=      0;
     21         #20000;
     22         ddr3_rst_n      <=      1;
     23 end
     24 
     25 initial begin
     26         wr_trig <=      0;
     27         @(posedge c3_calib_done)
     28         #100000
     29         wr_trig <=      1;
     30         #25600
     31         wr_trig <=      0;
     32 end
     33 
     34 always  #(C3_MEMCLK_PERIOD/2)   ddr3_ref_clk    =       ~ddr3_ref_clk;
     35 always  #(C3_MEMCLK_PERIOD/2)   usb_ifclk       =       ~usb_ifclk;
     36 
     37 always  @(posedge usb_ifclk or negedge ddr3_rst_n) begin
     38         if(ddr3_rst_n == 1'b0)
     39                 usb_fdata       <=      'd0;
     40         else if(usb_slrd == 1'b0)
     41                 usb_fdata       <=      usb_fdata + 1'b1;
     42 end
     43 
     44 wire    [15:0]  mcb3_dram_dq            ;       
     45 wire    [12:0]  mcb3_dram_a             ;       
     46 wire    [2:0]   mcb3_dram_ba            ;       
     47 wire            mcb3_dram_ras_n         ;       
     48 wire            mcb3_dram_cas_n         ;       
     49 wire            mcb3_dram_we_n          ;       
     50 wire            mcb3_dram_odt           ;       
     51 wire            mcb3_dram_reset_n       ;       
     52 wire            mcb3_dram_cke           ;       
     53 wire            mcb3_dram_ck            ;       
     54 wire            mcb3_dram_ck_n          ;    
     55 wire            mcb3_dram_dm            ;       
     56 wire            mcb3_dram_udqs          ;       
     57 wire            mcb3_dram_udqs_n        ;       
     58 wire            mcb3_dram_dqs           ;       
     59 wire            mcb3_dram_dqs_n         ;       
     60 wire            mcb3_rzq                ;       
     61 wire            mcb3_zio                ;       
     62 wire            mcb3_dram_udm           ;      
     63 
     64 top             top_inst(
     65         // system signals
     66         .c3_sys_clk             (ddr3_ref_clk           ),       
     67         .c3_sys_rst_i           (ddr3_rst_n             ),       
     68         // DDR3 Interfaces
     69         .mcb3_dram_dq            (mcb3_dram_dq           ),       
     70         .mcb3_dram_a             (mcb3_dram_a            ),       
     71         .mcb3_dram_ba            (mcb3_dram_ba           ),       
     72         .mcb3_dram_ras_n         (mcb3_dram_ras_n        ),       
     73         .mcb3_dram_cas_n         (mcb3_dram_cas_n        ),       
     74         .mcb3_dram_we_n          (mcb3_dram_we_n         ),       
     75         .mcb3_dram_odt           (mcb3_dram_odt          ),       
     76         .mcb3_dram_reset_n       (mcb3_dram_reset_n      ),       
     77         .mcb3_dram_cke           (mcb3_dram_cke          ),       
     78         .mcb3_dram_ck            (mcb3_dram_ck           ),       
     79         .mcb3_dram_ck_n          (mcb3_dram_ck_n         ),    
     80         .mcb3_dram_dm            (mcb3_dram_dm           ),       
     81         .mcb3_dram_udqs          (mcb3_dram_udqs         ),       
     82         .mcb3_dram_udqs_n        (mcb3_dram_udqs_n       ),       
     83         .mcb3_dram_dqs           (mcb3_dram_dqs          ),       
     84         .mcb3_dram_dqs_n         (mcb3_dram_dqs_n        ),       
     85         .mcb3_rzq                (mcb3_rzq               ),       
     86         .mcb3_zio                (mcb3_zio               ),       
     87         .mcb3_dram_udm           (mcb3_dram_udm          ),       
     88         // USB interfaces
     89         .usb_ifclk              (usb_ifclk              ),       
     90         .usb_full               (),       
     91         .usb_empty              (1'b1                   ),       
     92         .usb_slcs               (),       
     93         .usb_slwr               (),       
     94         .usb_slrd               (usb_slrd               ),       
     95         .usb_sloe               (),       
     96         .usb_fifoadr            (),
     97         .usb_fdata              (usb_fdata              )
     98 );
     99 /*
    100 ddr3_model_c3 u_mem_c3(
    101       .ck         (mcb3_dram_ck),
    102       .ck_n       (mcb3_dram_ck_n),
    103       .cke        (mcb3_dram_cke),
    104       .cs_n       (1'b0),
    105       .ras_n      (mcb3_dram_ras_n),
    106       .cas_n      (mcb3_dram_cas_n),
    107       .we_n       (mcb3_dram_we_n),
    108       .dm_tdqs    ({mcb3_dram_udm,mcb3_dram_dm}),
    109       .ba         (mcb3_dram_ba),
    110       .addr       (mcb3_dram_a),
    111       .dq         (mcb3_dram_dq),
    112       .dqs        ({mcb3_dram_udqs,mcb3_dram_dqs}),
    113       .dqs_n      ({mcb3_dram_udqs_n,mcb3_dram_dqs_n}),
    114       .tdqs_n     (),
    115       .odt        (mcb3_dram_odt),
    116       .rst_n      (mcb3_dram_reset_n)
    117 );
    118 
    119 PULLDOWN zio_pulldown3 (.O(mcb3_zio));   PULLDOWN rzq_pulldown3 (.O(mcb3_rzq));
    120 */
    121 endmodule
    View Code

    usb_read:

     1 // *********************************************************************************
     2 // Project Name : OSXXXX
     3 // Author       : 李国勇
     4 // weixin       : li15226499835
     5 // Website      : https://www.cnblogs.com/lgy-gdeu/
     6 // Create Time  : 2019-10-30
     7 // File Name    : .v
     8 // Module Name  : 
     9 // Called By    :
    10 // Abstract     :
    11 //
    12 // CopyRight(c) 2018, OpenSoc Studio.. 
    13 // All Rights Reserved
    14 //
    15 // *********************************************************************************
    16 // Modification History:
    17 // Date         By              Version                 Change Description
    18 // -----------------------------------------------------------------------
    19 // 2019/10/30   李国勇           1.0                     Original
    20 //  
    21 // *********************************************************************************
    22 `timescale      1ns/1ns
    23 
    24 module  usb_read(
    25         // system signals
    26         input                   s_rst_n                 ,       
    27         // system signals
    28         input                   usb_ifclk               ,       
    29         input                   usb_full                ,       
    30         input                   usb_empty               ,       
    31         output  wire            usb_slcs                ,       
    32         output  wire            usb_slwr                ,       
    33         output  wire            usb_slrd                ,       
    34         output  wire            usb_sloe                ,       
    35         output  wire    [ 1:0]  usb_fifoadr             ,
    36         input           [15:0]  usb_fdata               ,
    37         // User Data
    38         output  reg             usb_wr_en               ,
    39         output  reg     [63:0]  usb_wr_data             
    40 );
    41 
    42 //========================================================================
    43 // =========== Define Parameter and Internal signals =========== 
    44 //========================================================================/
    45 
    46 reg                             usb_slrd_reg                    ;   
    47 reg     [ 1:0]                  data_cnt                        ;
    48     
    49 
    50 //=============================================================================
    51 //**************    Main Code   **************
    52 //=============================================================================
    53 assign  usb_slcs        =       1'b0;
    54 assign  usb_slrd        =       (usb_empty == 1'b1 && usb_slrd_reg == 1'b0) ? 1'b0 : 1'b1;
    55 assign  usb_slwr        =       1'b1;
    56 assign  usb_sloe        =       1'b0;
    57 assign  usb_fifoadr     =       2'b00;  // 2,4,6,8
    58 
    59 
    60 always  @(posedge usb_ifclk or negedge s_rst_n) begin
    61         if(s_rst_n == 1'b0)
    62                 usb_slrd_reg    <=      1'b1;
    63         else if(usb_empty == 1'b1)
    64                 usb_slrd_reg    <=      1'b0;
    65         else 
    66                 usb_slrd_reg    <=      1'b1;
    67 end
    68 
    69 always  @(posedge usb_ifclk or negedge s_rst_n) begin
    70         if(s_rst_n == 1'b0)
    71                 usb_wr_data     <=       64'h0;
    72         else if(usb_slrd == 1'b0)
    73                 usb_wr_data     <=      {usb_wr_data[47:0], usb_fdata};
    74 end
    75 
    76 always  @(posedge usb_ifclk or negedge s_rst_n) begin
    77         if(s_rst_n == 1'b0)
    78                 data_cnt        <=      'd0;
    79         else if(usb_slrd == 1'b0)
    80                 data_cnt        <=      data_cnt + 1'b1;
    81 end
    82 
    83 always  @(posedge usb_ifclk or negedge s_rst_n) begin
    84         if(s_rst_n == 1'b0)
    85                 usb_wr_en       <=      1'b0;
    86         else if(usb_slrd == 1'b0 && data_cnt == 'd3)
    87                 usb_wr_en       <=      1'b1;
    88         else
    89                 usb_wr_en       <=      1'b0;
    90 end
    91 
    92 endmodule
    View Code

    ddr_drive:

     1 module  ddr3_drive(
     2         // system signals
     3         input                   wr_clk                  ,       
     4         input                   s_rst_n                 ,       
     5         // DDR3 User Interfaces
     6         input                   p0_wr_en                ,
     7         output  reg             p0_cmd_en               ,       
     8         output  wire    [ 2:0]  p0_cmd_instr            ,       
     9         output  wire    [ 5:0]  p0_cmd_bl               ,       
    10         output  reg     [29:0]  p0_byte_addr            , 
    11         output  wire    [ 7:0]  p0_wr_mask              ,       
    12         output  reg             p1_cmd_en               ,       
    13         output  wire    [ 2:0]  p1_cmd_instr            ,       
    14         output  wire    [ 5:0]  p1_cmd_bl               ,       
    15         output  reg     [29:0]  p1_byte_addr            ,
    16         output  reg             p1_rd_en                ,       
    17         input           [63:0]  p1_rd_data                            
    18 );
    19 
    20 //========================================================================
    21 // =========== Define Parameter and Internal signals =========== 
    22 //========================================================================/
    23 localparam      BURST_END       =       'd10                    ;
    24 // localparam      BURST_END       =       4800                    ;
    25 
    26 reg     [ 3:0]                  wr_cnt                          ;
    27 reg     [15:0]                  wr_bl_cnt                       ;
    28 
    29 //=============================================================================
    30 //**************    Main Code   **************
    31 //=============================================================================
    32 assign  p0_cmd_instr    =       3'b000;
    33 assign  p0_cmd_bl       =       'd15;
    34 assign  p0_wr_mask      =       8'h0;
    35 assign  p1_cmd_instr    =       3'b001;
    36 assign  p1_cmd_bl       =       'd15;
    37 
    38 always  @(posedge wr_clk or negedge s_rst_n) begin
    39         if(s_rst_n == 1'b0)
    40                 wr_cnt  <=      'd0;
    41         else if(p0_wr_en == 1'b1)
    42                 wr_cnt  <=      wr_cnt + 1'b1;
    43 end
    44 
    45 always  @(posedge wr_clk or negedge s_rst_n) begin
    46         if(s_rst_n == 1'b0)
    47                 p0_cmd_en       <=      1'b0;
    48         else if(p0_wr_en == 1'b1 && wr_cnt == 'd15)
    49                 p0_cmd_en       <=      1'b1;
    50         else
    51                 p0_cmd_en       <=      1'b0;
    52 end
    53 
    54 always  @(posedge wr_clk or negedge s_rst_n) begin
    55         if(s_rst_n == 1'b0)
    56                 p0_byte_addr    <=      'd0;
    57         else if(p0_cmd_en == 1'b1 && wr_bl_cnt >= (BURST_END-1))
    58                 p0_byte_addr    <=      'd0;
    59         else if(p0_cmd_en == 1'b1)
    60                 p0_byte_addr    <=      p0_byte_addr + 'd128;        
    61 end
    62 
    63 always  @(posedge wr_clk or negedge s_rst_n) begin
    64         if(s_rst_n == 1'b0)
    65                 wr_bl_cnt       <=      'd0;
    66         else if(p0_cmd_en == 1'b1 && wr_bl_cnt >= (BURST_END-1))
    67                 wr_bl_cnt       <=      'd0;
    68         else if(p0_cmd_en == 1'b1)
    69                 wr_bl_cnt       <=      wr_bl_cnt + 1'b1;
    70 end
    71 
    72 endmodule
    View Code
  • 相关阅读:
    C语言宏中"#"和"##"的用法
    Ubuntu 14.04 LTS 安装和配置Bochs
    C和C++中static的比较
    总线设备驱动模型
    驱动设计的思想:面向对象/分层/分离
    基于分层思想的驱动程序软件框架
    单元测试指南
    Apollo移植
    剑指offer python版 数组中出现次数超过一半的数字
    剑指offer python版 字符串的排列
  • 原文地址:https://www.cnblogs.com/lgy-gdeu/p/11762438.html
Copyright © 2020-2023  润新知