DDR3 IP基础知识 (1条消息) 快速上手Xilinx DDR3 IP核----汇总篇(MIG)_ddr3 xilinx_孤独的单刀的博客-CSDN博客
DDR3 tb文件
1 `timescale 1ns / 1ps 2 ////////////////////////////////////////////////////////////////////////////////// 3 // Company: 4 // Engineer: 5 // 6 // Create Date: 2022/08/17 10:52:08 7 // Design Name: 8 // Module Name: tb 9 // Project Name: 10 // Target Devices: 11 // Tool Versions: 12 // Description: 13 // 14 // Dependencies: 15 // 16 // Revision: 17 // Revision 0.01 - File Created 18 // Additional Comments: 19 // 20 ////////////////////////////////////////////////////////////////////////////////// 21 22 23 module axi4_mig_tb; 24 25 reg clk_100M ; 26 reg clk_200M ; 27 reg rst_n ; 28 29 wire [3:0] M00_AXI_awid ; 30 wire [31:0] M00_AXI_awaddr ; 31 wire [7:0] M00_AXI_awlen ; 32 wire [2:0] M00_AXI_awsize ; 33 wire [1:0] M00_AXI_awburst ; 34 wire M00_AXI_awlock ; 35 wire [3:0] M00_AXI_awcache ; 36 wire [2:0] M00_AXI_awprot ; 37 wire [3:0] M00_AXI_awqos ; 38 wire M00_AXI_awvalid ; 39 wire M00_AXI_awready ; 40 wire [63:0] M00_AXI_wdata ; 41 wire [7:0] M00_AXI_wstrb ; 42 wire M00_AXI_wlast ; 43 wire M00_AXI_wvalid ; 44 wire M00_AXI_wready ; 45 wire [3:0] M00_AXI_bid ; 46 wire [1:0] M00_AXI_bresp ; 47 wire M00_AXI_bvalid ; 48 wire M00_AXI_bready ; 49 wire [3:0] M00_AXI_arid ; 50 wire [31:0] M00_AXI_araddr ; 51 wire [7:0] M00_AXI_arlen ; 52 wire [2:0] M00_AXI_arsize ; 53 wire [1:0] M00_AXI_arburst ; 54 wire M00_AXI_arlock ; 55 wire [3:0] M00_AXI_arcache ; 56 wire [2:0] M00_AXI_arprot ; 57 wire [3:0] M00_AXI_arqos ; 58 wire M00_AXI_arvalid ; 59 wire M00_AXI_arready ; 60 wire [3:0] M00_AXI_rid ; 61 wire [63:0] M00_AXI_rdata ; 62 wire [1:0] M00_AXI_rresp ; 63 wire M00_AXI_rlast ; 64 wire M00_AXI_rvalid ; 65 wire M00_AXI_rready ; 66 67 wire src_vs ; 68 wire src_de ; 69 wire [7:0] src_data ; 70 71 wire mid_de ; 72 wire [7:0] mid_data ; 73 wire mid_start ; 74 75 wire dst_vs ; 76 wire dst_de ; 77 wire [7:0] dst_data ; 78 wire [31:0] dst_cnt ; 79 wire dst_end ; 80 81 wire axi_rd_start ; 82 83 wire [14:0] ddr3_addr ; 84 wire [2:0] ddr3_ba ; 85 wire ddr3_cas_n ; 86 wire [0:0] ddr3_ck_n ; 87 wire [0:0] ddr3_ck_p ; 88 wire [0:0] ddr3_cke ; 89 wire ddr3_ras_n ; 90 wire ddr3_reset_n ; 91 wire ddr3_we_n ; 92 wire [7:0] ddr3_dq ; 93 wire [0:0] ddr3_dqs_n ; 94 wire [0:0] ddr3_dqs_p ; 95 wire [0:0] ddr3_cs_n ; 96 wire [0:0] ddr3_dm ; 97 wire [0:0] ddr3_odt ; 98 99 wire init_done ; 100 101 wire ui_clk ; 102 wire ui_rst ; 103 104 integer outfile; 105 106 initial begin 107 clk_100M = 0; 108 clk_200M = 0; 109 rst_n = 0; 110 111 #11 112 113 rst_n = 1; 114 115 #100 116 117 outfile = $fopen("H:/xilinx2019/secondlevel/study/vip/lesson11/data/post.txt","w"); 118 end 119 120 always #5 clk_100M = ~clk_100M; 121 always #2.5 clk_200M = ~clk_200M; 122 123 localparam S_IW = 32 ; 124 localparam S_IH = 32 ; 125 126 img_gen #( 127 .ACTIVE_IW (S_IW ), 128 .ACTIVE_IH (S_IH ), 129 .TOTAL_IW (S_IW + 200 ), 130 .TOTAL_IH (S_IH + 200 ), 131 .H_START (5 ), 132 .V_START (5 ) 133 ) 134 u0_img_gen 135 ( 136 .clk (clk_100M ), 137 .rst_n (rst_n ), 138 .vs (src_vs ), 139 .de (src_de ), 140 .data (src_data ), 141 142 .wr_start (init_done ), //DDR初始化完成 143 .rd_start (axi_rd_start) //输出十行数据 144 ); 145 146 axi_dma #( 147 .AXI_ADDR_WIDTH (32 ), 148 .AXI_BUF_SIZE (1 ), 149 .AXI_ADDR_BASE (32'h00000000 ), 150 151 .WR_CH_EN (1 ), 152 .WR_BURST_LEN (4 ), 153 .WR_DATA_WIDTH (64 ), 154 .WR_IW (32 ), 155 .WR_IH (32 ), 156 157 .RD_CH_EN (1 ), 158 .RD_BURST_LEN (4 ), 159 .RD_DATA_WIDTH (64 ), 160 .RD_IW (32 ), 161 .RD_IH (32 ), 162 163 .I_DW (8 ), 164 .O_DW (8 ) 165 ) 166 u0_axi_dma 167 ( 168 //user_wr 169 .pre_clk (clk_100M ), 170 .pre_vs (src_vs ), 171 .pre_de (src_de ), 172 .pre_data (src_data ), 173 //user_rd 174 .post_clk (clk_100M ), 175 .post_de (mid_de ), 176 .post_data (mid_data ), 177 .post_start (mid_start ),//读FIFO中满足要求,开始读取数据 178 //ex_signal 179 .o_wr_index ( ), 180 //in_signal 181 .axi_rd_start (axi_rd_start ), //信号输入端输出10行数据,开始拉高读开始信号 182 .i_wr_index (8'd1 ), 183 //axi_logic 184 .M_AXI_ACLK (ui_clk ), 185 .M_AXI_ARESETN (~ui_rst ), 186 .M_AXI_AWID (M00_AXI_awid ), 187 .M_AXI_AWADDR (M00_AXI_awaddr ), 188 .M_AXI_AWLEN (M00_AXI_awlen ), 189 .M_AXI_AWSIZE (M00_AXI_awsize ), 190 .M_AXI_AWBURST (M00_AXI_awburst ), 191 .M_AXI_AWLOCK (M00_AXI_awlock ), 192 .M_AXI_AWCACHE (M00_AXI_awcache ), 193 .M_AXI_AWPROT (M00_AXI_awprot ), 194 .M_AXI_AWQOS (M00_AXI_awqos ), 195 .M_AXI_AWVALID (M00_AXI_awvalid ), 196 .M_AXI_AWREADY (M00_AXI_awready ), 197 .M_AXI_WDATA (M00_AXI_wdata ), 198 .M_AXI_WSTRB (M00_AXI_wstrb ), 199 .M_AXI_WLAST (M00_AXI_wlast ), 200 .M_AXI_WVALID (M00_AXI_wvalid ), 201 .M_AXI_WREADY (M00_AXI_wready ), 202 .M_AXI_BID (M00_AXI_bid ), 203 .M_AXI_BRESP (M00_AXI_bresp ), 204 .M_AXI_BVALID (M00_AXI_bvalid ), 205 .M_AXI_BREADY (M00_AXI_bready ), 206 .M_AXI_ARID (M00_AXI_arid ), 207 .M_AXI_ARADDR (M00_AXI_araddr ), 208 .M_AXI_ARLEN (M00_AXI_arlen ), 209 .M_AXI_ARSIZE (M00_AXI_arsize ), 210 .M_AXI_ARBURST (M00_AXI_arburst ), 211 .M_AXI_ARLOCK (M00_AXI_arlock ), 212 .M_AXI_ARCACHE (M00_AXI_arcache ), 213 .M_AXI_ARPROT (M00_AXI_arprot ), 214 .M_AXI_ARQOS (M00_AXI_arqos ), 215 .M_AXI_ARVALID (M00_AXI_arvalid ), 216 .M_AXI_ARREADY (M00_AXI_arready ), 217 .M_AXI_RID (M00_AXI_rid ), 218 .M_AXI_RDATA (M00_AXI_rdata ), 219 .M_AXI_RRESP (M00_AXI_rresp ), 220 .M_AXI_RLAST (M00_AXI_rlast ), 221 .M_AXI_RVALID (M00_AXI_rvalid ), 222 .M_AXI_RREADY (M00_AXI_rready ) 223 ); 224 225 mig_7series_0 u_mig_7series_0 ( 226 // Memory interface ports 227 .ddr3_addr (ddr3_addr ), // output [14:0] ddr3_addr 228 .ddr3_ba (ddr3_ba ), // output [2:0] ddr3_ba 229 .ddr3_cas_n (ddr3_cas_n ), // output ddr3_cas_n 230 .ddr3_ck_n (ddr3_ck_n ), // output [0:0] ddr3_ck_n 231 .ddr3_ck_p (ddr3_ck_p ), // output [0:0] ddr3_ck_p 232 .ddr3_cke (ddr3_cke ), // output [0:0] ddr3_cke 233 .ddr3_ras_n (ddr3_ras_n ), // output ddr3_ras_n 234 .ddr3_reset_n (ddr3_reset_n ), // output ddr3_reset_n 235 .ddr3_we_n (ddr3_we_n ), // output ddr3_we_n 236 .ddr3_dq (ddr3_dq ), // inout [7:0] ddr3_dq 237 .ddr3_dqs_n (ddr3_dqs_n ), // inout [0:0] ddr3_dqs_n 238 .ddr3_dqs_p (ddr3_dqs_p ), // inout [0:0] ddr3_dqs_p 239 240 .init_calib_complete (init_done ), // output init_calib_complete 241 242 .ddr3_cs_n (ddr3_cs_n ), // output [0:0] ddr3_cs_n 243 .ddr3_dm (ddr3_dm ), // output [0:0] ddr3_dm 244 .ddr3_odt (ddr3_odt ), // output [0:0] ddr3_odt 245 // Application interface ports 输入给0,输出悬空 246 .ui_clk (ui_clk ), // output ui_clk 247 .ui_clk_sync_rst (ui_rst ), // output ui_clk_sync_rst 248 .mmcm_locked ( ), // output mmcm_locked 249 .aresetn (rst_n ), // input aresetn 250 .app_sr_req (1'b0 ), // input app_sr_req 251 .app_ref_req (1'b0 ), // input app_ref_req 252 .app_zq_req (1'b0 ), // input app_zq_req 253 .app_sr_active ( ), // output app_sr_active 254 .app_ref_ack ( ), // output app_ref_ack 255 .app_zq_ack ( ), // output app_zq_ack 256 // Slave Interface Write Address Ports 257 .s_axi_awid (M00_AXI_awid ), // input [3:0] s_axi_awid 258 .s_axi_awaddr (M00_AXI_awaddr ), // input [27:0] s_axi_awaddr 259 .s_axi_awlen (M00_AXI_awlen ), // input [7:0] s_axi_awlen 260 .s_axi_awsize (M00_AXI_awsize ), // input [2:0] s_axi_awsize 261 .s_axi_awburst (M00_AXI_awburst), // input [1:0] s_axi_awburst 262 .s_axi_awlock (M00_AXI_awlock ), // input [0:0] s_axi_awlock 263 .s_axi_awcache (M00_AXI_awcache), // input [3:0] s_axi_awcache 264 .s_axi_awprot (M00_AXI_awprot ), // input [2:0] s_axi_awprot 265 .s_axi_awqos (M00_AXI_awqos ), // input [3:0] s_axi_awqos 266 .s_axi_awvalid (M00_AXI_awvalid), // input s_axi_awvalid 267 .s_axi_awready (M00_AXI_awready), // output s_axi_awready 268 // Slave Interface Write Data Ports 269 .s_axi_wdata (M00_AXI_wdata ), // input [63:0] s_axi_wdata 270 .s_axi_wstrb (M00_AXI_wstrb ), // input [7:0] s_axi_wstrb 271 .s_axi_wlast (M00_AXI_wlast ), // input s_axi_wlast 272 .s_axi_wvalid (M00_AXI_wvalid ), // input s_axi_wvalid 273 .s_axi_wready (M00_AXI_wready ), // output s_axi_wready 274 // Slave Interface Write Response Ports 275 .s_axi_bid (M00_AXI_bid ), // output [3:0] s_axi_bid 276 .s_axi_bresp (M00_AXI_bresp ), // output [1:0] s_axi_bresp 277 .s_axi_bvalid (M00_AXI_bvalid ), // output s_axi_bvalid 278 .s_axi_bready (M00_AXI_bready ), // input s_axi_bready 279 // Slave Interface Read Address Ports 280 .s_axi_arid (M00_AXI_arid ), // input [3:0] s_axi_arid 281 .s_axi_araddr (M00_AXI_araddr ), // input [27:0] s_axi_araddr 282 .s_axi_arlen (M00_AXI_arlen ), // input [7:0] s_axi_arlen 283 .s_axi_arsize (M00_AXI_arsize ), // input [2:0] s_axi_arsize 284 .s_axi_arburst (M00_AXI_arburst), // input [1:0] s_axi_arburst 285 .s_axi_arlock (M00_AXI_arlock ), // input [0:0] s_axi_arlock 286 .s_axi_arcache (M00_AXI_arcache), // input [3:0] s_axi_arcache 287 .s_axi_arprot (M00_AXI_arprot ), // input [2:0] s_axi_arprot 288 .s_axi_arqos (M00_AXI_arqos ), // input [3:0] s_axi_arqos 289 .s_axi_arvalid (M00_AXI_arvalid), // input s_axi_arvalid 290 .s_axi_arready (M00_AXI_arready), // output s_axi_arready 291 // Slave Interface Read Data Ports 292 .s_axi_rid (M00_AXI_rid ), // output [3:0] s_axi_rid 293 .s_axi_rdata (M00_AXI_rdata ), // output [63:0] s_axi_rdata 294 .s_axi_rresp (M00_AXI_rresp ), // output [1:0] s_axi_rresp 295 .s_axi_rlast (M00_AXI_rlast ), // output s_axi_rlast 296 .s_axi_rvalid (M00_AXI_rvalid ), // output s_axi_rvalid 297 .s_axi_rready (M00_AXI_rready ), // input s_axi_rready 298 // System Clock Ports 299 .sys_clk_i (clk_200M ),//通过PLL输出给MIG作为系统时钟和参考时钟用 300 .sys_rst (rst_n ) // input sys_rst 301 ); 302 303 ddr3_model u_ddr3_model( 304 .rst_n (ddr3_reset_n ), 305 .ck (ddr3_ck_p ), 306 .ck_n (ddr3_ck_n ), 307 .cke (ddr3_cke ), 308 .cs_n (ddr3_cs_n ), 309 .ras_n (ddr3_ras_n ), 310 .cas_n (ddr3_cas_n ), 311 .we_n (ddr3_we_n ), 312 .dm_tdqs (ddr3_dm ), 313 .ba (ddr3_ba ), 314 .addr (ddr3_addr ), 315 .dq (ddr3_dq ), 316 .dqs (ddr3_dqs_p ), 317 .dqs_n (ddr3_dqs_n ), 318 .tdqs_n ( ), 319 .odt (ddr3_odt ) 320 ); 321 322 img_rd #( 323 .S_IW (S_IW), 324 .S_IH (S_IH) 325 ) 326 u1_img_rd 327 ( 328 .clk_100M (clk_100M ), 329 .rst_n (rst_n ), 330 331 .mid_de (mid_de ), 332 .mid_data (mid_data ), 333 .mid_start (mid_start ), 334 335 .dst_vs (dst_vs ), 336 .dst_de (dst_de ), 337 .dst_data (dst_data ), 338 .dst_cnt (dst_cnt ), 339 .dst_end (dst_end ) 340 ); 341 342 always @(posedge clk_100M or negedge rst_n) 343 if(dst_de==1) 344 begin 345 $fdisplay(outfile,"%h",dst_data); 346 end 347 348 always @(posedge clk_100M or negedge rst_n) 349 if(dst_end) 350 begin 351 $stop; 352 end 353 354 355 endmodule
对于 ID参数,直接给0,因为AXI_interconnect会自己分配ID,写FIFO复位的时候,需要多拉高几个周期的复位信号,因为对于时钟速率相差较大的两个读写时钟,如果复位信号只是一个周期,会导致写FIFO一直存于复位状态
对于axi_wlast信号,不能直接使用组合逻辑,因为可能会导致在mig ip核中出错,
1 module axi_dma #( 2 parameter AXI_ADDR_WIDTH = 32 , //AXI地址位宽 3 parameter AXI_BUF_SIZE = 3 , //BUF个数 4 parameter AXI_ADDR_BASE = 32'h00000000 , //基地址 5 6 parameter WR_CH_EN = 1 , //写通道使能 7 parameter WR_BURST_LEN = 80 , //写突发长度 8 parameter WR_DATA_WIDTH = 64 , //写数据位宽 9 parameter WR_IW = 640 , //输入图像行像素宽度 10 parameter WR_IH = 512 , //输入图像场像素高度 11 12 parameter RD_CH_EN = 1 , 13 parameter RD_BURST_LEN = 80 , 14 parameter RD_DATA_WIDTH = 64 , 15 parameter RD_IW = 640 , 16 parameter RD_IH = 512 , 17 18 parameter I_DW = 8 , //输入像素位宽 19 parameter O_DW = 8 //输出像素位宽 20 ) 21 ( 22 23 input wire pre_clk , //输入数据时钟信号 24 input wire pre_vs , //输入场信号 25 input wire pre_de , //数据有效信号 26 input wire [I_DW-1:0] pre_data , //输入数据 27 28 input wire post_clk , //输出数据时钟 29 input wire post_de , //输出数据使能 30 output wire [O_DW-1:0] post_data , //输出数据 31 output reg post_start , //数据可读信号,拉高后一直保持 32 33 input wire axi_rd_start , //外围设备准备完毕信号 34 35 input wire [7:0] i_wr_index , //写指示信号 36 output reg [7:0] o_wr_index , 37 38 output reg wr_irq , //一帧数据中断信号 39 40 input wire M_AXI_ACLK , //AXI 时钟 41 input wire M_AXI_ARESETN , //AXI 复位 42 output wire M_AXI_AWID , //AXI 写地址ID 43 output wire [AXI_ADDR_WIDTH-1:0] M_AXI_AWADDR , //AXI 写地址 44 output wire [7:0] M_AXI_AWLEN , //AXI 一次突发长度 M_AXI_AWLEN = WR_BURST_LEN - 1'b1 (1-255) 45 output wire [2:0] M_AXI_AWSIZE , //AXI M_AXI_AWSIZE = clogb2((WR_DATA_WIDTH/8)-1) = 3 46 output wire [1:0] M_AXI_AWBURST , //2'b01 地址递增模式 47 output wire M_AXI_AWLOCK , //1'b0 48 output wire [3:0] M_AXI_AWCACHE , //4'b0010 ,ACP接口给4'b0011 49 output wire [2:0] M_AXI_AWPROT , //3'b0 50 output wire [3:0] M_AXI_AWQOS , //4'b0 51 output wire M_AXI_AWVALID , 52 input wire M_AXI_AWREADY , 53 output wire [WR_DATA_WIDTH-1:0] M_AXI_WDATA , 54 output wire [WR_DATA_WIDTH/8-1:0] M_AXI_WSTRB , //数据掩码 55 output wire M_AXI_WLAST , //一次突发结束信号 56 output wire M_AXI_WVALID , 57 input wire M_AXI_WREADY , 58 input wire M_AXI_BID , //响应ID 59 input wire [1:0] M_AXI_BRESP , 60 input wire M_AXI_BVALID , 61 output wire M_AXI_BREADY , 62 output wire M_AXI_ARID , //读地址ID 63 output wire [AXI_ADDR_WIDTH-1:0] M_AXI_ARADDR , 64 output wire [7:0] M_AXI_ARLEN , //一次读突发长度 65 output wire [2:0] M_AXI_ARSIZE , 66 output wire [1:0] M_AXI_ARBURST , //2'b01 地址递增模式 67 output wire M_AXI_ARLOCK , //1‘b0 68 output wire [3:0] M_AXI_ARCACHE , //4'b0010 69 output wire [2:0] M_AXI_ARPROT , //3'b0 70 output wire [3:0] M_AXI_ARQOS , //4'b0 71 output wire M_AXI_ARVALID , 72 input wire M_AXI_ARREADY , 73 input wire M_AXI_RID , 74 input wire [RD_DATA_WIDTH-1:0] M_AXI_RDATA , 75 input wire [1:0] M_AXI_RRESP , 76 input wire M_AXI_RLAST , 77 input wire M_AXI_RVALID , 78 output wire M_AXI_RREADY 79 ); 80 81 localparam addr_offset = WR_IW*WR_IH*I_DW/8 ; //一帧数据的地址偏移 82 83 localparam wr_burst_bytes = WR_BURST_LEN*WR_DATA_WIDTH/8 ; //写突发一次的字节数 84 localparam rd_burst_bytes = RD_BURST_LEN*RD_DATA_WIDTH/8 ; //读突发一次的字节数 85 86 localparam wr_burst_times = WR_IW*WR_IH*I_DW/8/wr_burst_bytes ; //一帧数据突发的次数 87 localparam rd_burst_times = WR_IW*WR_IH*O_DW/8/rd_burst_bytes ; //一帧数据突发的次数 88 89 //AXI_WR 90 reg pre_vs_r ; 91 wire pre_pose ; 92 wire pre_nege ; 93 wire ext_pre_pose ; 94 95 wire o_data_de ; 96 wire [WR_DATA_WIDTH-1:0] o_data ; 97 98 wire sys_pre_nege ; 99 reg sys_pre_nege_r ; 100 101 reg [7:0] wr_index ; 102 reg [31:0] wr_base_addr ; 103 reg wr_burst_start ; 104 reg wr_cycle_flag ; 105 106 reg axi_awvalid ; 107 reg [AXI_ADDR_WIDTH-1:0] axi_awaddr ; 108 reg axi_wvalid ; 109 wire [WR_DATA_WIDTH-1:0] axi_wdata ; 110 reg axi_wlast ; 111 wire axi_bready ; 112 113 reg [7:0] burst_cnt ; 114 wire axi_wdata_de ; 115 116 wire wr_full ; 117 wire wr_empty ; 118 wire [10:0] wr_rd_data_count; 119 wire [10:0] wr_wr_data_count; 120 121 reg [15:0] cnt_1us ; 122 123 always@(posedge pre_clk) 124 if(!M_AXI_ARESETN) 125 pre_vs_r <= 1'd0; 126 else 127 pre_vs_r <= pre_vs; 128 129 assign pre_pose = ~pre_vs_r&&pre_vs ; 130 assign pre_nege = ~pre_vs&&pre_vs_r ; 131 132 data_sync_ext u1_data_sync_ext( 133 .clka (pre_clk ), 134 .rst_n (M_AXI_ARESETN ), 135 .pulse_a (pre_pose ), 136 .ext_pulse_a (ext_pre_pose ) 137 ); 138 139 140 // ila_0 u3_ila_0 ( 141 // .clk(pre_clk), // input wire clk 142 143 // .probe0({ 144 // pre_vs, 145 // pre_vs_r, 146 // pre_pose, 147 // pre_de, 148 // pre_data, 149 // o_data_de, 150 // o_data, 151 // ext_pre_pose 152 // }) // input wire [255:0] probe0 153 // ); 154 155 // ila_0 u4_ila_0 ( 156 // .clk(M_AXI_ACLK), // input wire clk 157 158 // .probe0({ 159 // wr_burst_start, 160 // wr_cycle_flag, 161 // axi_awvalid, 162 // M_AXI_AWREADY, 163 // axi_awaddr, 164 // burst_cnt, 165 // axi_wlast, 166 // axi_wdata_de, 167 // axi_wdata, 168 // rd_index, 169 // wr_index, 170 // rd_flag, 171 // rd_cmd_flag, 172 // axi_arvalid, 173 // M_AXI_ARREADY, 174 // axi_araddr, 175 // rd_data_flag, 176 // axi_rready, 177 // axi_rdata_de, 178 // M_AXI_RDATA, 179 // axi_wvalid, 180 // M_AXI_WREADY, 181 // rd_wr_data_count, 182 // rd_rd_data_count, 183 // post_start, 184 // post_de, 185 // post_hcnt, 186 // post_vcnt, 187 // rd_hcnt, 188 // rd_vcnt 189 190 191 // }) // input wire [255:0] probe0 192 // ); 193 194 195 196 //数据拼接 197 data_joint #( 198 .IW_WIDTH (I_DW ), 199 .OW_WIDTH (WR_DATA_WIDTH ) 200 ) 201 u1_data_joint 202 ( 203 .clk (pre_clk ), 204 .rst_n (~pre_pose&&M_AXI_ARESETN ), 205 .i_data_de (pre_de ), 206 .i_data (pre_data ), 207 .o_data_de (o_data_de ), 208 .o_data (o_data ) 209 ); 210 //同步场下降沿信号 211 fifo_8_sys u1_fifo_fs_start 212 ( 213 .wr_clk (pre_clk ), 214 .rd_clk (M_AXI_ACLK ), 215 .din (8'd1 ), 216 .wr_en (pre_nege ), 217 .rd_en (~sys_pre_nege ), 218 .dout ( ), 219 .full ( ), 220 .empty (sys_pre_nege ) 221 ); 222 223 always@(posedge M_AXI_ACLK) 224 if(!M_AXI_ARESETN ) 225 sys_pre_nege_r <= 1'b0; 226 else 227 sys_pre_nege_r <= ~sys_pre_nege; 228 229 always@(posedge M_AXI_ACLK) 230 if(!M_AXI_ARESETN) 231 wr_index <= 'd1; 232 else if(~sys_pre_nege==1'b1&&wr_index==AXI_BUF_SIZE[7:0]) 233 wr_index <= 'd1; 234 else if(~sys_pre_nege==1'b1) 235 wr_index <= wr_index + 1'b1; 236 else 237 wr_index <= wr_index; 238 239 always@(posedge M_AXI_ACLK) 240 if(!M_AXI_ARESETN) 241 o_wr_index <= 'd0; 242 else 243 o_wr_index <= wr_index; 244 245 always@(posedge M_AXI_ACLK) 246 if(!M_AXI_ARESETN) 247 wr_base_addr <= 'd0; 248 else if(~sys_pre_nege==1'b1&&wr_index==AXI_BUF_SIZE[7:0]) 249 wr_base_addr <= 'd0; 250 else if(~sys_pre_nege==1'b1) 251 wr_base_addr <= wr_base_addr + addr_offset; 252 else 253 wr_base_addr <= wr_base_addr; 254 //发起突发开始信号 255 always@(posedge M_AXI_ACLK) 256 if(!M_AXI_ARESETN) 257 wr_burst_start <= 1'b0; 258 else if(wr_rd_data_count>=WR_BURST_LEN&&WR_CH_EN[0]==1'b1) 259 wr_burst_start <= 1'b1; 260 else 261 wr_burst_start <= 1'b0; 262 //写周期标志 263 always@(posedge M_AXI_ACLK) 264 if(!M_AXI_ARESETN) 265 wr_cycle_flag <= 1'b0; 266 else if(wr_cycle_flag==1'b1&&axi_wvalid==1'b1&&M_AXI_WREADY==1'b1&&axi_wlast==1'b1) 267 wr_cycle_flag <= 1'b0; 268 else if(wr_burst_start==1'b1&&wr_cycle_flag==1'b0) 269 wr_cycle_flag <= 1'b1; 270 else 271 wr_cycle_flag <= wr_cycle_flag; 272 //写地址valid信号 273 always@(posedge M_AXI_ACLK) 274 if(!M_AXI_ARESETN) 275 axi_awvalid <= 1'b0; 276 else if(axi_awvalid==1'b1&&M_AXI_AWREADY==1'b1) 277 axi_awvalid <= 1'b0; 278 else if(wr_burst_start==1'b1&&wr_cycle_flag==1'b0) 279 axi_awvalid <= 1'b1; 280 else 281 axi_awvalid <= axi_awvalid; 282 283 always@(posedge M_AXI_ACLK) 284 if(!M_AXI_ARESETN) 285 axi_awaddr <= 'd0; 286 else if(sys_pre_nege_r==1'b1) 287 axi_awaddr <= wr_base_addr; 288 else if(axi_awvalid==1'b1&&M_AXI_AWREADY==1'b1) 289 axi_awaddr <= axi_awaddr + wr_burst_bytes ; 290 else 291 axi_awaddr <= axi_awaddr; 292 293 always@(posedge M_AXI_ACLK) 294 if(!M_AXI_ARESETN) 295 axi_wvalid <= 1'b0; 296 else if(axi_wvalid==1'b1&&M_AXI_WREADY==1'b1&&burst_cnt==WR_BURST_LEN-1) 297 axi_wvalid <= 1'b0; 298 else if(axi_awvalid==1'b1&&M_AXI_AWREADY==1'b1) 299 axi_wvalid <= 1'b1; 300 else 301 axi_wvalid <= axi_wvalid; 302 303 always@(posedge M_AXI_ACLK) 304 if(!M_AXI_ARESETN) 305 burst_cnt <= 'd0; 306 else if(axi_wvalid==1'b1&&M_AXI_WREADY==1'b1&&burst_cnt==WR_BURST_LEN-1) 307 burst_cnt <= 'd0; 308 else if(axi_wvalid==1'b1&&M_AXI_WREADY==1'b1) 309 burst_cnt <= burst_cnt + 1'b1; 310 else 311 burst_cnt <= burst_cnt ; 312 313 always@(posedge M_AXI_ACLK) 314 if(!M_AXI_ARESETN) 315 axi_wlast <= 1'b0; 316 else if(axi_wvalid==1'b1&&M_AXI_WREADY==1'b1&&burst_cnt==WR_BURST_LEN-1) 317 axi_wlast <= 1'b0; 318 else if(axi_wvalid==1'b1&&M_AXI_WREADY==1'b1&&burst_cnt==WR_BURST_LEN-2) 319 axi_wlast <= 1'b1; 320 else 321 axi_wlast <= axi_wlast; 322 323 assign axi_bready = 1'b1; 324 325 assign axi_wdata_de = axi_wvalid&&M_AXI_WREADY; 326 327 always@(posedge M_AXI_ACLK) 328 if(!M_AXI_ARESETN) 329 wr_irq <= 1'b0; 330 else if(cnt_1us==99) 331 wr_irq <= 1'b0; 332 else if(~sys_pre_nege==1'b1) 333 wr_irq <= 1'b1; 334 else 335 wr_irq <= wr_irq; 336 337 always@(posedge M_AXI_ACLK) 338 if(!M_AXI_ARESETN) 339 cnt_1us <= 'd0; 340 else if(cnt_1us==99) 341 cnt_1us <= 'd0; 342 else if(wr_irq==1'b1) 343 cnt_1us <= cnt_1us + 1'b1; 344 else 345 cnt_1us <= cnt_1us; 346 347 generate 348 if (WR_CH_EN[0]==1) begin: WR_EN 349 fifo_wr_64_64 u1_fifo_wr_64_64 350 ( 351 .rst (ext_pre_pose ), 352 .wr_clk (pre_clk ), 353 .rd_clk (M_AXI_ACLK ), 354 .din (o_data ), 355 .wr_en (o_data_de ), 356 .rd_en (axi_wdata_de ), 357 .dout (axi_wdata ), 358 .full (wr_full ), 359 .empty (wr_empty ), 360 .rd_data_count (wr_rd_data_count ), 361 .wr_data_count (wr_wr_data_count ) 362 ); 363 end 364 endgenerate 365 366 //AXI_RD 367 reg [7:0] rd_index ; 368 reg [7:0] rd_index_r ; 369 reg [AXI_ADDR_WIDTH-1 : 0] rd_base_addr ; 370 371 reg rd_flag ; 372 reg rd_cmd_flag ; 373 reg rd_data_flag ; 374 375 reg axi_arvalid ; 376 reg [AXI_ADDR_WIDTH-1:0] axi_araddr ; 377 reg axi_rready ; 378 379 reg [15:0] rd_hcnt ; 380 reg [15:0] rd_vcnt ; 381 382 wire axi_rdata_de ; 383 wire [RD_DATA_WIDTH-1:0] axi_rdata ; 384 385 wire rd_full ; 386 wire rd_empty ; 387 wire [13:0] rd_rd_data_count ; 388 wire [10:0] rd_wr_data_count ; 389 390 391 always@(posedge M_AXI_ACLK) 392 if(!M_AXI_ARESETN) 393 rd_index <= AXI_BUF_SIZE[7:0]; 394 else 395 case(WR_CH_EN[0]) 396 1'b0: 397 if(i_wr_index>1'b1) 398 rd_index <= i_wr_index-1'b1; 399 else 400 rd_index <= AXI_BUF_SIZE[7:0]; 401 1'b1: 402 if(wr_index>1'b1) 403 rd_index <= wr_index-1'b1; 404 else 405 rd_index <= AXI_BUF_SIZE[7:0]; 406 407 default:rd_index <= rd_index; 408 endcase 409 410 always@(posedge M_AXI_ACLK) 411 if(!M_AXI_ARESETN) 412 rd_index_r <= 'd0; 413 else 414 rd_index_r <= rd_index-1'b1; 415 416 always@(posedge M_AXI_ACLK) 417 if(!M_AXI_ARESETN) 418 rd_base_addr <= 'd0; 419 else 420 rd_base_addr <= rd_index_r*addr_offset; 421 //读标志一直拉高 422 always@(posedge M_AXI_ACLK) 423 if(!M_AXI_ARESETN) 424 rd_flag <= 1'b0; 425 else if(RD_CH_EN[0]==1'b1&&axi_rd_start==1'b1) 426 rd_flag <= 1'b1; 427 else 428 rd_flag <= rd_flag; 429 //读命令标志,此时没有传输数据,表示可以传输读地址 430 always@(posedge M_AXI_ACLK) 431 if(!M_AXI_ARESETN) 432 rd_cmd_flag <= 1'b0; 433 else if(axi_arvalid==1'b1&&M_AXI_ARREADY==1'b1) 434 rd_cmd_flag <= 1'b0; 435 else if(rd_flag==1'b1&&rd_data_flag==1'b0) 436 rd_cmd_flag <= 1'b1; 437 else 438 rd_cmd_flag <= rd_cmd_flag; 439 //读数据标志,表示正在进行读数据操作 440 always@(posedge M_AXI_ACLK) 441 if(!M_AXI_ARESETN) 442 rd_data_flag <= 1'b0; 443 else if(axi_rready==1'b1&&M_AXI_RVALID==1'b1&&M_AXI_RLAST==1'b1) 444 rd_data_flag <= 1'b0; 445 else if(axi_arvalid==1'b1&&M_AXI_ARREADY==1'b1) 446 rd_data_flag <= 1'b1; 447 else 448 rd_data_flag <= rd_data_flag; 449 //此时可以写入命令,并且写数据计数不够时拉高读地址有效信号 450 always@(posedge M_AXI_ACLK) 451 if(!M_AXI_ARESETN) 452 axi_arvalid <= 1'b0; 453 else if(axi_arvalid==1'b1&&M_AXI_ARREADY==1'b1) 454 axi_arvalid <= 1'b0; 455 else if(rd_cmd_flag==1'b1&&rd_wr_data_count<RD_BURST_LEN*4) //小于四次突发的数据 456 axi_arvalid <= 1'b1; 457 else 458 axi_arvalid <= axi_arvalid; 459 //读地址更新 460 always@(posedge M_AXI_ACLK) 461 if(!M_AXI_ARESETN) 462 axi_araddr <= 'd0; 463 else if(M_AXI_RVALID==1'b1&&axi_rready==1'b1&&rd_hcnt==(RD_BURST_LEN-1'b1)&&rd_vcnt==rd_burst_times-1'b1) 464 axi_araddr <= rd_base_addr; 465 else if(axi_arvalid==1'b1&&M_AXI_ARREADY==1'b1) 466 axi_araddr <= axi_araddr + rd_burst_bytes; 467 else 468 axi_araddr <= axi_araddr; 469 //读数据信号拉高时,准备接收数据 470 always@(posedge M_AXI_ACLK) 471 if(!M_AXI_ARESETN) 472 axi_rready <= 1'b0; 473 else if(rd_data_flag==1'b0) 474 axi_rready <= 1'b0; 475 else if(rd_data_flag==1'b1) 476 axi_rready <= 1'b1; 477 else 478 axi_rready <= axi_rready; 479 480 always@(posedge M_AXI_ACLK) 481 if(!M_AXI_ARESETN) 482 rd_hcnt <= 'd0; 483 else if(M_AXI_RVALID==1'b1&&axi_rready==1'b1&&rd_hcnt==RD_BURST_LEN-1'b1) 484 rd_hcnt <= 'd0; 485 else if(M_AXI_RVALID==1'b1&&axi_rready==1'b1) 486 rd_hcnt <= rd_hcnt + 1'b1; 487 else 488 rd_hcnt <= rd_hcnt; 489 490 always@(posedge M_AXI_ACLK) 491 if(!M_AXI_ARESETN) 492 rd_vcnt <= 'd0; 493 else if(M_AXI_RVALID==1'b1&&axi_rready==1'b1&&rd_hcnt==(RD_BURST_LEN-1'b1)&&rd_vcnt==rd_burst_times-1'b1) 494 rd_vcnt <= 'd0; 495 else if(M_AXI_RVALID==1'b1&&axi_rready==1'b1&&rd_hcnt==RD_BURST_LEN-1'b1) 496 rd_vcnt <= rd_vcnt + 1'b1; 497 else 498 rd_vcnt <= rd_vcnt; 499 500 assign axi_rdata_de = M_AXI_RVALID&&axi_rready; 501 assign axi_rdata = M_AXI_RDATA; 502 503 generate 504 if (RD_CH_EN[0]==1) begin: RD_EN 505 fifo_rd_64_8 u1_fifo_rd_64_16 506 ( 507 .wr_clk (M_AXI_ACLK ), 508 .rd_clk (post_clk ), 509 .din (axi_rdata ), 510 .wr_en (axi_rdata_de ), 511 .rd_en (post_de ), 512 .dout (post_data ), 513 .full (rd_full ), 514 .empty (rd_empty ), 515 .rd_data_count (rd_rd_data_count ), 516 .wr_data_count (rd_wr_data_count ) 517 ); 518 end 519 endgenerate 520 521 522 function integer clogb2 (input integer bit_depth); 523 begin 524 for(clogb2=0; bit_depth>0; clogb2=clogb2+1) 525 bit_depth = bit_depth >> 1; 526 end 527 endfunction 528 529 530 assign M_AXI_AWID = 1'b0 ; 531 assign M_AXI_AWVALID = axi_awvalid ; 532 assign M_AXI_AWADDR = AXI_ADDR_BASE + axi_awaddr ; 533 assign M_AXI_AWLEN = WR_BURST_LEN - 1'b1 ; 534 assign M_AXI_AWSIZE = clogb2((WR_DATA_WIDTH/8)-1) ; 535 assign M_AXI_AWBURST = 2'b01 ; 536 assign M_AXI_AWLOCK = 1'b0 ; 537 assign M_AXI_AWCACHE = 4'b0010 ; 538 assign M_AXI_AWPROT = 3'b000 ; 539 assign M_AXI_AWQOS = 4'b0000 ; 540 assign M_AXI_WVALID = axi_wvalid ; 541 assign M_AXI_WDATA = axi_wdata ; 542 assign M_AXI_WSTRB = {(WR_DATA_WIDTH/8){1'b1}} ; 543 assign M_AXI_WLAST = axi_wlast ; 544 assign M_AXI_BREADY = axi_bready ; 545 546 assign M_AXI_ARID = 1'b0 ; 547 assign M_AXI_ARVALID = axi_arvalid ; 548 assign M_AXI_ARADDR = AXI_ADDR_BASE + axi_araddr ; 549 assign M_AXI_ARLEN = RD_BURST_LEN-1'b1 ; 550 assign M_AXI_ARSIZE = clogb2((RD_DATA_WIDTH/8)-1) ; 551 assign M_AXI_ARBURST = 2'b01 ; 552 assign M_AXI_ARLOCK = 1'b0 ; 553 assign M_AXI_ARCACHE = 4'b0010 ; 554 assign M_AXI_ARPROT = 3'b000 ; 555 assign M_AXI_ARQOS = 4'b0000 ; 556 assign M_AXI_RREADY = axi_rready ; 557 558 //post 559 reg [15:0] post_hcnt ; 560 reg [15:0] post_vcnt ; 561 // 562 always@(posedge post_clk) 563 if(!M_AXI_ARESETN) 564 post_start <= 1'b0; 565 else if(rd_rd_data_count>=RD_BURST_LEN*4*RD_DATA_WIDTH/I_DW) 566 post_start <= 1'b1; 567 else 568 post_start <= post_start; 569 570 always@(posedge post_clk) 571 if(!M_AXI_ARESETN) 572 post_hcnt <= 'd0; 573 else if(post_hcnt==RD_IW-1&&post_de==1'b1) 574 post_hcnt <= 'd0; 575 else if(post_de==1'b1) 576 post_hcnt <= post_hcnt + 1'b1; 577 else 578 post_hcnt <= post_hcnt; 579 580 always@(posedge post_clk) 581 if(!M_AXI_ARESETN) 582 post_vcnt <= 'd0; 583 else if(post_hcnt==RD_IW-1'b1&&post_vcnt==RD_IH-1&&post_de==1'b1) 584 post_vcnt <= 'd0; 585 else if(post_hcnt==RD_IW-1'b1&&post_de==1'b1) 586 post_vcnt <= post_vcnt + 1'b1; 587 else 588 post_vcnt <= post_vcnt; 589 590 endmodule
1 `timescale 1ns / 1ps 2 ////////////////////////////////////////////////////////////////////////////////// 3 // Company: 4 // Engineer: 5 // 6 // Create Date: 2019/05/27 22:56:38 7 // Design Name: 8 // Module Name: data_joint 9 // Project Name: 10 // Target Devices: 11 // Tool Versions: 12 // Description: 13 // 14 // Dependencies: 15 // 16 // Revision: 17 // Revision 0.01 - File Created 18 // Additional Comments: 19 // 20 ////////////////////////////////////////////////////////////////////////////////// 21 22 23 module data_joint #( 24 parameter IW_WIDTH=16, 25 parameter OW_WIDTH=64 26 ) 27 ( 28 input clk , 29 input rst_n , 30 input i_data_de , 31 input [IW_WIDTH-1:0] i_data , 32 output reg o_data_de , 33 output reg [OW_WIDTH-1:0] o_data 34 ); 35 36 reg [7:0] cnt; 37 38 39 localparam integer num = OW_WIDTH/IW_WIDTH; 40 41 always@(posedge clk) 42 if(!rst_n) 43 cnt <= 8'd0; 44 else if(cnt==num-1&&i_data_de) 45 cnt <= 8'd0; 46 else if(i_data_de==1'b1&&num>1) 47 cnt <= cnt + 1'b1; 48 else 49 cnt <= cnt; 50 51 always@(posedge clk) 52 if(!rst_n) 53 o_data <= {OW_WIDTH{1'b0}}; 54 else if(i_data_de==1'b1&&num>1) 55 o_data <= {o_data[OW_WIDTH-IW_WIDTH-1:0],i_data}; 56 else if(num==1) 57 o_data <= i_data; 58 else 59 o_data <= o_data; 60 61 always@(posedge clk) 62 if(!rst_n) 63 o_data_de <= 1'b0; 64 else if(cnt==num-1&&i_data_de&&num>1) 65 o_data_de <= 1'b1; 66 else if(num==1) 67 o_data_de <= i_data_de; 68 else 69 o_data_de <= 1'b0; 70 71 72 endmodule
脉冲延迟模块
1 `timescale 1ns / 1ps 2 ////////////////////////////////////////////////////////////////////////////////// 3 // Company: 4 // Engineer: 5 // 6 // Create Date: 2022/01/09 16:47:38 7 // Design Name: 8 // Module Name: data_sync_ext 9 // Project Name: 10 // Target Devices: 11 // Tool Versions: 12 // Description: 13 // 14 // Dependencies: 15 // 16 // Revision: 17 // Revision 0.01 - File Created 18 // Additional Comments: 19 // 20 ////////////////////////////////////////////////////////////////////////////////// 21 module data_sync_ext( 22 input clka , 23 input rst_n , 24 input pulse_a , 25 output reg ext_pulse_a 26 ); 27 28 reg [7:0] pulse_a_r ; 29 30 always@(posedge clka) 31 if(!rst_n) 32 pulse_a_r <= 8'd0; 33 else 34 pulse_a_r <= {pulse_a_r[6:0],pulse_a}; 35 36 always@(posedge clka) 37 if(!rst_n) 38 ext_pulse_a <= 1'b0; 39 else 40 ext_pulse_a <= |pulse_a_r; 41 42 43 endmodule
数据拼接模块,另一个方法是使用读写位宽不同的FIFO进行缓存,但是要考虑数据的排列顺序,先进入的数据会放到高位,最后读取时,也是高位先出
(1条消息) 读写位宽不同的FIFO,数据输入输出顺序是怎么样的?BRAM又如何呢?_视觉患者leon的博客-CSDN博客
1 `timescale 1ns / 1ps 2 ////////////////////////////////////////////////////////////////////////////////// 3 // Company: 4 // Engineer: 5 // 6 // Create Date: 2019/05/27 22:56:38 7 // Design Name: 8 // Module Name: data_joint 9 // Project Name: 10 // Target Devices: 11 // Tool Versions: 12 // Description: 13 // 14 // Dependencies: 15 // 16 // Revision: 17 // Revision 0.01 - File Created 18 // Additional Comments: 19 // 20 ////////////////////////////////////////////////////////////////////////////////// 21 22 23 module data_joint #( 24 parameter IW_WIDTH=16, 25 parameter OW_WIDTH=64 26 ) 27 ( 28 input clk , 29 input rst_n , 30 input i_data_de , 31 input [IW_WIDTH-1:0] i_data , 32 output reg o_data_de , 33 output reg [OW_WIDTH-1:0] o_data 34 ); 35 36 reg [7:0] cnt; 37 38 39 localparam integer num = OW_WIDTH/IW_WIDTH; 40 41 always@(posedge clk) 42 if(!rst_n) 43 cnt <= 8'd0; 44 else if(cnt==num-1&&i_data_de) 45 cnt <= 8'd0; 46 else if(i_data_de==1'b1&&num>1) 47 cnt <= cnt + 1'b1; 48 else 49 cnt <= cnt; 50 51 always@(posedge clk) 52 if(!rst_n) 53 o_data <= {OW_WIDTH{1'b0}}; 54 else if(i_data_de==1'b1&&num>1) 55 o_data <= {o_data[OW_WIDTH-IW_WIDTH-1:0],i_data}; 56 else if(num==1) 57 o_data <= i_data; 58 else 59 o_data <= o_data; 60 61 always@(posedge clk) 62 if(!rst_n) 63 o_data_de <= 1'b0; 64 else if(cnt==num-1&&i_data_de&&num>1) 65 o_data_de <= 1'b1; 66 else if(num==1) 67 o_data_de <= i_data_de; 68 else 69 o_data_de <= 1'b0; 70 71 72 endmodule
注意!!! 每帧的VS上升沿需要对写FIFO复位,且复位周期大概在240ns,此时数据不能写进去,所以如果图像vs 和 de 信号间隔很近,需要对de信号进行适当的延时