DMA研究:多缓存区管理和标志信号设计
代码中很多不对齐的情况来源于:
我使用了VIVADO的AXI 模板进行调整和书写,其中官方使用了制表符和缩进,我本地则是使用空格缩进,没有对官方的代码缩进方式进行替换导致的,太多了,而且我本地看没影响,请见谅!
个人浅见:
1.不要用读同步来复位FIFO,因为读相对写来的更快,且读写都复位对总线的利用会造成更大的消耗,地址管理也更复杂了;
2.如果不使用读同步来复位FIFO,就会导致错位问题,当然错位问题可以用写同步完成,可是进而“热拔插”的处理就变难了, 暂不考虑这点;
提供三个版本的代码:
读写均复位不多帧缓存;
读写均复位多帧缓存(存在问题);
写复位多帧缓存;
已经更新第四个版本。
第一个版本:
第一版代码,简陋,但是能用,会导致撕裂,也没有做PING-PANG。
`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 2023/10/28 16:03:50 // Design Name: // Module Name: Axi_Mig_ctrl // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module Axi_Mig_ctrl #( parameter Buff_NUM = 3 , parameter W_Brust_Length = 240 , parameter R_Brust_Length = 240 , parameter W_Data_width = 128 , parameter R_Data_width = 128 , parameter Image_width = 1920 , parameter Image_high = 1080 , parameter Wr_addr_space = 33 , parameter Rd_addr_space = 33 , parameter Aw_init_Base_Addr = 0 )( input wire ui_clk , input wire Rst_INIT_DONE , //Aw output wire [3:0] m_axi_awid , output reg [Wr_addr_space-1:0] m_axi_awaddr , output wire [7:0] m_axi_awlen , output wire [2:0] m_axi_awsize , output wire [1:0] m_axi_awburst , output wire m_axi_awlock , output wire [3:0] m_axi_awcache , output wire [2:0] m_axi_awprot , output wire [3:0] m_axi_awqos , output reg m_axi_awvalid , input wire m_axi_awready , //w output wire [W_Data_width-1:0] m_axi_wdata , output wire [15:0] m_axi_wstrb , output wire m_axi_wlast , output reg m_axi_wvalid , input wire m_axi_wready , //b input wire [3:0] m_axi_bid , input wire [1:0] m_axi_bresp , input wire m_axi_bvalid , output reg m_axi_bready , //Ar output wire [3:0] m_axi_arid , output reg [Rd_addr_space-1:0] m_axi_araddr , output wire [7:0] m_axi_arlen , output wire [2:0] m_axi_arsize , output wire [1:0] m_axi_arburst , output wire m_axi_arlock , output wire [3:0] m_axi_arcache , output wire [2:0] m_axi_arprot , output wire [3:0] m_axi_arqos , output reg m_axi_arvalid , input wire m_axi_arready , //r input wire [3:0] m_axi_rid , input wire [R_Data_width-1:0] m_axi_rdata , input wire [1:0] m_axi_rresp ,//Read response input wire m_axi_rlast , input wire m_axi_rvalid , output reg m_axi_rready , //FIFO_wdata input wire Aw_Wr_trigger , output wire wdata_fifo_Rd_en , input wire [W_Data_width-1:0] wdata_fifo_Rd_data , //FIFO_rdata input wire R_Rd_trigger , output wire rdata_fifo_Wr_en , output wire [R_Data_width-1:0] rdata_fifo_wr_data , //Sync input wire Rd_Rst_Sync , input wire Wr_Rst_Sync , input wire Wr_Clk , input wire Rd_Clk // output reg Rd_Start_DDR3 ); //========================================= Define Ports =========================================// localparam Awaddr_Offset = (W_Data_width)*(W_Brust_Length)/8 ; localparam Araddr_Offset = (R_Data_width)*(R_Brust_Length)/8 ; localparam Total_Frame = (Image_width)*(Image_high)*2 ; localparam Awaddr_max = Total_Frame - (Awaddr_Offset) ; localparam Araddr_max = Total_Frame - (Araddr_Offset) ; localparam Aw_Size = $clog2((W_Data_width/8)-1) ; localparam Ar_Size = $clog2((R_Data_width/8)-1) ; //========================================= Define Ports =========================================// reg [1:0] Wr_Cnt; always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 'd0) begin Wr_Cnt <= 'd0; end else if(Wr_Cnt != 2'd3) begin if(m_axi_bready == 1'b1 && m_axi_bvalid == 1'b1) begin Wr_Cnt <= Wr_Cnt + 1'b1; end else begin Wr_Cnt <= Wr_Cnt; end end else begin Wr_Cnt <= Wr_Cnt; end end // always @(posedge ui_clk or negedge Rst_INIT_DONE) begin // if(Rst_INIT_DONE == 'd0) begin // Rd_Start_DDR3 <= 'd0; // end else if(Wr_Cnt == 2'd3) begin // Rd_Start_DDR3 <= 1'b1; // end else begin // Rd_Start_DDR3 <= Rd_Start_DDR3; // end // end //W_Sync reg [20:0] r_Wr_Rst_Sync ; wire High_Wr_Rst_Sync ; reg r_High_Wr_Rst_Sync ; wire Pose_Wr_Rst_Sync ; reg r_Pose_Wr_Rst_Sync ; always @(posedge Wr_Clk) begin if(Rst_INIT_DONE == 'd0) begin r_Wr_Rst_Sync <= 'd0; end else begin r_Wr_Rst_Sync <= {r_Wr_Rst_Sync[19:0],Wr_Rst_Sync}; end end assign High_Wr_Rst_Sync = |r_Wr_Rst_Sync; always @(posedge ui_clk) begin r_High_Wr_Rst_Sync <= High_Wr_Rst_Sync; end assign Pose_Wr_Rst_Sync = (High_Wr_Rst_Sync)&&(!r_High_Wr_Rst_Sync); //wr_index reg [2:0] wr_index ; reg [Wr_addr_space-1:0] wr_base_addr; always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin wr_index <= 'd1; end else if(Pose_Wr_Rst_Sync == 1'b1 && wr_index == Buff_NUM) begin wr_index <= 'd1; end else if(Pose_Wr_Rst_Sync == 1'b1) begin wr_index <= wr_index + 1'b1; end end always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin wr_base_addr <= Aw_init_Base_Addr; end else if(Pose_Wr_Rst_Sync == 1'b1 && wr_index == Buff_NUM) begin wr_base_addr <= Aw_init_Base_Addr; end else if(Pose_Wr_Rst_Sync == 1'b1) begin wr_base_addr <= wr_base_addr + Total_Frame; end end always @(posedge ui_clk) begin r_Pose_Wr_Rst_Sync <= Pose_Wr_Rst_Sync; end //Aw //Aw reg [7:0] w_brust_cnt; reg Aw_running ; //ConFig assign m_axi_awid = 1'b0 ; assign m_axi_awlen = W_Brust_Length - 1'b1 ; assign m_axi_awsize = Aw_Size ; assign m_axi_awburst = 1'b1 ; assign m_axi_awlock = 1'b0 ; assign m_axi_awcache = 1'b0 ; assign m_axi_awprot = 1'b0 ; assign m_axi_awqos = 1'b0 ; //Aw_running always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin Aw_running <= 'd0; end else if(r_Pose_Wr_Rst_Sync == 1'b1) begin Aw_running <= 'd0; end else if(m_axi_bvalid == 1'b1 && m_axi_bready == 1'b1) begin Aw_running <= 1'b0; end else if(Aw_Wr_trigger == 1'b1 && Aw_running == 1'b0) begin Aw_running <= 1'b1; end end //m_axi_awvalid always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin m_axi_awvalid <= 1'b0; end else if(m_axi_awvalid == 1'b1 && m_axi_awready == 1'b1) begin m_axi_awvalid <= 1'b0; end else if(Aw_Wr_trigger == 1'b1 && Aw_running == 1'b0) begin m_axi_awvalid <= 1'b1; end end //m_axi_awaddr always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin m_axi_awaddr <= 'd0; end else if(r_Pose_Wr_Rst_Sync == 1'b1) begin m_axi_awaddr <= 'd0; end else if(m_axi_awvalid == 1'b1 && m_axi_awready && m_axi_awaddr == Awaddr_max) begin m_axi_awaddr <= 'd0; end else if(m_axi_awvalid == 1'b1 && m_axi_awready == 1'b1) begin m_axi_awaddr <= m_axi_awaddr + Awaddr_Offset; end end // always @(posedge ui_clk or negedge Rst_INIT_DONE) begin // if(Rst_INIT_DONE == 0) begin // m_axi_awaddr <= 'd0; // end else if(r_Pose_Wr_Rst_Sync == 1'b1) begin // m_axi_awaddr <= wr_base_addr; // // end else if(m_axi_awvalid == 1'b1 && m_axi_awready && m_axi_awaddr == wr_base_addr + Awaddr_max) begin // // m_axi_awaddr <= wr_base_addr; // end else if(m_axi_awvalid == 1'b1 && m_axi_awready == 1'b1) begin // m_axi_awaddr <= m_axi_awaddr + Awaddr_Offset; // end // end //w assign m_axi_wdata = wdata_fifo_Rd_data; assign wdata_fifo_Rd_en = ((m_axi_wvalid == 1'b1)&&(m_axi_wready == 1'b1))?1'b1:1'b0; assign m_axi_wstrb = {(W_Data_width/8){1'b1}}; assign m_axi_wlast = (w_brust_cnt == W_Brust_Length - 1'b1)?1'b1:1'b0; //w_brust_cnt always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin w_brust_cnt <= 'd0; end else if((m_axi_wvalid == 1'b1)&&(m_axi_wready == 1'b1)) begin if(w_brust_cnt == W_Brust_Length - 1'b1) begin w_brust_cnt <= 'd0; end else begin w_brust_cnt <= w_brust_cnt + 1'b1; end end else begin w_brust_cnt <= w_brust_cnt; end end //m_axi_wvalid always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin m_axi_wvalid <= 'd0; end else if(r_Pose_Wr_Rst_Sync == 1'b1) begin m_axi_wvalid <= 'd0; end else if(m_axi_wvalid == 1'b1 && m_axi_wready == 1'b1 && m_axi_wlast == 1'b1) begin m_axi_wvalid <= 'd0; end else if(m_axi_awvalid == 1'b1 && m_axi_awready == 1'b1) begin m_axi_wvalid <= 1'b1; end end //m_axi_bready always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin m_axi_bready <= 'd0; end else if(m_axi_bready == 1'b1 && m_axi_bvalid == 1'b1) begin m_axi_bready <= 'd0; end else if(m_axi_wvalid == 1'b1 && m_axi_wready == 1'b1 && m_axi_wlast == 1'b1) begin m_axi_bready <= 1'b1; end end //R_Sync reg [1:0] r_Rd_Rst_Sync ; always @(posedge ui_clk) begin r_Rd_Rst_Sync <= {r_Rd_Rst_Sync[0],Rd_Rst_Sync}; end reg [Rd_addr_space-1:0] rd_base_addr ; reg [Rd_addr_space-1:0] r_rd_base_addr; reg [2:0] rd_index ; reg [2:0] r_rd_index ; always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin rd_index <= 'd0; end else if(wr_index > 'd1) begin rd_index <= wr_index - 1'b1; end else begin rd_index <= Buff_NUM; end end always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin r_rd_index <= 'd0; end else begin r_rd_index <= rd_index; end end always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin rd_base_addr <= 'd0; end else if(r_Rd_Rst_Sync[1] == 1'b1)begin rd_base_addr <= (r_rd_index)*(Total_Frame); end end always @(posedge ui_clk) begin r_rd_base_addr <= rd_base_addr; end //Ar reg Ar_running ; //ConFig assign m_axi_arid = 'd0 ; assign m_axi_arlen = R_Brust_Length - 1'b1 ; assign m_axi_arsize = Ar_Size ; assign m_axi_arburst = 1'b1 ; assign m_axi_arlock = 'd0 ; assign m_axi_arcache = 'd0 ; assign m_axi_arprot = 'd0 ; assign m_axi_arqos = 'd0 ; //Ar_running always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin Ar_running <= 'd0; end else if(r_Rd_Rst_Sync[1] == 1'b1) begin Ar_running <= 'd0; end else if(m_axi_rlast == 1'b1 && m_axi_rvalid == 1'b1 && m_axi_rready == 1'b1) begin Ar_running <= 'd0; end else if(R_Rd_trigger == 1'b1 && Ar_running == 'd0) begin Ar_running <= 1'b1; end end //m_axi_araddr always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin m_axi_araddr <= 'd0; end else if(r_Rd_Rst_Sync[1] == 1'b1) begin m_axi_araddr <= 'd0; end else if(m_axi_arvalid == 1'b1 && m_axi_arready == 1'b1 && m_axi_araddr == r_rd_base_addr + Araddr_max) begin m_axi_araddr <= 'd0; end else if(m_axi_arvalid == 1'b1 && m_axi_arready == 1'b1) m_axi_araddr <= m_axi_araddr + Araddr_Offset; end // always @(posedge ui_clk or negedge Rst_INIT_DONE) begin // if(Rst_INIT_DONE == 0) begin // m_axi_araddr <= 'd0; // end else if(r_Rd_Rst_Sync[1] == 1'b1) begin // m_axi_araddr <= r_rd_base_addr; // end else if(m_axi_arvalid == 1'b1 && m_axi_arready == 1'b1 && m_axi_araddr == r_rd_base_addr + Araddr_max) begin // m_axi_araddr <= r_rd_base_addr; // end else if(m_axi_arvalid == 1'b1 && m_axi_arready == 1'b1) // m_axi_araddr <= m_axi_araddr + Araddr_Offset; // end //m_axi_arvalid always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin m_axi_arvalid <= 'd0; end else if(r_Rd_Rst_Sync[1] == 1'b1) begin m_axi_arvalid <= 'd0; end else if(m_axi_arvalid == 1'b1 && m_axi_arready == 1'b1) begin m_axi_arvalid <= 'd0; end else if(R_Rd_trigger == 1'b1 && Ar_running == 'd0) begin m_axi_arvalid <= 1'b1; end end //r assign rdata_fifo_Wr_en = ((m_axi_rvalid == 1'b1) && (m_axi_rready == 1'b1))?1'b1:1'b0; assign rdata_fifo_wr_data = m_axi_rdata; always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin m_axi_rready <= 'd0; end else if(r_Rd_Rst_Sync[1] == 1'b1) begin m_axi_rready <= 'd0; end else if(m_axi_rready == 1'b1 && m_axi_rvalid == 1'b1 && m_axi_rlast == 1'b1) begin m_axi_rready <= 'd0; end else if(m_axi_arvalid == 1'b1 && m_axi_arready == 1'b1) begin m_axi_rready <= 1'b1; end end // ila_1 your_instance_name ( // .clk(ui_clk), // input wire clk // .probe0(r_Pose_Wr_Rst_Sync), // input wire [0:0] probe0 // .probe1(r_Rd_Rst_Sync[1]) // input wire [0:0] probe1 // ); endmodule
第二个版本:
多帧缓存,但是地址管理得不好,存在很多问题;
`timescale 1ns / 1ps module DMA_Custom #( parameter Buff_NUM = 3 , parameter W_Brust_Length = 240 , parameter R_Brust_Length = 240 , parameter W_Data_width = 128 , parameter R_Data_width = 128 , parameter Image_width = 1920 , parameter Image_high = 1080 , parameter Wr_addr_space = 33 , parameter Rd_addr_space = 33 , parameter Aw_init_Base_Addr = 0 )( input wire ui_clk , input wire Rst_INIT_DONE , //Aw output wire [3:0] m_axi_awid , output reg [Wr_addr_space-1:0] m_axi_awaddr , output wire [7:0] m_axi_awlen , output wire [2:0] m_axi_awsize , output wire [1:0] m_axi_awburst , output wire m_axi_awlock , output wire [3:0] m_axi_awcache , output wire [2:0] m_axi_awprot , output wire [3:0] m_axi_awqos , output reg m_axi_awvalid , input wire m_axi_awready , //w output wire [W_Data_width-1:0] m_axi_wdata , output wire [15:0] m_axi_wstrb , output wire m_axi_wlast , output reg m_axi_wvalid , input wire m_axi_wready , //b input wire [3:0] m_axi_bid , input wire [1:0] m_axi_bresp , input wire m_axi_bvalid , output reg m_axi_bready , //Ar output wire [3:0] m_axi_arid , output reg [Rd_addr_space-1:0] m_axi_araddr , output wire [7:0] m_axi_arlen , output wire [2:0] m_axi_arsize , output wire [1:0] m_axi_arburst , output wire m_axi_arlock , output wire [3:0] m_axi_arcache , output wire [2:0] m_axi_arprot , output wire [3:0] m_axi_arqos , output reg m_axi_arvalid , input wire m_axi_arready , //r input wire [3:0] m_axi_rid , input wire [R_Data_width-1:0] m_axi_rdata , input wire [1:0] m_axi_rresp ,//Read response input wire m_axi_rlast , input wire m_axi_rvalid , output reg m_axi_rready , //FIFO_wdata input wire Aw_Wr_trigger , output wire wdata_fifo_Rd_en , input wire [W_Data_width-1:0] wdata_fifo_Rd_data , //FIFO_rdata input wire R_Rd_trigger , output wire rdata_fifo_Wr_en , output wire [R_Data_width-1:0] rdata_fifo_wr_data , //Sync input wire Rd_Rst_Sync , input wire Wr_Rst_Sync , input wire Wr_Clk , input wire Rd_Clk // output reg Rd_Start_DDR3 ); //========================================= Define Ports =========================================// localparam Awaddr_Brust_Offset = (W_Data_width)*(W_Brust_Length)/8 ; localparam Araddr_Brust_Offset = (R_Data_width)*(R_Brust_Length)/8 ; localparam One_Frame_Size = (Image_width)*(Image_high)*2 ; localparam Awaddr_Brust_max = One_Frame_Size - (Awaddr_Brust_Offset) ; localparam Araddr_Brust_max = One_Frame_Size - (Araddr_Brust_Offset) ; localparam Aw_Size = $clog2((W_Data_width/8)-1) ; localparam Ar_Size = $clog2((R_Data_width/8)-1) ; localparam RAM_Start_1 = 0 ; localparam RAM_Start_2 = One_Frame_Size ; localparam RAM_Start_3 = One_Frame_Size*2 ; //========================================= Define Ports =========================================// // W_Sync ----------------------------------------------------------------------------------------// reg [4:0] reg_Wr_Rst_Sync ; wire High_Wr_Rst_Sync ; reg r_High_Wr_Rst_Sync ; wire Pose_Wr_Rst_Sync ; wire Nege_Wr_Rst_Sync ; reg r_Pose_Wr_Rst_Sync ; always @(posedge Wr_Clk) begin reg_Wr_Rst_Sync <= {reg_Wr_Rst_Sync[3:0],Wr_Rst_Sync}; end assign High_Wr_Rst_Sync = |reg_Wr_Rst_Sync; always @(posedge ui_clk) begin r_High_Wr_Rst_Sync <= High_Wr_Rst_Sync; r_Pose_Wr_Rst_Sync <= Pose_Wr_Rst_Sync; end assign Pose_Wr_Rst_Sync = ( High_Wr_Rst_Sync)&&(!r_High_Wr_Rst_Sync); assign Nege_Wr_Rst_Sync = (!High_Wr_Rst_Sync)&&( r_High_Wr_Rst_Sync); // W_Sync ----------------------------------------------------------------------------------------// // wr_index --------------------------------------------------------------------------------------// reg [2:0] wr_index ; reg [Wr_addr_space-1:0] wr_base_addr; always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin wr_index <= 'd1; end else if(Pose_Wr_Rst_Sync == 1'b1 && wr_index == Buff_NUM) begin wr_index <= 'd1; end else if(Pose_Wr_Rst_Sync == 1'b1) begin wr_index <= wr_index + 1'b1; end end always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin wr_base_addr <= Aw_init_Base_Addr; end else if(Pose_Wr_Rst_Sync == 1'b1) begin case (wr_index) 3'd1:begin wr_base_addr <= RAM_Start_1; end 3'd2:begin wr_base_addr <= RAM_Start_2; end 3'd3:begin wr_base_addr <= RAM_Start_3; end default:begin wr_base_addr <= RAM_Start_1; end endcase end else begin wr_base_addr <= wr_base_addr; end end // wr_index --------------------------------------------------------------------------------------// // Aw------ --------------------------------------------------------------------------------------// //Aw reg [7:0] w_brust_cnt; reg Aw_running ; //ConFig assign m_axi_awid = 1'b0 ; assign m_axi_awlen = W_Brust_Length - 1'b1 ; assign m_axi_awsize = Aw_Size ; assign m_axi_awburst = 1'b1 ; assign m_axi_awlock = 1'b0 ; assign m_axi_awcache = 1'b0 ; assign m_axi_awprot = 1'b0 ; assign m_axi_awqos = 1'b0 ; //Aw_running always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin Aw_running <= 'd0; end else if(m_axi_bvalid == 1'b1 && m_axi_bready == 1'b1) begin Aw_running <= 1'b0; end else if(Aw_Wr_trigger == 1'b1 && Aw_running == 1'b0) begin Aw_running <= 1'b1; end end //m_axi_awvalid always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin m_axi_awvalid <= 1'b0; end else if(m_axi_awvalid == 1'b1 && m_axi_awready == 1'b1) begin m_axi_awvalid <= 1'b0; end else if(Aw_Wr_trigger == 1'b1 && Aw_running == 1'b0) begin m_axi_awvalid <= 1'b1; end end //m_axi_awaddr always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin m_axi_awaddr <= 'd0; end else if(r_Pose_Wr_Rst_Sync == 1'b1) begin m_axi_awaddr <= wr_base_addr; end else if(m_axi_awvalid == 1'b1 && m_axi_awready && m_axi_awaddr == Awaddr_Brust_max) begin m_axi_awaddr <= wr_base_addr; end else if(m_axi_awvalid == 1'b1 && m_axi_awready == 1'b1) begin m_axi_awaddr <= m_axi_awaddr + Awaddr_Brust_Offset; end end // Aw---------------------------------------------------------------------------------------------// // w----------------------------------------------------------------------------------------------// assign m_axi_wdata = wdata_fifo_Rd_data; assign wdata_fifo_Rd_en = ((m_axi_wvalid == 1'b1)&&(m_axi_wready == 1'b1))?1'b1:1'b0; assign m_axi_wstrb = {(W_Data_width/8){1'b1}}; assign m_axi_wlast = (w_brust_cnt == W_Brust_Length - 1'b1)?1'b1:1'b0; //w_brust_cnt always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin w_brust_cnt <= 'd0; end else if((m_axi_wvalid == 1'b1)&&(m_axi_wready == 1'b1)) begin if(w_brust_cnt == W_Brust_Length - 1'b1) begin w_brust_cnt <= 'd0; end else begin w_brust_cnt <= w_brust_cnt + 1'b1; end end else begin w_brust_cnt <= w_brust_cnt; end end //m_axi_wvalid always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin m_axi_wvalid <= 'd0; end else if(r_Pose_Wr_Rst_Sync == 1'b1) begin m_axi_wvalid <= 'd0; end else if(m_axi_wvalid == 1'b1 && m_axi_wready == 1'b1 && m_axi_wlast == 1'b1) begin m_axi_wvalid <= 'd0; end else if(m_axi_awvalid == 1'b1 && m_axi_awready == 1'b1) begin m_axi_wvalid <= 1'b1; end end // w----------------------------------------------------------------------------------------------// //m_axi_bready always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin m_axi_bready <= 'd0; end else if(m_axi_bready == 1'b1 && m_axi_bvalid == 1'b1) begin m_axi_bready <= 'd0; end else if(m_axi_wvalid == 1'b1 && m_axi_wready == 1'b1 && m_axi_wlast == 1'b1) begin m_axi_bready <= 1'b1; end end // R_Sync------------------------------------------------------------------------------------------// reg reg_Rd_Rst_Sync ; wire Pose_Rd_Rst_Sync_post ; wire Pose_Rd_Rst_Sync ; wire Nege_Rd_Rst_Sync ; reg r_Pose_Rd_Rst_Sync ; always @(posedge Rd_Clk) begin reg_Rd_Rst_Sync <= Rd_Rst_Sync; end assign Pose_Rd_Rst_Sync_post = (Rd_Rst_Sync == 1'b1)&&(reg_Rd_Rst_Sync == 1'b0); data_sync_ext rd_sync_ext( .clka (Rd_Clk ), .rst_n (Rst_INIT_DONE ), .pulse_a (Pose_Rd_Rst_Sync_post ), .ext_pulse_a (Pose_Rd_Rst_Sync ) ); always @(posedge ui_clk) begin r_Pose_Rd_Rst_Sync <= Pose_Rd_Rst_Sync; end // R_Sync------------------------------------------------------------------------------------------// // rd_index----------------------------------------------------------------------------------------// reg [Rd_addr_space-1:0] rd_base_addr ; reg [2:0] rd_index ; reg [2:0] r_rd_index ; always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin rd_index <= 'd0; end else if(Pose_Rd_Rst_Sync == 1'b1 && wr_index > 'd1) begin rd_index <= wr_index - 1'b1; end else if(Pose_Rd_Rst_Sync == 1'b1)begin rd_index <= Buff_NUM; end else begin rd_index <= rd_index; end end always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin rd_base_addr <= 'd0; end else if(Pose_Rd_Rst_Sync)begin case (rd_index) 3'd1:begin rd_base_addr <= RAM_Start_1; end 3'd2:begin rd_base_addr <= RAM_Start_2; end 3'd3:begin rd_base_addr <= RAM_Start_3; end default:begin rd_base_addr <= RAM_Start_1; end endcase end else begin rd_base_addr <= rd_base_addr; end end // rd_index----------------------------------------------------------------------------------------// // Ar----------------------------------------------------------------------------------------------// reg Ar_running ; //ConFig assign m_axi_arid = 'd0 ; assign m_axi_arlen = R_Brust_Length - 1'b1 ; assign m_axi_arsize = Ar_Size ; assign m_axi_arburst = 1'b1 ; assign m_axi_arlock = 'd0 ; assign m_axi_arcache = 'd0 ; assign m_axi_arprot = 'd0 ; assign m_axi_arqos = 'd0 ; //Ar_running always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin Ar_running <= 'd0; end else if(r_Pose_Rd_Rst_Sync == 1'b1) begin Ar_running <= 'd0; end else if(m_axi_rlast == 1'b1 && m_axi_rvalid == 1'b1 && m_axi_rready == 1'b1) begin Ar_running <= 'd0; end else if(R_Rd_trigger == 1'b1 && Ar_running == 'd0) begin Ar_running <= 1'b1; end end //m_axi_araddr always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin m_axi_araddr <= 'd0; end else if(r_Pose_Rd_Rst_Sync == 1'b1) begin m_axi_araddr <= rd_base_addr; end else if(m_axi_arvalid == 1'b1 && m_axi_arready == 1'b1 && m_axi_araddr == rd_base_addr + Araddr_Brust_max) begin m_axi_araddr <= rd_base_addr; end else if(m_axi_arvalid == 1'b1 && m_axi_arready == 1'b1) m_axi_araddr <= m_axi_araddr + Araddr_Brust_Offset; end //m_axi_arvalid always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin m_axi_arvalid <= 'd0; end else if(r_Pose_Rd_Rst_Sync == 1'b1) begin m_axi_arvalid <= 'd0; end else if(m_axi_arvalid == 1'b1 && m_axi_arready == 1'b1) begin m_axi_arvalid <= 'd0; end else if(R_Rd_trigger == 1'b1 && Ar_running == 'd0) begin m_axi_arvalid <= 1'b1; end end // Ar----------------------------------------------------------------------------------------------// // r-----------------------------------------------------------------------------------------------// assign rdata_fifo_Wr_en = ((m_axi_rvalid == 1'b1) && (m_axi_rready == 1'b1))?1'b1:1'b0; assign rdata_fifo_wr_data = m_axi_rdata; always @(posedge ui_clk or negedge Rst_INIT_DONE) begin if(Rst_INIT_DONE == 0) begin m_axi_rready <= 'd0; end else if(r_Pose_Rd_Rst_Sync == 1'b1) begin m_axi_rready <= 'd0; end else if(m_axi_rready == 1'b1 && m_axi_rvalid == 1'b1 && m_axi_rlast == 1'b1) begin m_axi_rready <= 'd0; end else if(m_axi_arvalid == 1'b1 && m_axi_arready == 1'b1) begin m_axi_rready <= 1'b1; end end // r-----------------------------------------------------------------------------------------------// ila_0 ila_0 ( .clk(ui_clk), // input wire clk .probe0(Pose_Wr_Rst_Sync), // input wire [15:0] probe0 .probe1(wr_base_addr), // input wire [15:0] probe1 .probe2(wr_index), // input wire [0:0] probe2 .probe3(Aw_running), // input wire [0:0] probe3 .probe4(m_axi_awaddr), // input wire [31:0] probe4 .probe5(Pose_Rd_Rst_Sync), // input wire [31:0] probe5 .probe6(rd_base_addr), // input wire [2:0] probe6 .probe7(rd_index), // input wire [0:0] probe7 .probe8(Ar_running), // input wire [0:0] probe8 .probe9(m_axi_araddr) // input wire [0:0] probe9 ); endmodule
第三个版本:
多帧缓存,写复位,个人认为是较好的版本。
`timescale 1 ns / 1 ps module DMA_Custom # ( parameter C_M_TARGET_SLAVE_BASE_ADDR = 32'h2000000, parameter integer C_M_AXI_BURST_LEN = 256 , parameter integer C_M_AXI_ID_WIDTH = 1 , parameter integer C_M_AXI_ADDR_WIDTH = 32 , parameter integer C_M_AXI_DATA_WIDTH = 64 , parameter integer C_M_AXI_AWUSER_WIDTH = 0 , parameter integer C_M_AXI_ARUSER_WIDTH = 0 , parameter integer C_M_AXI_WUSER_WIDTH = 0 , parameter integer C_M_AXI_RUSER_WIDTH = 0 , parameter integer C_M_AXI_BUSER_WIDTH = 0 , parameter I_image_w = 1920 , parameter I_image_h = 1080 , parameter Pixel_byte_num = 4 , parameter AXI_Buff_NUM = 3 , parameter Input_Data_width = 24 ) ( input wire M_AXI_ACLK , input wire M_AXI_ARESETN , output wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_AWID , output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_AWADDR , output wire [7 : 0] M_AXI_AWLEN , output wire [2 : 0] M_AXI_AWSIZE , output wire [1 : 0] M_AXI_AWBURST , output wire M_AXI_AWLOCK , output wire [3 : 0] M_AXI_AWCACHE , output wire [2 : 0] M_AXI_AWPROT , output wire [3 : 0] M_AXI_AWQOS , output wire [C_M_AXI_AWUSER_WIDTH-1 : 0] M_AXI_AWUSER , output wire M_AXI_AWVALID , input wire M_AXI_AWREADY , output wire [C_M_AXI_DATA_WIDTH-1 : 0] M_AXI_WDATA , output wire [C_M_AXI_DATA_WIDTH/8-1 : 0] M_AXI_WSTRB , output wire M_AXI_WLAST , output wire [C_M_AXI_WUSER_WIDTH-1 : 0] M_AXI_WUSER , output wire M_AXI_WVALID , input wire M_AXI_WREADY , input wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_BID, input wire [1 : 0] M_AXI_BRESP , input wire [C_M_AXI_BUSER_WIDTH-1 : 0] M_AXI_BUSER , input wire M_AXI_BVALID , output wire M_AXI_BREADY , output wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_ARID , output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_ARADDR , output wire [7 : 0] M_AXI_ARLEN , output wire [2 : 0] M_AXI_ARSIZE , output wire [1 : 0] M_AXI_ARBURST , output wire M_AXI_ARLOCK , output wire [3 : 0] M_AXI_ARCACHE , output wire [2 : 0] M_AXI_ARPROT , output wire [3 : 0] M_AXI_ARQOS , output wire [C_M_AXI_ARUSER_WIDTH-1 : 0] M_AXI_ARUSER , output wire M_AXI_ARVALID , input wire M_AXI_ARREADY , input wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_RID , input wire [C_M_AXI_DATA_WIDTH-1 : 0] M_AXI_RDATA , input wire [1 : 0] M_AXI_RRESP , input wire M_AXI_RLAST , input wire [C_M_AXI_RUSER_WIDTH-1 : 0] M_AXI_RUSER , input wire M_AXI_RVALID , output wire M_AXI_RREADY , //Custom input wire I_Pre_clk , input wire I_Pre_vs , input wire [Input_Data_width-1:0] I_Pre_data , input wire I_Pre_de , input wire I_Post_clk , output wire O_Post_Start , output wire [Input_Data_width-1:0] O_Post_data , input wire I_Post_de , input wire I_Post_vs ); function integer clogb2 (input integer bit_depth); begin for(clogb2=0; bit_depth>0; clogb2=clogb2+1) bit_depth = bit_depth >> 1; end endfunction //========================================= Define Ports =========================================// localparam integer C_TRANSACTIONS_NUM = clogb2(C_M_AXI_BURST_LEN-1) ; localparam Awaddr_Brust_Offset = (C_M_AXI_DATA_WIDTH)*(C_M_AXI_BURST_LEN)/8 ; localparam Araddr_Brust_Offset = (C_M_AXI_DATA_WIDTH)*(C_M_AXI_BURST_LEN)/8 ; localparam Total_Frame_Offset = I_image_w*I_image_h*Pixel_byte_num ; localparam RAM_1_start_addr = 0 ; localparam RAM_2_start_addr = Total_Frame_Offset ; localparam RAM_3_start_addr = Total_Frame_Offset*2 ; localparam wr_burst_times = I_image_w*I_image_h*Pixel_byte_num /Awaddr_Brust_Offset ; localparam rd_burst_times = I_image_w*I_image_h*Pixel_byte_num /Araddr_Brust_Offset ; //========================================= Define Ports =========================================// // AXI4LITE signals //AXI4 internal temp signals reg [C_M_AXI_ADDR_WIDTH-1 : 0] axi_awaddr ; reg axi_awvalid ; reg axi_wlast ; reg axi_wvalid ; reg [C_TRANSACTIONS_NUM-1:0] wr_burst_cnt ; reg axi_bready ; reg [C_M_AXI_ADDR_WIDTH-1 : 0] axi_araddr ; reg axi_arvalid ; reg axi_rready ; //W_FIFO wire wr_fifo_wr_en ; wire [C_M_AXI_DATA_WIDTH-1 : 0] wr_fifo_wr_data ; wire wr_fifo_rd_en ; wire [C_M_AXI_DATA_WIDTH-1 : 0] wr_fifo_rd_data ; wire full_w ; wire empty_w ; wire [15 : 0] w_rd_data_count ; wire [15 : 0] w_wr_data_count ; //r_FIFO wire rd_fifo_wr_en ; wire [C_M_AXI_DATA_WIDTH-1 : 0] rd_fifo_wr_data ; wire rd_fifo_rd_en ; wire [31 : 0] rd_fifo_rd_data ; wire [12 : 0] r_rd_data_count ; wire [11 : 0] r_wr_data_count ; wire full_r ; wire empty_r ; reg [15:0] rd_hcnt ; reg [15:0] rd_vcnt ; //I/O Connections. Write Address (AW) assign M_AXI_AWID = 'b0; assign M_AXI_AWADDR = C_M_TARGET_SLAVE_BASE_ADDR + axi_awaddr; assign M_AXI_AWLEN = C_M_AXI_BURST_LEN - 1; assign M_AXI_AWSIZE = clogb2((C_M_AXI_DATA_WIDTH/8)-1); assign M_AXI_AWBURST = 2'b01; assign M_AXI_AWLOCK = 1'b0; assign M_AXI_AWCACHE = 4'b0010; assign M_AXI_AWPROT = 3'h0; assign M_AXI_AWQOS = 4'h0; assign M_AXI_AWUSER = 'b1; assign M_AXI_AWVALID = axi_awvalid; //Write Data(W) assign wr_fifo_rd_en = (axi_wvalid == 1'b1)&&(M_AXI_WREADY == 1'b1); assign M_AXI_WDATA = wr_fifo_rd_data; //All bursts are complete and aligned in this example assign M_AXI_WSTRB = {(C_M_AXI_DATA_WIDTH/8){1'b1}}; assign M_AXI_WLAST = axi_wlast; assign M_AXI_WUSER = 'b0; assign M_AXI_WVALID = axi_wvalid; //Write Response (B) assign M_AXI_BREADY = axi_bready; //Read Address (AR) assign M_AXI_ARID = 'b0; assign M_AXI_ARADDR = C_M_TARGET_SLAVE_BASE_ADDR + axi_araddr; assign M_AXI_ARLEN = C_M_AXI_BURST_LEN - 1; assign M_AXI_ARSIZE = clogb2((C_M_AXI_DATA_WIDTH/8)-1); assign M_AXI_ARBURST = 2'b01; assign M_AXI_ARLOCK = 1'b0; assign M_AXI_ARCACHE = 4'b0010; assign M_AXI_ARPROT = 3'h0; assign M_AXI_ARQOS = 4'h0; assign M_AXI_ARUSER = 'b1; assign M_AXI_ARVALID = axi_arvalid; //Read and Read Response (R) assign M_AXI_RREADY = axi_rready; // Wr_Sync------------------------------------------------------------------------------------------// //W Sync Port //wrclk reg r1_pre_vs ; wire Pose_pre_vs ; wire Nege_pre_vs ; wire Ext_Pose_pre_vs ; //sysclk reg sys_pre_vs ; reg r1_sys_pre_vs ; reg sys_Pose_pre_vs ; reg sys_Nege_pre_vs ; reg r_sys_Nege_pre_vs; reg [1:0] wr_index ; reg [C_M_AXI_ADDR_WIDTH-1 : 0] wr_base_addr ; always @(posedge I_Pre_clk) begin r1_pre_vs <= I_Pre_vs; end assign Pose_pre_vs = (I_Pre_vs == 1'b1)&&(r1_pre_vs == 1'b0); assign Nege_pre_vs = (I_Pre_vs == 1'b0)&&(r1_pre_vs == 1'b1); always@(posedge M_AXI_ACLK) begin sys_pre_vs <= I_Pre_vs ; r1_sys_pre_vs <= sys_pre_vs; r_sys_Nege_pre_vs <= sys_Nege_pre_vs; end always @(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 1'b0) begin sys_Pose_pre_vs <= 1'b0; sys_Nege_pre_vs <= 1'b0; end else if(sys_pre_vs==1'b1&&r1_sys_pre_vs==1'b0) begin sys_Pose_pre_vs <= 1'b1; sys_Nege_pre_vs <= 1'b0; end else if(sys_pre_vs==1'b0&&r1_sys_pre_vs==1'b1) begin sys_Pose_pre_vs <= 1'b0; sys_Nege_pre_vs <= 1'b1; end else begin sys_Pose_pre_vs <= 1'b0; sys_Nege_pre_vs <= 1'b0; end end Data_sync_ext Data_sync_ext_Inst0( .clka ( I_Pre_clk ), .rst_n ( M_AXI_ARESETN ), .pulse_a ( Pose_pre_vs ), .ext_pulse_a ( Ext_Pose_pre_vs ) ); always@(posedge M_AXI_ACLK) if(M_AXI_ARESETN == 1'b0) begin wr_index <= 'd1; end else if(sys_Nege_pre_vs == 1'b1&&wr_index == AXI_Buff_NUM) begin wr_index <= 'd1; end else if(sys_Nege_pre_vs==1'b1) begin wr_index <= wr_index + 1'b1; end else begin wr_index <= wr_index; end always@(posedge M_AXI_ACLK) if(M_AXI_ARESETN == 1'b0) begin wr_base_addr <= 0; end else if(sys_Nege_pre_vs == 1'b1&&wr_index == AXI_Buff_NUM) begin wr_base_addr <= 0; end else if(sys_Nege_pre_vs == 1'b1) begin wr_base_addr <= wr_base_addr + Total_Frame_Offset; end else begin wr_base_addr <= wr_base_addr; end // Wr_Sync------------------------------------------------------------------------------------------// assign wr_fifo_wr_en = I_Pre_de; assign wr_fifo_wr_data = {8'h0,I_Pre_data}; wdata_w64x1024_r64x1024 wdata_w32x4096_r64x2048 ( .rst ( (!M_AXI_ARESETN)|(Ext_Pose_pre_vs)), // input wire rst .wr_clk ( I_Pre_clk ), // input wire wr_clk .rd_clk ( M_AXI_ACLK ), // input wire rd_clk .din ( wr_fifo_wr_data ), // input wire [63 : 0] din .wr_en ( wr_fifo_wr_en ), // input wire wr_en .rd_en ( wr_fifo_rd_en ), // input wire rd_en .dout ( wr_fifo_rd_data ), // output wire [63 : 0] dout .full ( full_w ), // output wire full .empty ( empty_w ), // output wire empty .rd_data_count(w_rd_data_count ), // output wire [10 : 0] rd_data_count .wr_data_count(w_wr_data_count ), // output wire [10 : 0] wr_data_count .wr_rst_busy(), // output wire wr_rst_busy .rd_rst_busy() // output wire rd_rst_busy ); // w_start_control----------------------------------------------------------------------------------// //Control reg wr_brust_start ; wire wr_brust_Req ; wire wr_brust_end ; reg wr_brust_now ; assign wr_brust_Req = (w_rd_data_count>=C_M_AXI_BURST_LEN); assign wr_brust_end = (axi_wvalid==1'b1&&M_AXI_WREADY==1'b1&&wr_burst_cnt==C_M_AXI_BURST_LEN-1); //多路输入的时候,wr_brust_Req输出到仲裁器中,使用仲裁器输出的aribe_req请求完成此处wr_brust_Req的工作 always@(*) if(wr_brust_Req == 1'b1) begin wr_brust_start <= 1'b1; end else begin wr_brust_start <= 1'b0; end always@(posedge M_AXI_ACLK) if(M_AXI_ARESETN == 1'b0) begin wr_brust_now <= 1'b0; end else if(wr_brust_end == 1'b1 && wr_brust_now == 1'b1) begin wr_brust_now <= 1'b0; end else if(wr_brust_start == 1'b1 && wr_brust_now == 1'b0) begin wr_brust_now <= 1'b1; end else begin wr_brust_now <= wr_brust_now; end // w_start_control----------------------------------------------------------------------------------// // Aw------ --------------------------------------------------------------------------------------// //axi_awvalid always@(posedge M_AXI_ACLK) if(M_AXI_ARESETN == 1'b0) begin axi_awvalid <= 1'b0; end else if(axi_awvalid == 1'b1 && M_AXI_AWREADY == 1'b1) begin axi_awvalid <= 1'b0; end else if(wr_brust_start == 1'b1 && wr_brust_now == 1'b0) begin axi_awvalid <= 1'b1; end else begin axi_awvalid <= axi_awvalid; end //axi_awaddr always@(posedge M_AXI_ACLK) if(M_AXI_ARESETN == 1'b0) begin axi_awaddr <= 'd0; end else if(r_sys_Nege_pre_vs == 1'b1) begin axi_awaddr <= wr_base_addr; // end else if(r_sys_Nege_pre_vs == 1'b1) begin // axi_awaddr <= 0; end else if(axi_awvalid==1'b1 && M_AXI_AWREADY==1'b1) begin axi_awaddr <= axi_awaddr + Awaddr_Brust_Offset ; end else begin axi_awaddr <= axi_awaddr; end // Aw---------------------------------------------------------------------------------------------// // W----------------------------------------------------------------------------------------------// //axi_wvalid always@(posedge M_AXI_ACLK) if(M_AXI_ARESETN == 1'b0) begin axi_wvalid <= 1'b0; end else if(axi_wvalid==1'b1&&M_AXI_WREADY==1'b1&&wr_burst_cnt==C_M_AXI_BURST_LEN-1) begin axi_wvalid <= 1'b0; end else if(axi_awvalid==1'b1&&M_AXI_AWREADY==1'b1) begin axi_wvalid <= 1'b1; end else begin axi_wvalid <= axi_wvalid; end //wr_burst_cnt always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 1'b0) begin wr_burst_cnt <= 'd0; end else if(axi_wvalid==1'b1&&M_AXI_WREADY==1'b1&&wr_burst_cnt==C_M_AXI_BURST_LEN-1) begin wr_burst_cnt <= 'd0; end else if(axi_wvalid==1'b1&&M_AXI_WREADY==1'b1) begin wr_burst_cnt <= wr_burst_cnt + 1'b1; end else begin wr_burst_cnt <= wr_burst_cnt; end end //axi_wlast always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 1'b0) begin axi_wlast <= 1'b0; end else if(axi_wvalid==1'b1&&M_AXI_WREADY==1'b1&&wr_burst_cnt==C_M_AXI_BURST_LEN-1'b1) begin axi_wlast <= 1'b0; end else if(axi_wvalid==1'b1&&M_AXI_WREADY==1'b1&&wr_burst_cnt==C_M_AXI_BURST_LEN-2'd2) begin axi_wlast <= 1'b1; end else begin axi_wlast <= axi_wlast; end end // W----------------------------------------------------------------------------------------------// // b----------------------------------------------------------------------------------------------// always @(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 0) begin axi_bready <= 'd0; end else begin axi_bready <= 1'b1; end end // b----------------------------------------------------------------------------------------------// // r_start_control----------------------------------------------------------------------------------// //Control reg [7:0] rd_index ; reg [7:0] rd_index_ptr ; reg [C_M_AXI_ADDR_WIDTH-1 : 0] rd_base_addr ; reg rd_start_cycle ; reg [2:0] rd_start_cnt ; reg rd_brust_start ; reg rd_brust_Req ; reg rd_brust_end ; reg rd_brust_now ; reg Post_Start ; always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 0) begin rd_index <= 0; end else if(wr_index > 1) begin rd_index <= wr_index - 1'b1; end else begin rd_index <= AXI_Buff_NUM; end end always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 0) begin rd_index_ptr <= 'd0; end else begin rd_index_ptr <= rd_index - 1'b1; end end always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 0) begin rd_base_addr <= 'd0; end else begin rd_base_addr <= rd_index_ptr*Total_Frame_Offset; end end always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 0) begin rd_start_cnt <= 'd0; end else if(sys_Nege_pre_vs && rd_start_cnt[2] != 1'b1) begin rd_start_cnt <= rd_start_cnt + 1'b1; end else begin rd_start_cnt <= rd_start_cnt; end end always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 0) begin rd_start_cycle <= 1'b0; end else if(rd_start_cnt[2] == 1'b1 && full_r == 1'b0) begin rd_start_cycle <= 1'b1; end else begin rd_start_cycle <= rd_start_cycle; end end always@(posedge I_Post_clk) if(M_AXI_ARESETN == 0) begin Post_Start <= 1'b0; end else if(rd_start_cycle == 1'b1 && r_rd_data_count >= C_M_AXI_BURST_LEN) begin Post_Start <= 1'b1; end else begin Post_Start <= Post_Start; end assign O_Post_Start = Post_Start; always @(*) begin if((rd_start_cycle == 1'b1) && (r_wr_data_count < C_M_AXI_BURST_LEN*4)) begin rd_brust_Req <= 1'b1; end else begin rd_brust_Req <= 1'b0; end end always@(*) begin if((M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1)&&(M_AXI_RLAST == 1'b1)) begin rd_brust_end <= 1'b1; end else begin rd_brust_end <= 1'b0; end end //No aribe always@(*) begin if(rd_brust_Req == 1'b1) begin rd_brust_start <= 1'b1; end else begin rd_brust_start <= 1'b0; end end always@(posedge M_AXI_ACLK) if(M_AXI_ARESETN == 1'b0) begin rd_brust_now <= 1'b0; end else if(rd_brust_end == 1'b1 && rd_brust_now == 1'b1) begin rd_brust_now <= 1'b0; end else if(rd_brust_start == 1'b1 && rd_brust_now == 1'b0) begin rd_brust_now <= 1'b1; end else begin rd_brust_now <= rd_brust_now; end // r_start_control----------------------------------------------------------------------------------// // ar---------------------------------------------------------------------------------------------// always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 1'b0) begin axi_arvalid <= 1'b0; end else if(axi_arvalid==1'b1&&M_AXI_ARREADY==1'b1) begin axi_arvalid <= 1'b0; end else if(rd_brust_start == 1'b1 && rd_brust_now == 1'b0) begin axi_arvalid <= 1'b1; end else begin axi_arvalid <= axi_arvalid; end end always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 1'b0) begin axi_araddr <= 'd0; end else if((M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1)&&(rd_hcnt == C_M_AXI_BURST_LEN - 1)&&(rd_vcnt == rd_burst_times - 1'b1)) begin axi_araddr <= rd_base_addr; // end else if((M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1)&&(rd_hcnt == C_M_AXI_BURST_LEN - 1)&&(rd_vcnt == rd_burst_times - 1'b1)) begin // axi_araddr <= 0; end else if(axi_arvalid==1'b1&&M_AXI_ARREADY==1'b1) begin axi_araddr <= axi_araddr + Araddr_Brust_Offset; end else begin axi_araddr <= axi_araddr; end end // ar---------------------------------------------------------------------------------------------// // r----------------------------------------------------------------------------------------------// always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 1'b0) begin axi_rready <= 1'b0; end else if((M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1)&&(M_AXI_RLAST == 1'b1)) begin axi_rready <= 1'b0; end else if(axi_arvalid==1'b1&&M_AXI_ARREADY==1'b1) begin axi_rready <= 1'b1; end else begin axi_rready <= axi_rready; end end // r----------------------------------------------------------------------------------------------// // r_Sync-----------------------------------------------------------------------------------------// assign rd_fifo_wr_en = (M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1); assign rd_fifo_wr_data = M_AXI_RDATA; assign rd_fifo_rd_en = I_Post_de && Post_Start; assign O_Post_data = rd_fifo_rd_data[23:0]; rdata_w64x2048_r32x4096 rdata_w64x2048_r32x4096 ( .rst ( (!M_AXI_ARESETN)&&(!rd_start_cnt[2])), // input wire rst .wr_clk ( M_AXI_ACLK ), // input wire wr_clk .rd_clk ( I_Post_clk ), // input wire rd_clk .din ( rd_fifo_wr_data ), // input wire [63 : 0] din .wr_en ( rd_fifo_wr_en ), // input wire wr_en .rd_en ( rd_fifo_rd_en ), // input wire rd_en .dout ( rd_fifo_rd_data ), // output wire [31 : 0] dout .full ( full_r ), // output wire full .empty ( empty_r ), // output wire empty .rd_data_count( r_rd_data_count ), // output wire [12 : 0] rd_data_count .wr_data_count( r_wr_data_count ), // output wire [11 : 0] wr_data_count .wr_rst_busy(), // output wire wr_rst_busy .rd_rst_busy() // output wire rd_rst_busy ); //hcnt always@(posedge M_AXI_ACLK)begin if(M_AXI_ARESETN == 1'b0) begin rd_hcnt <= 'd0; end else if((M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1)&&(rd_hcnt == C_M_AXI_BURST_LEN - 1)) begin rd_hcnt <= 'd0; end else if((M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1)) begin rd_hcnt <= rd_hcnt + 1'b1; end else begin rd_hcnt <= rd_hcnt; end end //vcnt always@(posedge M_AXI_ACLK)begin if(M_AXI_ARESETN == 1'b0) begin rd_vcnt <= 'd0; end else if((M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1)&&(rd_hcnt == C_M_AXI_BURST_LEN - 1)&&(rd_vcnt == rd_burst_times - 1'b1)) begin rd_vcnt <= 'd0; end else if((M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1)&&(rd_hcnt == C_M_AXI_BURST_LEN - 1)) begin rd_vcnt <= rd_vcnt + 1'b1; end else begin rd_vcnt <= rd_vcnt; end end // r_Sync-----------------------------------------------------------------------------------------// endmodule
第四个版本:
在第三个版本的基础上,把接口全部统一的版本,所有的位宽操作都在外部做:
`timescale 1 ns / 1 ps module dma_complex # ( parameter WR_Base_addr = 32'h2000000, parameter RD_Base_addr = 32'h2000000, parameter integer C_M_AXI_BURST_LEN = 256 , parameter integer C_M_AXI_ID_WIDTH = 1 , parameter integer C_M_AXI_ADDR_WIDTH = 32 , parameter integer C_M_AXI_DATA_WIDTH = 64 , parameter integer C_M_AXI_AWUSER_WIDTH = 0 , parameter integer C_M_AXI_ARUSER_WIDTH = 0 , parameter integer C_M_AXI_WUSER_WIDTH = 0 , parameter integer C_M_AXI_RUSER_WIDTH = 0 , parameter integer C_M_AXI_BUSER_WIDTH = 0 , parameter I_image_w = 1920 , parameter I_image_h = 1080 , parameter Pixel_byte_num = 4 , parameter AXI_Buff_NUM = 3 , parameter WR_CH_EN = 1 , parameter RD_CH_EN = 1 ) ( input wire M_AXI_ACLK , input wire M_AXI_ARESETN , output wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_AWID , output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_AWADDR , output wire [7 : 0] M_AXI_AWLEN , output wire [2 : 0] M_AXI_AWSIZE , output wire [1 : 0] M_AXI_AWBURST , output wire M_AXI_AWLOCK , output wire [3 : 0] M_AXI_AWCACHE , output wire [2 : 0] M_AXI_AWPROT , output wire [3 : 0] M_AXI_AWQOS , output wire [C_M_AXI_AWUSER_WIDTH-1 : 0] M_AXI_AWUSER , output wire M_AXI_AWVALID , input wire M_AXI_AWREADY , output wire [C_M_AXI_DATA_WIDTH-1 : 0] M_AXI_WDATA , output wire [C_M_AXI_DATA_WIDTH/8-1 : 0] M_AXI_WSTRB , output wire M_AXI_WLAST , output wire [C_M_AXI_WUSER_WIDTH-1 : 0] M_AXI_WUSER , output wire M_AXI_WVALID , input wire M_AXI_WREADY , input wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_BID , input wire [1 : 0] M_AXI_BRESP , input wire [C_M_AXI_BUSER_WIDTH-1 : 0] M_AXI_BUSER , input wire M_AXI_BVALID , output wire M_AXI_BREADY , output wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_ARID , output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_ARADDR , output wire [7 : 0] M_AXI_ARLEN , output wire [2 : 0] M_AXI_ARSIZE , output wire [1 : 0] M_AXI_ARBURST , output wire M_AXI_ARLOCK , output wire [3 : 0] M_AXI_ARCACHE , output wire [2 : 0] M_AXI_ARPROT , output wire [3 : 0] M_AXI_ARQOS , output wire [C_M_AXI_ARUSER_WIDTH-1 : 0] M_AXI_ARUSER , output wire M_AXI_ARVALID , input wire M_AXI_ARREADY , input wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_RID , input wire [C_M_AXI_DATA_WIDTH-1 : 0] M_AXI_RDATA , input wire [1 : 0] M_AXI_RRESP , input wire M_AXI_RLAST , input wire [C_M_AXI_RUSER_WIDTH-1 : 0] M_AXI_RUSER , input wire M_AXI_RVALID , output wire M_AXI_RREADY , //Custom input wire [7:0] I_wr_index ,// 仅读通道下接受所读取帧的位置; input wire I_rd_start , //Aribe-----------------------------------------------------// output wire O_wr_req , input wire I_Aribe_wr_enable , output wire O_wr_brust_start , output wire O_wr_brust_end , output wire O_rd_req , input wire I_Aribe_rd_enable , output wire O_rd_brust_start , output wire O_rd_brust_end , //Aribe-----------------------------------------------------// input wire I_Pre_clk , input wire I_Pre_vs , input wire [C_M_AXI_DATA_WIDTH -1:0] I_Pre_data , input wire I_Pre_de , output wire [7:0] O_wr_index , input wire I_Post_clk , output wire O_Post_Start ,//Reset Post Module output wire [C_M_AXI_DATA_WIDTH -1:0] O_Post_data , input wire I_Post_de ); function integer clogb2 (input integer bit_depth); begin for(clogb2=0; bit_depth>0; clogb2=clogb2+1) bit_depth = bit_depth >> 1; end endfunction //========================================= Define Ports =========================================// localparam integer C_TRANSACTIONS_NUM = clogb2(C_M_AXI_BURST_LEN-1) ; localparam Awaddr_Brust_Offset = (C_M_AXI_DATA_WIDTH)*(C_M_AXI_BURST_LEN)/8 ; localparam Araddr_Brust_Offset = (C_M_AXI_DATA_WIDTH)*(C_M_AXI_BURST_LEN)/8 ; localparam Total_Frame_Offset = I_image_w*I_image_h*Pixel_byte_num ; localparam RAM_1_start_addr = 0 ; localparam RAM_2_start_addr = Total_Frame_Offset ; localparam RAM_3_start_addr = Total_Frame_Offset*2 ; localparam wr_burst_times = I_image_w*I_image_h*Pixel_byte_num /Awaddr_Brust_Offset ; localparam rd_burst_times = I_image_w*I_image_h*Pixel_byte_num /Araddr_Brust_Offset ; //========================================= Define Ports =========================================// // AXI4LITE signals //AXI4 internal temp signals reg [C_M_AXI_ADDR_WIDTH-1 : 0] axi_awaddr ; reg axi_awvalid ; reg axi_wlast ; reg axi_wvalid ; reg [C_TRANSACTIONS_NUM-1:0] wr_burst_cnt ; reg axi_bready ; reg [C_M_AXI_ADDR_WIDTH-1 : 0] axi_araddr ; reg axi_arvalid ; reg axi_rready ; //W_FIFO wire wr_fifo_wr_en ; wire [C_M_AXI_DATA_WIDTH-1 : 0] wr_fifo_wr_data ; wire wr_fifo_rd_en ; wire [C_M_AXI_DATA_WIDTH-1 : 0] wr_fifo_rd_data ; wire full_w ; wire empty_w ; wire [15 : 0] w_rd_data_count ; wire [15 : 0] w_wr_data_count ; //r_FIFO wire rd_fifo_wr_en ; wire [C_M_AXI_DATA_WIDTH-1 : 0] rd_fifo_wr_data ; wire rd_fifo_rd_en ; wire [C_M_AXI_DATA_WIDTH-1 : 0] rd_fifo_rd_data ; wire [15 : 0] r_rd_data_count ; wire [15 : 0] r_wr_data_count ; wire full_r ; wire empty_r ; reg [15:0] rd_hcnt ; reg [15:0] rd_vcnt ; //I/O Connections. Write Address (AW) assign M_AXI_AWID = 'b0; assign M_AXI_AWADDR = WR_Base_addr + axi_awaddr; assign M_AXI_AWLEN = C_M_AXI_BURST_LEN - 1; assign M_AXI_AWSIZE = clogb2((C_M_AXI_DATA_WIDTH/8)-1); assign M_AXI_AWBURST = 2'b01; assign M_AXI_AWLOCK = 1'b0; assign M_AXI_AWCACHE = 4'b0010; assign M_AXI_AWPROT = 3'h0; assign M_AXI_AWQOS = 4'h0; assign M_AXI_AWUSER = 'b1; assign M_AXI_AWVALID = axi_awvalid; //Write Data(W) assign wr_fifo_rd_en = (axi_wvalid == 1'b1)&&(M_AXI_WREADY == 1'b1); assign M_AXI_WDATA = wr_fifo_rd_data; //All bursts are complete and aligned in this example assign M_AXI_WSTRB = {(C_M_AXI_DATA_WIDTH/8){1'b1}}; assign M_AXI_WLAST = axi_wlast; assign M_AXI_WUSER = 'b0; assign M_AXI_WVALID = axi_wvalid; //Write Response (B) assign M_AXI_BREADY = axi_bready; //Read Address (AR) assign M_AXI_ARID = 'b0; assign M_AXI_ARADDR = RD_Base_addr + axi_araddr; assign M_AXI_ARLEN = C_M_AXI_BURST_LEN - 1; assign M_AXI_ARSIZE = clogb2((C_M_AXI_DATA_WIDTH/8)-1); assign M_AXI_ARBURST = 2'b01; assign M_AXI_ARLOCK = 1'b0; assign M_AXI_ARCACHE = 4'b0010; assign M_AXI_ARPROT = 3'h0; assign M_AXI_ARQOS = 4'h0; assign M_AXI_ARUSER = 'b1; assign M_AXI_ARVALID = axi_arvalid; //Read and Read Response (R) assign M_AXI_RREADY = axi_rready; // Wr_Sync------------------------------------------------------------------------------------------// //W Sync Port //wrclk reg r1_pre_vs ; wire Pose_pre_vs ; wire Nege_pre_vs ; wire Ext_Pose_pre_vs ; //sysclk reg sys_pre_vs ; reg r1_sys_pre_vs ; reg sys_Pose_pre_vs ; reg sys_Nege_pre_vs ; reg r_sys_Nege_pre_vs; reg [1:0] wr_index ; reg [C_M_AXI_ADDR_WIDTH-1 : 0] wr_base_addr ; always @(posedge I_Pre_clk) begin r1_pre_vs <= I_Pre_vs; end assign Pose_pre_vs = (I_Pre_vs == 1'b1)&&(r1_pre_vs == 1'b0); assign Nege_pre_vs = (I_Pre_vs == 1'b0)&&(r1_pre_vs == 1'b1); always@(posedge M_AXI_ACLK) begin sys_pre_vs <= I_Pre_vs ; r1_sys_pre_vs <= sys_pre_vs; r_sys_Nege_pre_vs <= sys_Nege_pre_vs; end always @(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 1'b0) begin sys_Pose_pre_vs <= 1'b0; sys_Nege_pre_vs <= 1'b0; end else if(sys_pre_vs==1'b1&&r1_sys_pre_vs==1'b0) begin sys_Pose_pre_vs <= 1'b1; sys_Nege_pre_vs <= 1'b0; end else if(sys_pre_vs==1'b0&&r1_sys_pre_vs==1'b1) begin sys_Pose_pre_vs <= 1'b0; sys_Nege_pre_vs <= 1'b1; end else begin sys_Pose_pre_vs <= 1'b0; sys_Nege_pre_vs <= 1'b0; end end Data_sync_ext Data_sync_ext_Inst0( .clka ( I_Pre_clk ), .rst_n ( M_AXI_ARESETN ), .pulse_a ( Pose_pre_vs ), .ext_pulse_a ( Ext_Pose_pre_vs ) ); always@(posedge M_AXI_ACLK) if(M_AXI_ARESETN == 1'b0) begin wr_index <= 'd1; end else if(sys_Nege_pre_vs == 1'b1&&wr_index == AXI_Buff_NUM) begin wr_index <= 'd1; end else if(sys_Nege_pre_vs==1'b1) begin wr_index <= wr_index + 1'b1; end else begin wr_index <= wr_index; end assign O_wr_index = wr_index; always@(posedge M_AXI_ACLK) if(M_AXI_ARESETN == 1'b0) begin wr_base_addr <= 0; end else if(sys_Nege_pre_vs == 1'b1&&wr_index == AXI_Buff_NUM) begin wr_base_addr <= 0; end else if(sys_Nege_pre_vs == 1'b1) begin wr_base_addr <= wr_base_addr + Total_Frame_Offset; end else begin wr_base_addr <= wr_base_addr; end // Wr_Sync------------------------------------------------------------------------------------------// assign wr_fifo_wr_en = I_Pre_de; assign wr_fifo_wr_data = I_Pre_data; generate if (WR_CH_EN[0]==1) begin: WR_EN wdata_w256x256_r256x256 wdata_w256x256_r256x256 ( .rst ( (!M_AXI_ARESETN)|(Ext_Pose_pre_vs)), // input wire rst .wr_clk ( I_Pre_clk ), // input wire wr_clk .rd_clk ( M_AXI_ACLK ), // input wire rd_clk .din ( wr_fifo_wr_data ), // input wire [255 : 0] din .wr_en ( wr_fifo_wr_en ), // input wire wr_en .rd_en ( wr_fifo_rd_en ), // input wire rd_en .dout ( wr_fifo_rd_data ), // output wire [255 : 0] dout .full ( full_w ), // output wire full .empty ( empty_w ), // output wire empty .rd_data_count(w_rd_data_count ), // output wire [10 : 0] rd_data_count .wr_data_count(w_wr_data_count ), // output wire [10 : 0] wr_data_count .wr_rst_busy(), // output wire wr_rst_busy .rd_rst_busy() // output wire rd_rst_busy ); end endgenerate // w_start_control----------------------------------------------------------------------------------// //Control reg wr_brust_start ; wire wr_brust_Req ; reg wr_brust_end ; reg wr_brust_now ; assign wr_brust_Req = (w_rd_data_count>=C_M_AXI_BURST_LEN); assign O_wr_req = wr_brust_Req; assign O_wr_brust_start = (wr_brust_start == 1'b1 && wr_brust_now == 1'b0); assign O_wr_brust_end = wr_brust_end; // 多路输入的时候,wr_burst_Req输出到仲裁器中,使用仲裁器输出的aribe_req请求完成此处wr_burst_Req的工作 // 如果FIFO内数据满足写入需求:拉高请求 // 如果请求得到仲裁通过,启动burst always@(*) if(WR_CH_EN[0] == 1'b1 && wr_brust_Req == 1'b1 && I_Aribe_wr_enable == 1'b1) begin wr_brust_start <= 1'b1; end else begin wr_brust_start <= 1'b0; end always@(posedge M_AXI_ACLK) if(M_AXI_ARESETN == 1'b0) begin wr_brust_now <= 1'b0; end else if(wr_brust_end == 1'b1 && wr_brust_now == 1'b1) begin wr_brust_now <= 1'b0; end else if(wr_brust_start == 1'b1 && wr_brust_now == 1'b0) begin wr_brust_now <= 1'b1; end else begin wr_brust_now <= wr_brust_now; end always@(posedge M_AXI_ACLK) if(M_AXI_ARESETN == 1'b0) begin wr_brust_end <= 1'b0; end else if(axi_wvalid==1'b1&&M_AXI_WREADY==1'b1&&wr_burst_cnt==C_M_AXI_BURST_LEN-1) begin wr_brust_end <= 1'b1; end else begin wr_brust_end <= 1'b0; end // w_start_control----------------------------------------------------------------------------------// // Aw------ --------------------------------------------------------------------------------------// //axi_awvalid always@(posedge M_AXI_ACLK) if(M_AXI_ARESETN == 1'b0) begin axi_awvalid <= 1'b0; end else if(axi_awvalid == 1'b1 && M_AXI_AWREADY == 1'b1) begin axi_awvalid <= 1'b0; end else if(wr_brust_start == 1'b1 && wr_brust_now == 1'b0) begin axi_awvalid <= 1'b1; end else begin axi_awvalid <= axi_awvalid; end //axi_awaddr always@(posedge M_AXI_ACLK) if(M_AXI_ARESETN == 1'b0) begin axi_awaddr <= 'd0; end else if(r_sys_Nege_pre_vs == 1'b1) begin axi_awaddr <= wr_base_addr; // end else if(r_sys_Nege_pre_vs == 1'b1) begin // axi_awaddr <= 0; end else if(axi_awvalid==1'b1 && M_AXI_AWREADY==1'b1) begin axi_awaddr <= axi_awaddr + Awaddr_Brust_Offset ; end else begin axi_awaddr <= axi_awaddr; end // Aw---------------------------------------------------------------------------------------------// // W----------------------------------------------------------------------------------------------// //axi_wvalid always@(posedge M_AXI_ACLK) if(M_AXI_ARESETN == 1'b0) begin axi_wvalid <= 1'b0; end else if(axi_wvalid==1'b1&&M_AXI_WREADY==1'b1&&wr_burst_cnt==C_M_AXI_BURST_LEN-1) begin axi_wvalid <= 1'b0; end else if(axi_awvalid==1'b1&&M_AXI_AWREADY==1'b1) begin axi_wvalid <= 1'b1; end else begin axi_wvalid <= axi_wvalid; end //wr_burst_cnt always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 1'b0) begin wr_burst_cnt <= 'd0; end else if(axi_wvalid==1'b1&&M_AXI_WREADY==1'b1&&wr_burst_cnt==C_M_AXI_BURST_LEN-1) begin wr_burst_cnt <= 'd0; end else if(axi_wvalid==1'b1&&M_AXI_WREADY==1'b1) begin wr_burst_cnt <= wr_burst_cnt + 1'b1; end else begin wr_burst_cnt <= wr_burst_cnt; end end //axi_wlast always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 1'b0) begin axi_wlast <= 1'b0; end else if(axi_wvalid==1'b1&&M_AXI_WREADY==1'b1&&wr_burst_cnt==C_M_AXI_BURST_LEN-1'b1) begin axi_wlast <= 1'b0; end else if(axi_wvalid==1'b1&&M_AXI_WREADY==1'b1&&wr_burst_cnt==C_M_AXI_BURST_LEN-2'd2) begin axi_wlast <= 1'b1; end else begin axi_wlast <= axi_wlast; end end // W----------------------------------------------------------------------------------------------// // b----------------------------------------------------------------------------------------------// always @(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 0) begin axi_bready <= 'd0; end else begin axi_bready <= 1'b1; end end // b----------------------------------------------------------------------------------------------// // r_start_control----------------------------------------------------------------------------------// //Control reg [7:0] rd_index ; reg [7:0] rd_index_ptr ; reg [C_M_AXI_ADDR_WIDTH-1 : 0] rd_base_addr ; reg rd_start_cycle ; reg [2:0] rd_start_cnt ; reg rd_brust_start ; reg rd_brust_Req ; reg rd_brust_end ; reg rd_brust_now ; reg Post_Start ; always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 0) begin rd_index <= 0; end else case (WR_CH_EN[0] == 1'b1) 1'b0:begin if(I_wr_index > 1) begin rd_index <= I_wr_index - 1'b1; end else begin rd_index <= AXI_Buff_NUM; end end 1'b1:begin if(wr_index > 1) begin rd_index <= wr_index - 1'b1; end else begin rd_index <= AXI_Buff_NUM; end end default: begin rd_index <= rd_index; end endcase end always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 0) begin rd_index_ptr <= 'd0; end else begin rd_index_ptr <= rd_index - 1'b1; end end always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 0) begin rd_base_addr <= 'd0; end else begin rd_base_addr <= rd_index_ptr*Total_Frame_Offset; end end always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 0) begin rd_start_cnt <= 'd0; end else if(sys_Nege_pre_vs == 1'b1 && rd_start_cnt[2] != 1'b1 && WR_CH_EN[0] == 1'b1) begin rd_start_cnt <= rd_start_cnt + 1'b1; end else if(I_rd_start == 1'b1 && WR_CH_EN[0] == 1'b0) begin rd_start_cnt <= rd_start_cnt + 1'b1; end else begin rd_start_cnt <= rd_start_cnt; end end always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 0) begin rd_start_cycle <= 1'b0; end else if(rd_start_cnt[2] == 1'b1 && full_r == 1'b0) begin rd_start_cycle <= 1'b1; end else begin rd_start_cycle <= rd_start_cycle; end end always@(posedge I_Post_clk) if(M_AXI_ARESETN == 0) begin Post_Start <= 1'b0; end else if(rd_start_cycle == 1'b1 && r_rd_data_count >= C_M_AXI_BURST_LEN) begin Post_Start <= 1'b1; end else begin Post_Start <= Post_Start; end assign O_Post_Start = Post_Start ; assign O_rd_req = rd_brust_Req; assign O_rd_brust_start = (rd_brust_start == 1'b1 && rd_brust_now == 1'b0); assign O_rd_brust_end = rd_brust_end; always @(*) begin if((RD_CH_EN[0] == 1'b1) && (rd_start_cycle == 1'b1) && (r_wr_data_count < C_M_AXI_BURST_LEN*4)) begin rd_brust_Req <= 1'b1; end else begin rd_brust_Req <= 1'b0; end end always@(posedge M_AXI_ACLK) if(M_AXI_ARESETN == 1'b0) begin rd_brust_end <= 1'b0; end else if((M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1)&&(M_AXI_RLAST == 1'b1)) begin rd_brust_end <= 1'b1; end else begin rd_brust_end <= 1'b0; end //No aribe always@(*) begin if(rd_brust_Req == 1'b1 && I_Aribe_rd_enable == 1'b1) begin rd_brust_start <= 1'b1; end else begin rd_brust_start <= 1'b0; end end always@(posedge M_AXI_ACLK) if(M_AXI_ARESETN == 1'b0) begin rd_brust_now <= 1'b0; end else if(rd_brust_end == 1'b1 && rd_brust_now == 1'b1) begin rd_brust_now <= 1'b0; end else if(rd_brust_start == 1'b1 && rd_brust_now == 1'b0) begin rd_brust_now <= 1'b1; end else begin rd_brust_now <= rd_brust_now; end // r_start_control----------------------------------------------------------------------------------// // ar---------------------------------------------------------------------------------------------// always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 1'b0) begin axi_arvalid <= 1'b0; end else if(axi_arvalid==1'b1&&M_AXI_ARREADY==1'b1) begin axi_arvalid <= 1'b0; end else if(rd_brust_start == 1'b1 && rd_brust_now == 1'b0) begin axi_arvalid <= 1'b1; end else begin axi_arvalid <= axi_arvalid; end end always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 1'b0) begin axi_araddr <= 'd0; end else if((M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1)&&(rd_hcnt == C_M_AXI_BURST_LEN - 1)&&(rd_vcnt == rd_burst_times - 1'b1)) begin axi_araddr <= rd_base_addr; end else if(axi_arvalid==1'b1&&M_AXI_ARREADY==1'b1) begin axi_araddr <= axi_araddr + Araddr_Brust_Offset; end else begin axi_araddr <= axi_araddr; end end // ar---------------------------------------------------------------------------------------------// // r----------------------------------------------------------------------------------------------// always@(posedge M_AXI_ACLK) begin if(M_AXI_ARESETN == 1'b0) begin axi_rready <= 1'b0; end else if((M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1)&&(M_AXI_RLAST == 1'b1)) begin axi_rready <= 1'b0; end else if(axi_arvalid==1'b1&&M_AXI_ARREADY==1'b1) begin axi_rready <= 1'b1; end else begin axi_rready <= axi_rready; end end // r----------------------------------------------------------------------------------------------// // r_Sync-----------------------------------------------------------------------------------------// assign rd_fifo_wr_en = (M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1); assign rd_fifo_wr_data = M_AXI_RDATA; assign rd_fifo_rd_en = I_Post_de && Post_Start; assign O_Post_data = rd_fifo_rd_data; generate if (RD_CH_EN[0]==1) begin: RD_EN rdata_w256x512_r256x512 rdata_w256x512_r256x512 ( .rst ( (!M_AXI_ARESETN)&&(!rd_start_cnt[2])), // input wire rst .wr_clk ( M_AXI_ACLK ), // input wire wr_clk .rd_clk ( I_Post_clk ), // input wire rd_clk .din ( rd_fifo_wr_data ), // input wire [255 : 0] din .wr_en ( rd_fifo_wr_en ), // input wire wr_en .rd_en ( rd_fifo_rd_en ), // input wire rd_en .dout ( rd_fifo_rd_data ), // output wire [255 : 0] dout .full ( full_r ), // output wire full .empty ( empty_r ), // output wire empty .rd_data_count( r_rd_data_count ), // output wire [8 : 0] rd_data_count .wr_data_count( r_wr_data_count ), // output wire [8 : 0] wr_data_count .wr_rst_busy(), // output wire wr_rst_busy .rd_rst_busy() // output wire rd_rst_busy ); end endgenerate //hcnt always@(posedge M_AXI_ACLK)begin if(M_AXI_ARESETN == 1'b0) begin rd_hcnt <= 'd0; end else if((M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1)&&(rd_hcnt == C_M_AXI_BURST_LEN - 1)) begin rd_hcnt <= 'd0; end else if((M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1)) begin rd_hcnt <= rd_hcnt + 1'b1; end else begin rd_hcnt <= rd_hcnt; end end //vcnt always@(posedge M_AXI_ACLK)begin if(M_AXI_ARESETN == 1'b0) begin rd_vcnt <= 'd0; end else if((M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1)&&(rd_hcnt == C_M_AXI_BURST_LEN - 1)&&(rd_vcnt == rd_burst_times - 1'b1)) begin rd_vcnt <= 'd0; end else if((M_AXI_RVALID == 1'b1)&&(axi_rready == 1'b1)&&(rd_hcnt == C_M_AXI_BURST_LEN - 1)) begin rd_vcnt <= rd_vcnt + 1'b1; end else begin rd_vcnt <= rd_vcnt; end end endmodule
位宽管理:
输入:(写着uart但其他的也都可以用,改参数即可)
module uart_buff #( parameter IW = 8, parameter OW = 256 )( input wire sys_clk , input wire rst_n , input wire uart_rx_vaild , input wire [7:0] uart_rx_data , output wire [255:0] uart_8to256_data , output wire uart_8to256_vaild ); localparam DATA_MAX = OW/IW; reg [7:0] data_cnt ; reg [255:0] shift_data ; reg r1_uart_8to256_vaild; assign uart_8to256_vaild = r1_uart_8to256_vaild; assign uart_8to256_data = shift_data; always @(posedge sys_clk) begin if(rst_n == 1'b0) begin data_cnt <= 'd0; end else if(uart_rx_vaild == 1'b1 && data_cnt == DATA_MAX - 1'b1) begin data_cnt <= 'd0; end else if(uart_rx_vaild == 1'b1) begin data_cnt <= data_cnt + 1'b1; end else begin data_cnt <= data_cnt; end end // shift_data always @(posedge sys_clk) begin if(rst_n == 1'b0) begin shift_data <= 'd0; end else if(uart_rx_vaild == 1'b1) begin shift_data <= {shift_data[247:0],uart_rx_data}; end else begin shift_data <= shift_data; end end always @(posedge sys_clk) begin if(rst_n == 1'b0) begin r1_uart_8to256_vaild <= 1'b0; end else if(uart_rx_vaild == 1'b1 && data_cnt == DATA_MAX - 1'b1) begin r1_uart_8to256_vaild <= 1'b1; end else begin r1_uart_8to256_vaild <= 1'b0; end end endmodule
输出:
module hdmi_buff #( parameter Iw = 256, parameter Ow = 16 )( input wire rst_n , input wire hdmi_clk , input wire hdmi_Pre_de , input wire hdmi_Pre_hsync , input wire hdmi_Pre_vsync , output wire hdmi_Post_en , output wire hdmi_Post_hsync , output wire hdmi_Post_vsync , output wire [15:0] hdmi_rd_data , //fifo output wire fifo_rd_en , input wire [255:0] fifo_rd_data ); localparam Div_Num = (Iw/Ow); reg [7:0] byte_cnt ; reg r_fifo_rd_en ; reg [255:0] shift_rd_data ; //hdmi reg r1_hdmi_Pre_de ; reg r1_hdmi_Pre_hsync ; reg r1_hdmi_Pre_vsync ; assign hdmi_Post_en = r1_hdmi_Pre_de ; assign hdmi_Post_hsync = r1_hdmi_Pre_hsync ; assign hdmi_Post_vsync = r1_hdmi_Pre_vsync ; assign hdmi_rd_data = (hdmi_Post_en == 1'b1)?(shift_rd_data[255:240]):('d0); // fifo_rd_en assign fifo_rd_en = r_fifo_rd_en; always @(posedge hdmi_clk) begin r1_hdmi_Pre_de <= hdmi_Pre_de ; r1_hdmi_Pre_hsync <= hdmi_Pre_hsync ; r1_hdmi_Pre_vsync <= hdmi_Pre_vsync ; end //byte_cnt always @(posedge hdmi_clk) begin if(rst_n == 1'b0) begin byte_cnt <= 'd0; end else if(hdmi_Pre_de == 1'b1 && byte_cnt == Div_Num - 1'b1) begin byte_cnt <= 'd0; end else if(hdmi_Pre_de == 1'b1) begin byte_cnt <= byte_cnt + 1'b1; end else begin byte_cnt <= byte_cnt; end end always @(*) begin if(hdmi_Pre_de == 1'b1 && byte_cnt == 'd0) begin r_fifo_rd_en <= 1'b1; end else begin r_fifo_rd_en <= 1'b0; end end always @(posedge hdmi_clk) begin if(rst_n == 1'b0) begin shift_rd_data <= 'd0; end else if(hdmi_Pre_de == 1'b1 && byte_cnt == 'd0) begin shift_rd_data <= fifo_rd_data; end else if(hdmi_Post_en == 1'b1) begin shift_rd_data <= {shift_rd_data[239:0],16'b0}; end else begin shift_rd_data <= shift_rd_data; end end endmodule
参考:
[1] 开源骚客;
[2] 黑金教程;
[3] V3学院;
[4] 无双软件学院;
[5] 正点原子教程;
[6] 其他渠道的视频和代码;