linux怎么读zynq的ddr数据,Zedboard & Zynq 图像采集 视频开发 (三) AXI4总线读写DDR

/*-----------------------------------------------------------------------

CONFIDENTIAL IN CONFIDENCE

This confidential and proprietary software may be only used as authorized

by a licensing agreement from EEPROM .

In the event of publication, the following notice is applicable:

Copyright (C) 2013-20xx EEPROM Corporation

The entire notice above must be reproduced on all authorized copies.

Author              :       EEPROM

Technology blogs    :       http://blog.csdn.net/zhangyu_eeprom

Email Address       :       [email protected]

Filename            :       axi4_s2mm_video_dma.v

Data                :       2014-05-20

Description         :       axi4_s2mm_video_dma.

Modification History    :

Data            By          Version         Change Description

=========================================================================

-------------------------------------------------------------------------

------     ------    ------|   ------|      /-------\

|          |          |     |   |     |     /         \      /-\     /-\

|------    |------    |-----|   |-----|    /           \    /   \   /   \

|          |          |         | \        \           /   /     \_/     \

|------    |------    |         |  \        \         /   /               \

|         |   \        \-------/

-----------------------------------------------------------------------*/

module axi4_s2mm_video_dma #(

parameter [31:0]  APB_BASE_ADDR  = 32'h70000000,

parameter [31:0]  DMA_DEST_ADDR0 = 32'h1c000000,

parameter [31:0]  DMA_DEST_ADDR1 = 32'h1c200000,

parameter [31:0]  DMA_DEST_ADDR2 = 32'h1c400000,

parameter [8:0]   C_DATA_WIDTH = 9'd32,

parameter [12:0]  STRIDE       = 13'd1920,

parameter [12:0]  WIDTH        = 13'd1920,

parameter [12:0]  HEIGHT       = 13'd1080

)

(

input             axi_clk,

input             axi_rstn,

output            IRQ_F2P_pin,

input             M_APB_PCLK_pin,

input             M_APB_PRESETN_pin,

input   [31:0]    M_APB_PADDR_pin,

input             M_APB_PSEL_pin,

input             M_APB_PENABLE_pin,

input             M_APB_PWRITE_pin,

input   [31:0]    M_APB_PWDATA_pin,

output            M_APB_PREADY_pin,

output [31:0]     M_APB_PRDATA_pin,

output            M_APB_PSLVERR_pin,

input            v_video_clk,

input            v_timing_hsync_i,

input            v_timing_vsync_i,

input            v_timing_hblank_i,

input            v_timing_vblank_i,

input            v_timing_active_video_i,

input   [23:0]   v_video_data_i,

input             S_AXI_AWREADY_pin,

input             S_AXI_BVALID_pin,

input             S_AXI_WREADY_pin,

input   [1:0]     S_AXI_BRESP_pin,

input   [5:0]     S_AXI_BID_pin,

output reg        S_AXI_AWVALID_pin,

output            S_AXI_BREADY_pin,

output            S_AXI_WLAST_pin,

output reg        S_AXI_WVALID_pin,

output [1:0]      S_AXI_AWBURST_pin,

output [1:0]      S_AXI_AWLOCK_pin,

output [2:0]      S_AXI_AWSIZE_pin,

output [2:0]      S_AXI_AWPROT_pin,

output reg [31:0] S_AXI_AWADDR_pin,

output reg [C_DATA_WIDTH-1:0]     S_AXI_WDATA_pin,

output [3:0]      S_AXI_AWCACHE_pin,

output [3:0]      S_AXI_AWLEN_pin,

output [3:0]      S_AXI_AWQOS_pin,

output [7:0]      S_AXI_WSTRB_pin,

output [5:0]      S_AXI_AWID_pin,

output [5:0]      S_AXI_WID_pin

);

/******************************************/

reg [23:0]   v_video_data_r;

reg          v_timing_vsync_r;

reg          v_timing_active_video_r;

reg          process_start; // first vsync rising

reg          [1:0]frame_num;

wire         line_last;

wire         frame_last;

reg          frame_last_r;

reg          [12:0]hcount;

reg          [12:0]vcount;

reg          [4:0]axi_write_num;

reg          axi_write_ok;

reg          axi_addr_ok;

reg          [31:0]prev_line_start;

wire         stall;

reg          [4:0]read_fifo_num;

reg          fifo_rd_ok;

wire         dma_frame_write_end;

wire         dma_line_write_end;

reg          v_timing_hsync_r;

reg          [12:0]write_fifo_num;

/************fifo**************/

