利用bram形成雙緩沖,如下圖配置所示:
wr_flag 表明?buffer0寫 還是 buffer1寫? ? ? ? ? ? ?rd_flag?表明 buffer0讀 還是 buffer1讀
通過寫入邏輯控制(結合wr_finish)? 寫哪個buffer ;寫地址? 進而控制ip的寫使能
通過狀態緩存來跳轉buffer的寫和讀
通過讀取邏輯(結合rd_finish)? ? ? ? ?讀哪個buffer ;讀地址
最后通過時序控制,調整輸出數據及數據有效對齊
`timescale 1ns / 1ps
//
// Description: 水平鏡像
//
module image_horizion_flip(input wire clk,input wire reset,input wire [10:0] img_width,input wire valid_i,input wire [23:0] data_i,output reg valid_o,output reg [23:0] data_o
);///有關寫邏輯部分的變量申明
reg wr_flag ;
reg [10:0] addra ;
//一行像素寫入buffer結束標志
wire wr_finish;
assign wr_finish = (valid_i && (addra == img_width - 1))? 1'b1 : 1'b0;
//buffer0/1的寫使能
wire buffer0_wr, buffer1_wr;
assign buffer0_wr = valid_i&(~wr_flag);
assign buffer1_wr = valid_i&wr_flag;///有關讀邏輯部分的變量申明
reg buffer0_status, buffer1_status;
//讀數據使能 讀取數據 緩存完一行,啟動讀數據。
wire rd_en;
assign rd_en = buffer0_status|buffer1_status;reg rd_flag;
reg [10:0] addrb;
//一行像素讀出buffer結束標志
wire rd_finish;
assign rd_finish = rd_en&&(addrb == img_width - 1) ? 1'b1 : 1'b0;wire [23:0] buffer0_dout, buffer1_dout;
reg rd_en_d;
reg rd_flag_d;
///寫入邏輯//
//寫入地址,wr_flag等于0時,寫入buffer0,等于1時,寫入buffer1
always@(posedge clk or posedge reset) beginif(reset) beginwr_flag <= 0;addra <= 0;end else beginwr_flag <= wr_finish ? ~wr_flag : wr_flag;addra <= wr_finish ? 0 : (valid_i ? (addra + 1'b1) : addra);end
end/緩存狀態保存///
//先判斷buffer是否寫滿,寫滿開始讀;繼而判斷是否讀空,讀空則開始寫
always@(posedge clk or posedge reset) beginif(reset) beginbuffer0_status <= 0;buffer1_status <= 0;end else beginbuffer0_status <= ((~wr_flag) && wr_finish) ? 1'b1 :(((~rd_flag) && rd_finish) ? 1'b0 : buffer0_status);buffer1_status <= (wr_flag && wr_finish) ? 1'b1:((rd_flag && rd_finish) ? 1'b0 : buffer1_status);end
end /讀取邏輯///
//讀地址一般邏輯
always@(posedge clk or posedge reset) beginif(reset) beginaddrb <= 0;rd_flag <= 0;end else beginaddrb <= rd_en ? ((addrb == img_width - 1) ? 'b0 : addrb + 1'b1) : addrb;rd_flag <= rd_finish ? ~rd_flag : rd_flag;end
end
//鏡像讀數據地址 水平鏡像,從右往左
wire [10:0] addrb_flip;
assign addrb_flip = img_width - 1 - addrb;bram_line_buffer u0 (.clka (clk ), // input wire clka.wea (buffer0_wr ), // input wire [0 : 0] wea.addra(addra ), // input wire [10 : 0] addra.dina (data_i ), // input wire [23 : 0] dina.clkb (clk ), // input wire clkb.addrb(addrb_flip ), // input wire [10 : 0] addrb.doutb(buffer0_dout) // output wire [23 : 0] doutb
);bram_line_buffer u1 (.clka (clk ), // input wire clka.wea (buffer1_wr ), // input wire [0 : 0] wea.addra(addra ), // input wire [10 : 0] addra.dina (data_i ), // input wire [23 : 0] dina.clkb (clk ), // input wire clkb.addrb(addrb_flip ), // input wire [10 : 0] addrb.doutb(buffer1_dout) // output wire [23 : 0] doutb
);//輸出數據打一拍延時
always@(posedge clk or posedge reset) beginif(reset) beginrd_en_d <= 0;rd_flag_d <= 0;end else beginrd_en_d <= rd_en;rd_flag_d <= rd_flag;endend
//輸出
always@(posedge clk or posedge reset) beginif(reset) beginvalid_o <= 0;data_o <= 0;end else beginvalid_o <= rd_en_d;data_o <= rd_flag_d ? buffer1_dout : buffer0_dout;end
end endmodule