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
View Code

第二个版本:

多帧缓存,但是地址管理得不好,存在很多问题;

`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
View Code

第三个版本:

多帧缓存,写复位,个人认为是较好的版本。

`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
View Code

 第四个版本:

在第三个版本的基础上,把接口全部统一的版本,所有的位宽操作都在外部做:

`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
View Code

位宽管理:

输入:(写着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
View Code

输出:

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
View Code

参考:

[1] 开源骚客;

[2] 黑金教程;

[3] V3学院;

[4] 无双软件学院;

[5] 正点原子教程;

[6] 其他渠道的视频和代码;

 

posted @ 2024-01-18 12:22  NoNounknow  阅读(70)  评论(0编辑  收藏  举报