上一节已经成功地测试了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