目錄
前言
一、添加端口
二、添加局部變量
三、例化讀寫(xiě)FIFO
四、內(nèi)部變量修改,設(shè)置一次讀寫(xiě)進(jìn)行多少次突發(fā)操作
五、寫(xiě)地址
六、讀地址
七、狀態(tài)機(jī)
1.寫(xiě)狀態(tài)機(jī)
2.讀狀態(tài)機(jī)
總結(jié)
前言
在Altera FPGA進(jìn)行圖像處理時(shí),我們采用的存儲(chǔ)芯片為SDRAM,當(dāng)時(shí)參照正點(diǎn)原子的例程是封裝SDRAM控制器,然后像操作FIFO一樣去控制SDRAM?,F(xiàn)在換了ZYNQ的板子后,由于DDR3是掛載在PS端的,Xilinx官方提供了視頻接口的IP,但是IP這東西像個(gè)小黑盒子一樣,在開(kāi)發(fā)過(guò)程中遇到了問(wèn)題,極其不易排查,所以我就在官方的AXI4—FULL接口代碼上稍做修改,實(shí)現(xiàn)像以前一樣像操作FIFO一樣去操作PS端的DDR3。
一、添加端口
// Users to add ports here
//圖像數(shù)據(jù)寫(xiě)端口
input wire wr_clk, //輸入像素時(shí)鐘
input wire wr_en, //數(shù)據(jù)有效信號(hào)
input wire [15:0] wr_data, //像素?cái)?shù)據(jù)
//圖像數(shù)據(jù)讀端口
input wire rd_clk, //輸入hdmi驅(qū)動(dòng)時(shí)鐘
input wire rd_en, //讀請(qǐng)求
output wire [15:0] rd_data, //像素?cái)?shù)據(jù)
二、添加局部變量
觸發(fā)一次讀寫(xiě)DDR3的FIFO中的數(shù)據(jù)量設(shè)置為256,當(dāng)寫(xiě)FIFO中的數(shù)據(jù)量大于THRESHOLD進(jìn)行一次寫(xiě)操作的觸發(fā),當(dāng)讀FIFO中的數(shù)據(jù)量小于THRESHOLD時(shí)進(jìn)行一次讀操作的觸發(fā)。一幀圖像的最大存儲(chǔ)地址為FIRST_FRAME
// I/O Connections assignments
localparam THRESHOLD = 256 ; //觸發(fā)寫(xiě)FIFO讀數(shù)據(jù)個(gè)數(shù)
localparam FIRST_FRAME = (640*480)*4 ; //存儲(chǔ)最大值
三、例化讀寫(xiě)FIFO
用作數(shù)據(jù)緩存
// Add user logic here
//寫(xiě)數(shù)據(jù)補(bǔ)位
assign din_wr_fifo = {16'd0,wr_data};
assign wr_en_wr_fifo = wr_en;
assign rd_en_wr = wnext;
//寫(xiě)FIFO
wr_fifo inst_fifo (
.wr_clk(wr_clk), // input wire wr_clk
.rd_clk(M_AXI_ACLK), // input wire rd_clk
.din(din_wr_fifo), // input wire [31 : 0] din
.wr_en(wr_en_wr_fifo), // input wire wr_en
.rd_en(rd_en_wr), // input wire rd_en
.dout(dout_wr_fifo), // output wire [31 : 0] dout
.full(full_wr_fifo), // output wire full
.empty(empty_wr_fifo), // output wire empty
.rd_data_count(rd_data_count_wr_fifo) // output wire [11 : 0] rd_data_count
);
assign rd_data = dout_rd_fifo[15:0];
assign wr_en_rd_fifo = rnext;
//讀FIFO
rd_fifo inst_rd_fifo (
.wr_clk(M_AXI_ACLK), // input wire wr_clk
.rd_clk(rd_clk), // input wire rd_clk
.din(M_AXI_RDATA), // input wire [63 : 0] din
.wr_en(wr_en_rd_fifo), // input wire wr_en
.rd_en(rd_en), // input wire rd_en
.dout(dout_rd_fifo), // output wire [31 : 0] dout
.full(full_rd_fifo), // output wire full
.empty(empty_rd_fifo), // output wire empty
.rd_data_count(rd_data_count_rd_fifo), // output wire [11 : 0] rd_data_count
.wr_data_count(wr_data_count_rd_fifo) // output wire [10 : 0] wr_data_count
);
四、內(nèi)部變量修改,設(shè)置一次讀寫(xiě)進(jìn)行多少次突發(fā)操作
將原本代碼里面C_MASTER_LENGTH 的數(shù)值12更改為10,原本的12表示一次讀寫(xiě)操作進(jìn)行64次突發(fā)操作,由于一次突發(fā)的數(shù)據(jù)量為16個(gè)32位的數(shù)據(jù),所以64*16=1024個(gè)數(shù)據(jù),與AXI4讀寫(xiě)DDR3的實(shí)驗(yàn)現(xiàn)象一致,更改位10的原因?yàn)樽屍湟淮巫x寫(xiě)的數(shù)據(jù)量保持跟設(shè)置的THRESHOLD 一致都為256,避免數(shù)據(jù)沖突。
五、寫(xiě)地址
由于DDR3可以自由設(shè)置數(shù)據(jù)存儲(chǔ)的地址,所以我們?cè)诖a內(nèi)部自己劃分讀寫(xiě)bank,從而可以實(shí)現(xiàn)乒乓操作。
always @(posedge M_AXI_ACLK)begin
if(M_AXI_ARESETN == 0)begin
bank_1 <= 2'b00;
end
else if((axi_awaddr[21:0] == FIRST_FRAME) && writes_done && bank_1 == 2'b00)begin
bank_1 <= 2'b01;
end
else if((axi_awaddr[21:0] == FIRST_FRAME) && writes_done && bank_1 == 2'b01)begin
bank_1 <= 2'b00;
end
else
bank_1 <= bank_1;
end
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
begin
axi_awaddr <= 'b0;
sw_bank_en <= 1'b0;
rw_bank_flag <= 1'b0;
end
else if (M_AXI_AWREADY && axi_awvalid)
begin
//bank0的剩余地址滿足一次突發(fā)長(zhǎng)度
if(axi_awaddr[21:0] < FIRST_FRAME - burst_size_bytes)begin
axi_awaddr <= axi_awaddr + burst_size_bytes;
end
//不滿足切換BANK
else begin
axi_awaddr <= {8'b0000_0000,bank_1,22'd0};
end
end
else
axi_awaddr <= axi_awaddr;
end
六、讀地址
讀地址操作與寫(xiě)地址類似。
七、狀態(tài)機(jī)
1.寫(xiě)狀態(tài)機(jī)
在原本官方狀態(tài)機(jī)上刪除讀狀態(tài)與讀寫(xiě)錯(cuò)誤判斷狀態(tài)。
always @ ( posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 1'b0 )
begin
// reset condition
// All the signals are assigned default values under reset condition
mst_exec_state <= IDLE;
start_single_burst_write <= 1'b0;
compare_done <= 1'b0;
ERROR <= 1'b0;
end
else
begin
// state transition
case (mst_exec_state)
IDLE:
// This state is responsible to wait for user defined C_M_START_COUNT
// number of clock cycles.
if ( init_txn_pulse == 1'b1 || rd_data_count_wr_fifo >= THRESHOLD)
begin
mst_exec_state <= INIT_WRITE;
start_single_burst_write <= 1'b0;
ERROR <= 1'b0;
compare_done <= 1'b0;
end
else
begin
mst_exec_state <= IDLE;
end
INIT_WRITE:
// This state is responsible to issue start_single_write pulse to
// initiate a write transaction. Write transactions will be
// issued until burst_write_active signal is asserted.
// write controller
if (writes_done)
begin
mst_exec_state <= IDLE;//
start_single_burst_write <= 1'b0;
end
else
begin
mst_exec_state <= INIT_WRITE;
if (~axi_awvalid && ~start_single_burst_write && ~burst_write_active)
begin
start_single_burst_write <= 1'b1;
end
else
begin
start_single_burst_write <= 1'b0; //Negate to generate a pulse
end
end
default :
begin
mst_exec_state <= IDLE;
end
endcase
end
end
2.讀狀態(tài)機(jī)
與寫(xiě)狀態(tài)機(jī)類似,照著來(lái)就行文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-787489.html
always @(posedge M_AXI_ACLK)begin
if(M_AXI_ARESETN == 1'b0)begin
curr_state <= IDLE;
start_single_burst_read <= 1'b0;
end
else begin
case(curr_state)
IDLE:
if(wr_data_count_rd_fifo < 2048-THRESHOLD)begin
curr_state <= INIT_READ;
start_single_burst_read <= 1'b0;
end
else begin
curr_state <= IDLE;
end
INIT_READ:
if(reads_done)begin
curr_state <= IDLE;
start_single_burst_read <= 1'b0;
end
else begin
curr_state <= INIT_READ;
if(~axi_arvalid && ~burst_read_active && ~start_single_burst_read)begin
start_single_burst_read <= 1'b1;
end
else begin
start_single_burst_read <= 1'b0;
end
end
default :
begin
curr_state <= IDLE;
end
endcase
end
end
總結(jié)
一開(kāi)始拿到AXI4總線我也是一頭霧水,但認(rèn)真看完總線介紹還是比較簡(jiǎn)單的文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-787489.html
到了這里,關(guān)于ZYNQ AXI4總線訪問(wèn)DDR3實(shí)現(xiàn)圖像數(shù)據(jù)乒乓存儲(chǔ)與顯示的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!