reg   fifo_wr_en;

wire  fifo_rd_en;

wire  fifo_full;

wire  fifo_empty;

wire  fifo_valid;

wire  [9:0] fifo_rd_data_count;

wire  [9:0] fifo_wr_data_count;

wire  [31:0] fifo_dout;

/******************************/

/******************************/

/*

* APB bus

*/

reg [1:0] DMA_WRITE_STATUS;

assign IRQ_F2P_pin = DMA_WRITE_STATUS[1];

// write dma busy status configuration

always @(posedge M_APB_PCLK_pin)

begin

if (!M_APB_PRESETN_pin) begin

DMA_WRITE_STATUS[0] <= 1'b0;

end

else if(dma_frame_write_end) begin

DMA_WRITE_STATUS[0] <= 1'b0;

end

else if(M_APB_PSEL_pin && M_APB_PWRITE_pin && M_APB_PENABLE_pin) begin

if (M_APB_PADDR_pin==APB_BASE_ADDR && M_APB_PWDATA_pin[0] && !DMA_WRITE_STATUS[0]) begin

DMA_WRITE_STATUS[0] <= 1'b1;

end

end

end

// write dma interrupt configuration, write '1' to clear interrupt

always @(posedge M_APB_PCLK_pin)

begin

if (!M_APB_PRESETN_pin) begin

DMA_WRITE_STATUS[1] <= 1'b0;

end

else if(dma_frame_write_end) begin

DMA_WRITE_STATUS[1] <= 1'b1;

end

else if(M_APB_PSEL_pin && M_APB_PWRITE_pin && M_APB_PENABLE_pin) begin

if (M_APB_PADDR_pin==APB_BASE_ADDR && M_APB_PWDATA_pin[1] && DMA_WRITE_STATUS[1]) begin

DMA_WRITE_STATUS[1] <= 1'b0;

end

end

end

//------------------------------------------------------

// APB output

//------------------------------------------------------

