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