小梅哥的這個ZYNQ開發板上的DDR3位於PS側,PL側想要使用DDR3作為緩存的話,得通過HP介面來與PS側的DDR3控制進行通信。 本次實驗在小梅哥OV5640工程的基礎上,通過修改VDMA的S2MM端的模塊而來的。 將VMDA的幀緩存區設為1,關閉幀同步的功能後,其實和DMA差不多。 一、需要 ...
小梅哥的這個ZYNQ開發板上的DDR3位於PS側,PL側想要使用DDR3作為緩存的話,得通過HP介面來與PS側的DDR3控制進行通信。
本次實驗在小梅哥OV5640工程的基礎上,通過修改VDMA的S2MM端的模塊而來的。
將VMDA的幀緩存區設為1,關閉幀同步的功能後,其實和DMA差不多。
一、需要自定義的ip核
這裡列出的為自己寫的IP核。小梅哥的工程里還用到了其它的自定義的IP核,這裡就不列出了。
1、串口接收圖像數據模塊
該模塊調用了之前寫的串口8位接收模塊,詳情可點擊查看。
此外,本模塊還調用16位寬、深度為1024的帶數據計數的普通FIFO核
該模塊主要的思想就是將接收到的兩個8位的數據拼接位1個16位的數據並存入FIFO中,
當存入的數據達到LINE_LENGTH(800)的時候,在收到從介面的準備信號時一次性寫入VMDA中,再通過VMDA將數據寫到DDR3中。
此外該模塊在應用的時候要封裝成帶AXI4_Stream 介面的IP核,具體封裝過程可網上找教程。
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: GDUT
// Engineer: Lclone
//
// Create Date: 2023/02/07 20:38:34
// Design Name:
// Module Name: Img_Rx
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module Img_Rx
# (parameter RX_BAUD = 115200,
parameter CLK_FQC = 50_000_000,
parameter LINE_LENGTH = 800)
(
input Uart_Rx,
//---------------------------
input m_clk,
input m_axis_aresetn,
output [15:0] m_axis_tdata,
output reg m_axis_tlast,
input m_axis_tready,
output reg m_axis_tvalid
);
wire [7:0] Uart_Data;
wire Rx_done;
reg Rx_done_r;
reg Rx_done_cnt;
reg [15:0] Uart_Data_16;
wire [9:0] fifo_data_count;
reg [9:0] out_data_count;
reg m_axis_tvalid_r;
reg [18:0] cnt_1ms;
always @(posedge m_clk) Rx_done_r <= Rx_done;
always @(posedge m_clk) m_axis_tvalid <= m_axis_tvalid_r;
always @(posedge m_clk or negedge m_axis_aresetn) begin
if(m_axis_aresetn == 0)
Uart_Data_16 <= 0;
else if(Rx_done == 1)
Uart_Data_16 <= {Uart_Data_16[7:0],Uart_Data};
end
always @(posedge m_clk or negedge m_axis_aresetn) begin
if(m_axis_aresetn == 0)
Rx_done_cnt <= 0;
else if(Rx_done == 1)
Rx_done_cnt <= Rx_done_cnt + 1'b1;
else
Rx_done_cnt <= Rx_done_cnt;
end
always @(posedge m_clk or negedge m_axis_aresetn) begin
if(m_axis_aresetn == 0)
m_axis_tvalid_r <= 0;
else if(m_axis_tready == 1 & fifo_data_count >= LINE_LENGTH)
m_axis_tvalid_r <= 1'b1;
else if(fifo_data_count <= 1)
m_axis_tvalid_r <= 0;
else
m_axis_tvalid_r <= m_axis_tvalid_r;
end
always @(posedge m_clk or negedge m_axis_aresetn) begin
if(m_axis_aresetn == 0)
out_data_count <= 0;
else if(out_data_count == LINE_LENGTH - 1)
out_data_count <= 0;
else if(m_axis_tvalid_r & m_axis_tready)
out_data_count <= out_data_count + 1'b1;
else
out_data_count <= out_data_count;
end
always @(posedge m_clk or negedge m_axis_aresetn) begin
if(m_axis_aresetn == 0)
m_axis_tlast <= 0;
else if(out_data_count == LINE_LENGTH - 1)
m_axis_tlast <= 1;
else
m_axis_tlast <= 0;
end
always @(posedge m_clk or negedge m_axis_aresetn) begin
if(m_axis_aresetn == 0)
cnt_1ms <= 0;
else if(cnt_1ms == 500000 - 1)
cnt_1ms <= 0;
else
cnt_1ms <= cnt_1ms + 1'b1;
end
uart_byte_rx
# (
.RX_BAUD (RX_BAUD),
.CLK_FQC (CLK_FQC))
uart_byte_rx_inst
(
.Clk (m_clk),
.Rst_n (m_axis_aresetn),
.Uart_rx (Uart_Rx),
.Data (Uart_Data),
.Rx_done (Rx_done)
);
fifo_generator_0 fifo_generator_0_inst (
.clk(m_clk), // input wire clk
.srst(~m_axis_aresetn), // input wire srst
.din(Uart_Data_16), // input wire [15 : 0] din
.wr_en(~Rx_done_cnt & Rx_done_r), // input wire wr_en
.rd_en(m_axis_tvalid_r & m_axis_tready), // input wire rd_en
.dout(m_axis_tdata), // output wire [15 : 0] dout
.full(), // output wire full
.empty(), // output wire empty
.data_count(fifo_data_count) // output wire [9 : 0] data_count
);
endmodule
2、模塊模擬
(1)模擬激勵
`timescale 1ns / 1ps
module rx_img_test();
reg clk_50m;
initial clk_50m <= 1;
always #10 clk_50m <= ~clk_50m;
reg rst_n;
initial begin
rst_n <= 0;
#200
rst_n <= 1;
end
wire [15:0] m_axis_tdata;
wire m_axis_tlast;
wire m_axis_tready;
wire m_axis_tvalid;
wire [15:0] out_axis_tdata;
wire out_axis_tlast;
wire out_axis_tready;
wire out_axis_tvalid;
reg Uart_Rx;
reg [ 7:0] Uart_Data;
Img_Rx #(
.RX_BAUD(2_000_000),
.CLK_FQC(100_000_000),
.LINE_LENGTH(16)
)
Img_Rx_inst (
.Uart_Rx(Uart_Rx), // input wire Uart_Rx
.m_clk(clk_50m), // input wire m_clk
.m_axis_aresetn(rst_n), // input wire m_axis_aresetn
.m_axis_tdata(m_axis_tdata), // output wire [15 : 0] m_axis_tdata
.m_axis_tlast(m_axis_tlast), // output wire m_axis_tlast
.m_axis_tready(m_axis_tready), // input wire m_axis_tready
.m_axis_tvalid(m_axis_tvalid) // output wire m_axis_tvalid
);
axis_data_fifo_0 axis_data_fifo_0_inst (
.s_axis_aresetn(rst_n), // input wire s_axis_aresetn
.s_axis_aclk(clk_50m), // input wire s_axis_aclk
.s_axis_tvalid(m_axis_tvalid), // input wire s_axis_tvalid
.s_axis_tready(m_axis_tready), // output wire s_axis_tready
.s_axis_tdata(m_axis_tdata), // input wire [15 : 0] s_axis_tdata
.s_axis_tlast(m_axis_tlast), // input wire s_axis_tlast
.m_axis_tvalid(out_axis_tvalid), // output wire m_axis_tvalid
.m_axis_tready(out_axis_tready), // input wire m_axis_tready
.m_axis_tdata(out_axis_tdata), // output wire [15 : 0] m_axis_tdata
.m_axis_tlast(out_axis_tlast) // output wire m_axis_tlast
);
initial begin
Uart_Rx <= 1;
Uart_Data <= 0;
#200
repeat (256) begin
data_deliver(Uart_Data);
Uart_Data = Uart_Data + 1;
end
$stop;
end
task data_deliver;
input [7:0] test_data;
begin
Uart_Rx <= 1'b0;
#1000
Uart_Rx <= test_data[0];
#1000
Uart_Rx <= test_data[1];
#1000
Uart_Rx <= test_data[2];
#1000
Uart_Rx <= test_data[3];
#1000
Uart_Rx <= test_data[4];
#1000
Uart_Rx <= test_data[5];
#1000
Uart_Rx <= test_data[6];
#1000
Uart_Rx <= test_data[7];
#1000
Uart_Rx <= 1'b1;
#1000;
end
endtask
assign out_axis_tready = 1;
endmodule
(2)模擬結果
可見該模塊能夠正確地將16個兩位元組的數據正確的輸出,併在最後一個數據的位置基於一個tlast信號。
二、工程修改
打開小梅哥的ACZ7020的OV5640_LCD工程,然後將紅框部分的模塊刪除,加入自定義的串口接收圖像數據模塊。
並修改下列IP核的參數
將頻率修改為如下:
將幀緩存區設為1
Fsync Options選擇None,關掉幀同步功能
在約束文件中,加入串口的管腳約束
在SDK中,將OV5640的初始化函數刪除,將PS_IIC和OV5640庫刪除
同時也將PS_IIC和OV5640庫的路徑刪除掉
然後就可以下載程式到開發板上了
三、上板驗證
將程式下載進開發板,然後打開img2lcd軟體,讀取一個800*480大小的BMP文件,並按如下設置:
然後在輸出的文件中進行修改
刪除首行
刪除末尾符號
使用軟體的查找替換功能,將所有的0X刪掉,並將","換為空格符,然後使用行操作裡面的行合併去除掉每一行末尾的回車符。最後就得到傳輸的圖像數據:
打開友善串口調試助手,將圖像數據複製進去,打開串口埠,設置好波特率,然後發送,確保TX發送了768000個位元組,否則圖像會錯位;確保底下綠色的字顯示的波特率為115200,否則數據無法正確傳輸。
傳輸數據後,發現圖像能夠正確顯示在LCD上
實驗成功。
本隨筆還有許多小細節沒有給出,如果遇到問題,可以評論詢問。