assign M_APB_PRDATA_pin = {28'h0000,frame_num,DMA_WRITE_STATUS};

assign M_APB_PREADY_pin = 1'b1;

assign M_APB_PSLVERR_pin = 1'b0;

/*******************************************/

wire dma_write_start;

reg process_start_pre;

always @(posedge v_video_clk)

begin

if(!axi_rstn)

begin

v_video_data_r <= 24'd0;

v_timing_vsync_r <= 1'b0;

v_timing_hsync_r <= 1'b0;

v_timing_active_video_r <= 1'b0;

process_start <= 1'b0;

//process_start_pre <= 1'b0;

process_start_pre <= 1'b1;

end

else

begin

v_video_data_r <= v_video_data_i;

v_timing_vsync_r <= v_timing_vsync_i;

v_timing_hsync_r <= v_timing_hsync_i;

v_timing_active_video_r <= v_timing_active_video_i;

if(dma_write_start)

process_start_pre <= 1'b1;

if((~v_timing_vsync_r) && v_timing_vsync_i && process_start_pre)begin

process_start <= 1'b1;

//process_start_pre <= 1'b0;

end

else if(dma_frame_write_end)

process_start <= 1'b0;

end

end

cross_clk cross_clk1

(

.clkin   (axi_clk),

.din     (frame_last),

.clkout  (v_video_clk),

.dout    (dma_frame_write_end)

);

cross_clk cross_clk2

(

.clkin   (M_APB_PCLK_pin),

.din     (DMA_WRITE_STATUS[0]),

.clkout  (v_video_clk),

.dout    (dma_write_start)

);

always @(posedge v_video_clk) begin

if(!axi_rstn)

write_fifo_num   <= 13'h0;

else if(fifo_wr_en && (write_fifo_num != (WIDTH - 1)))

write_fifo_num   <= write_fifo_num + 1;

else if(fifo_wr_en && (write_fifo_num == (WIDTH - 1)))

write_fifo_num   <= 13'h0;

end

always @(posedge v_video_clk)

begin

if(!axi_rstn)begin

fifo_wr_en = 1'b0;

end

else begin

if((fifo_wr_en == 1'b0) && process_start && v_timing_active_video_i && (write_fifo_num != (WIDTH - 1)))

fifo_wr_en = 1'b1;

else if(write_fifo_num == (WIDTH - 1))

fifo_wr_en = 1'b0;

else if(!process_start)

fifo_wr_en = 1'b0;

end

end

fifo_axi32bit u_fifo_axi32bit (

.wr_clk(v_video_clk),

.rd_clk(axi_clk),

.din({v_video_data_r,8'h00}),

.wr_en(fifo_wr_en),

.rd_en(fifo_rd_en),

.dout(fifo_dout),

.full(fifo_full),

.empty(fifo_empty),

.valid(fifo_valid),

.rd_data_count(fifo_rd_data_count),

.wr_data_count(fifo_wr_data_count)

);

//------------------------------------------------------

// AXI bus

//------------------------------------------------------

assign S_AXI_AWID_pin      = 6'b000000;

assign S_AXI_AWLEN_pin     = 4'hf;     //burst length: 16

assign S_AXI_AWSIZE_pin    = 3'b010;   //size: 4byte

assign S_AXI_AWBURST_pin   = 2'b01;    //incr

assign S_AXI_AWLOCK_pin    = 2'b00;

assign S_AXI_AWCACHE_pin   = 4'b0011; 

assign S_AXI_AWPROT_pin    = 3'b000;

assign S_AXI_AWQOS_pin     = 4'b0000;

assign S_AXI_BREADY_pin    = 1'b1;

assign S_AXI_WSTRB_pin     = 8'b11111111;

assign S_AXI_WID_pin       = 0;

parameter   IDLE        = 4'b0000;

parameter   CHECK_FIFO  = 4'b0001;

parameter   AXI_WRITE   = 4'b0011;

parameter   NEXT_WRITE  = 4'b0111;

parameter   NEXT_LINE   = 4'b1111;

parameter   NEXT_FRAME  = 4'b1110;

parameter   FINISH      = 4'b1100;

reg [3:0]w_cs;

reg [3:0]w_ns;

always @(posedge axi_clk)

begin

if(!axi_rstn)

begin

w_cs <= IDLE;

end

else

begin

w_cs <= w_ns;

end

end

always @(*) begin

case(w_cs)

IDLE: begin

if(process_start)

w_ns  = CHECK_FIFO;

else

w_ns  = w_cs;

end

CHECK_FIFO: begin

if(fifo_rd_data_count >= 10'h10)

w_ns  = AXI_WRITE;

else

w_ns  = w_cs;

end

AXI_WRITE: begin

if(axi_addr_ok && axi_write_ok && ~line_last)

w_ns  = NEXT_WRITE;

else if(axi_addr_ok && axi_write_ok && line_last && ~frame_last)

w_ns  = NEXT_LINE;

else if(axi_addr_ok && axi_write_ok && line_last && frame_last)

w_ns  = NEXT_FRAME;

else

w_ns  = w_cs;

end

NEXT_WRITE: begin

w_ns  = CHECK_FIFO;

end

NEXT_LINE: begin

w_ns  = CHECK_FIFO;

end

NEXT_FRAME: begin // pro

if(frame_num

w_ns  = CHECK_FIFO;

else

w_ns  = FINISH;

end

FINISH: begin

w_ns  = FINISH;

end

default: begin

w_ns  = w_cs;

end

endcase

end

always @(posedge axi_clk) begin

if(!axi_rstn) begin

read_fifo_num    <= 5'h0;

fifo_rd_ok      <= 1'b0;

end

else if(w_ns != AXI_WRITE) begin

read_fifo_num    <= 5'h0;

fifo_rd_ok      <= 1'b0;

end

else if(fifo_rd_en && (read_fifo_num != 5'hf)) begin

read_fifo_num    <= read_fifo_num + 1;

fifo_rd_ok      <= 1'b0;

end

else if(fifo_rd_en && (read_fifo_num == 5'hf)) begin

read_fifo_num    <= 5'h0;

fifo_rd_ok      <= 1'b1;

end

end

assign  fifo_rd_en      = (w_ns == AXI_WRITE && ~stall && !fifo_rd_ok)? 1'b1 : 1'b0;

assign  stall           = (w_cs == AXI_WRITE && ~axi_write_ok && S_AXI_WVALID_pin && ~S_AXI_WREADY_pin)? 1'b1 : 1'b0;

always @(posedge axi_clk) begin

if(!axi_rstn) begin

S_AXI_AWVALID_pin <= 1'b0;

axi_addr_ok <= 1'b0;

end

else if(w_ns == AXI_WRITE && w_cs != AXI_WRITE) begin

S_AXI_AWVALID_pin <= 1'b1;

axi_addr_ok <= 1'b0;

end

else if(S_AXI_AWREADY_pin) begin

S_AXI_AWVALID_pin <= 1'b0;

axi_addr_ok <= 1'b1;

end

end

always @(posedge axi_clk) begin

if(!axi_rstn)

S_AXI_WVALID_pin  <= 1'b0;

else if((S_AXI_WREADY_pin & S_AXI_WVALID_pin) && (axi_write_num == 5'hf))

S_AXI_WVALID_pin  <= 1'b0;

else if(w_cs == AXI_WRITE && ~axi_write_ok)

S_AXI_WVALID_pin  <= 1'b1;

end

always @(posedge axi_clk) begin

if(!axi_rstn)

S_AXI_WDATA_pin   <= 32'h0;

else if(!stall)

S_AXI_WDATA_pin   <= {fifo_dout[7:0],fifo_dout[15:8],fifo_dout[23:16],fifo_dout[31:24]};//{8'h33,8'h22,8'h11,8'h00};

end

wire [31:0] dma_tran_addr;

assign dma_tran_addr = (frame_num == 2'b00)? DMA_DEST_ADDR0 : (frame_num == 2'b01)? DMA_DEST_ADDR1 : DMA_DEST_ADDR2;

always @(posedge axi_clk) begin

if(!axi_rstn)

S_AXI_AWADDR_pin  <= 32'h0;

else if(w_cs == IDLE && w_ns == CHECK_FIFO)

S_AXI_AWADDR_pin  <= dma_tran_addr;

else if(w_cs == NEXT_WRITE && w_ns == CHECK_FIFO)

S_AXI_AWADDR_pin  <= S_AXI_AWADDR_pin + 8'h40; //16 * 1byte

else if(w_cs == NEXT_LINE  && w_ns == CHECK_FIFO)

S_AXI_AWADDR_pin  <= prev_line_start + STRIDE;

else if(w_cs == NEXT_FRAME && w_ns == CHECK_FIFO)

S_AXI_AWADDR_pin  <= dma_tran_addr;

end

always @(posedge axi_clk) begin

if(!axi_rstn)

prev_line_start <= 32'h0;

else if(w_cs == IDLE && w_ns == CHECK_FIFO)

prev_line_start <= dma_tran_addr;

else if(w_cs == NEXT_LINE  && w_ns == CHECK_FIFO)

prev_line_start <= prev_line_start + STRIDE;

else if(w_cs == NEXT_FRAME && w_ns == CHECK_FIFO)

prev_line_start <= dma_tran_addr;

end

always @(posedge axi_clk) begin

if(!axi_rstn) begin

axi_write_num    <= 5'h0;

axi_write_ok    <= 1'b0;

end

else if(w_ns != AXI_WRITE) begin

axi_write_num    <= 5'h0;

axi_write_ok    <= 1'b0;

end

else if((S_AXI_WREADY_pin & S_AXI_WVALID_pin) && (axi_write_num != 5'hf)) begin

axi_write_num    <= axi_write_num + 1;

axi_write_ok    <= 1'b0;

end

else if((S_AXI_WREADY_pin & S_AXI_WVALID_pin) && (axi_write_num == 5'hf)) begin

axi_write_num    <= 5'h0;

axi_write_ok    <= 1'b1;

end

end

always @(posedge axi_clk) begin

if(!axi_rstn)

frame_num    <= 2'b00;

else if(process_start && frame_last && ~frame_last_r)

begin

if(frame_num != 2'b10)

frame_num    <= frame_num + 1;

else

frame_num    <= 2'b00;

end

end

always @(posedge axi_clk) begin

if(!axi_rstn)

hcount  <= 13'h0;

else if(w_ns == NEXT_LINE)

hcount  <= 13'h0;

else if(w_ns == NEXT_FRAME)

hcount  <= 13'h0;

else if(w_ns == NEXT_WRITE)

hcount  <= hcount + 16;

end

always @(posedge axi_clk) begin

if(!axi_rstn)

vcount  <= 13'h0;

else if(w_ns == NEXT_FRAME)

vcount  <= 13'h0;

else if(w_ns == NEXT_LINE)

vcount  <= vcount + 1;

end

always @(posedge axi_clk) begin

if(!axi_rstn)

frame_last_r    <= 1'b0;

else

frame_last_r    <= frame_last;

end

assign  line_last   = (hcount == (WIDTH - 16) )? 1'b1 : 1'b0;

assign  frame_last  = (vcount == (HEIGHT - 1) )? 1'b1 : 1'b0;

assign  S_AXI_WLAST_pin   = (axi_write_num == 5'hf)? 1'b1 : 1'b0;

endmodule

你可能感兴趣的:(linux怎么读zynq的ddr数据,Zedboard & Zynq 图像采集 视频开发 (三) AXI4总线读写DDR)