FPGA基礎設計(7)雙口RAM乒乓操作
雙口RAM經常用於跨時鐘域處理,且比FIFO靈活性更大。本文給出一個具體的設計例項,讓大家理解雙口RAM在跨時鐘域處理中乒乓操作的用法。
輸入資料速率20MHz,輸出資料速率100Mhz,使用雙口RAM完成跨時鐘域處理。一次傳輸的資料為1024個,假設資料位寬為8bit,使用兩片寬度為8、深度為1024的雙口RAM完成資料傳輸。
使用乒乓操作提高讀寫效率,寫RAM1時,讀取RAM2中的資料;寫RAM2時,讀取RAM1中的資料。資料讀取速率為資料寫入速率的5倍,因此寫資料端可以一直保持資料寫入,而讀資料端按寫入一組資料時間的1/5進行,使用out_valid訊號表示讀出的資料有效。
Vivado環境下,RAM使用Block Memory Generator IP核配置,儲存型別選擇為“True Dual Port RAM”。RAM在讀取資料時根據配置引數會有一定的延遲,設計時要注意時序對齊(否則會容易丟掉開頭或結尾的一些資料),程式碼如下:
`timescale 1ns / 1ps
module DualRAM
(
input clk_wr, //寫時鐘速率20Mhz
input clk_rd, //讀時鐘速率100Mhz
input rst_n,
input [7:0] din,
output reg out_valid,
output reg [7:0] dout
);
reg [9:0] addr_wr, addr_rd;
reg en_wr1, en_wr2, we_wr1, we_wr2, en_rd1, en_rd2;
wire [7:0] dout1, dout2;
dual_port_ram u1 (
.clka(clk_wr), //寫埠
.ena(en_wr1),
.wea(we_wr1),
.addra(addr_wr),
.dina(din),
.douta(),
.clkb(clk_rd), //讀埠
.enb(en_rd1),
.web(1'b0),
.addrb(addr_rd),
.dinb(8'd0),
.doutb(dout1)
);
dual_port_ram u2 (
.clka(clk_wr), //寫埠
.ena(en_wr2),
.wea(we_wr2),
.addra(addr_wr),
.dina(din),
.douta(),
.clkb(clk_rd), //讀埠
.enb(en_rd2),
.web(1'b0),
.addrb(addr_rd),
.dinb(8'd0),
.doutb(dout2)
);
//寫埠乒乓操作
always @ (posedge clk_wr) //寫地址訊號控制0~1023
if (!rst_n) addr_wr <= 1023;
else addr_wr <= addr_wr + 1'b1;
always @ (posedge clk_wr) //輪流寫RAM1與RAM2
if (!rst_n) begin we_wr1 <= 1'b1; we_wr2 <= 1'b0;
en_wr1 <= 1'b1; en_wr2 <= 1'b0; end
else if (addr_wr == 1023) begin
we_wr1 <= ~we_wr1; we_wr2 <= ~we_wr2;
en_wr1 <= ~en_wr1; en_wr2 <= ~en_wr2;
end
//讀埠乒乓操作
always @ (posedge clk_rd) //讀地址訊號控制0~1023
if (!rst_n) addr_rd <= 1021; //匹配延遲
else addr_rd <= addr_rd + 1'b1;
reg [15:0] cnt;
always @ (posedge clk_rd) //讀時鐘為寫時鐘的5倍
if (!rst_n) cnt <= 16'hFFFE; //匹配延遲
else if (cnt == 5119) cnt <= 0;
else cnt <= cnt + 1'b1;
reg flag1, flag2;
always @ (posedge clk_rd) //讀RAM標誌,RAM1或RAM2
if (!rst_n) begin flag1 <= 1'b1; flag2 <= 1'b0; end
else if (cnt == 5119) begin flag1 = ~flag1; flag2 = ~flag2; end
else begin flag1 <= flag1; flag2 <= flag2; end
always @ (posedge clk_rd) //讀RAM使能,選擇cnt的前1/5時間讀取
if (!rst_n) begin en_rd1 <= 1'b1; en_rd2 <= 1'b0; end
else if (cnt < 1024) begin en_rd1 <= flag1; en_rd2 <= flag2; end
else begin en_rd1 <= 1'b0; en_rd2 <= 1'b0; end
reg en_rd1_reg, en_rd2_reg;
always @ (posedge clk_rd) //延遲一級,匹配時序
if (!rst_n) begin en_rd1_reg <= 0; en_rd1_reg <= en_rd1_reg; end
else begin en_rd1_reg <= en_rd1; en_rd2_reg <= en_rd2; end
always @ (posedge clk_rd) //輸出選擇,RAM1或RAM2;控制輸出使能訊號
if (!rst_n) begin dout <= 0; out_valid <= 0; end
else if (en_rd1_reg) begin dout <= dout1; out_valid <= 1; end
else if (en_rd2_reg) begin dout <= dout2; out_valid <= 1; end
else begin dout <= 0; out_valid <= 0; end
endmodule
整體模擬結果如下圖所示,看以看到整個乒乓操作的流程。實際上由於時序問題,模擬時經歷了很多階段,總體而言首先要模擬寫時序能準確地把資料寫入到RAM中,然後再模擬讀時序能正確讀取資料。
讀時鐘clk_rd是寫時鐘clk_wr的5倍。寫埠Write Port部分,一直保持資料寫入,不停在兩片RAM間切換:en_wr1和we_wr1控制RAM1的寫入,第一個douta為RAM1的A埠讀出的資料;en_wr2和we_wr2控制RAM2的寫入,第二個douta為RAM2的A埠讀出的資料。
讀埠Read Port部分,en_rd1和en_rd2為RAM1和RAM2的讀使能訊號,輪流開啟。dout1和dout2為RAM1和RAM2的讀取資料,同樣輪流輸出有效。dout即為整體設計的輸出資料,在dout1和dout2之間切換選擇。當dout輸出有效時,out_valid訊號置高。
檢視前兩組寫入的資料,第一組為“24、81、09…2f、44、9b”寫入RAM2,第二組為“62、e9、2e…59、d7、87”寫入RAM1,如下圖所示:
檢視輸出dout和有效訊號valid如下圖:
上圖為第一組資料從RAM2中讀取,讀出資料為“24、81、09…2f、44、9b”,同時out_valid訊號置高。
上圖為第二組資料從RAM1中讀取,讀出資料為“62、e9、2e…59、d7、87”,同時out_valid訊號置高。可以看到輸出資料保持連貫性,沒有漏掉資料,表明設計正確。
相關文章
- 【iCore4 雙核心板_FPGA】例程十六:基於雙口RAM的ARM+FPGA資料存取實驗FPGA
- 【iCore1S 雙核心板_FPGA】例程十七:基於雙口RAM的ARM+FPGA資料存取實驗FPGA
- 【iCore3 雙核心板_FPGA】實驗十九:基於雙口RAM的ARM+FPGA資料存取實驗FPGA
- 【iCore4 雙核心板_FPGA】例程十五:基於單口RAM的ARM+FPGA資料存取實驗FPGA
- 【iCore1S 雙核心板_FPGA】例程十二:基於單口RAM的ARM+FPGA資料存取實驗FPGA
- 【iCore3 雙核心板_FPGA】實驗十八:基於單口RAM的ARM+FPGA資料存取實驗FPGA
- FPGA基礎設計(6)使用DAC的Interleaved模式FPGA模式
- 【FPGA基礎】Latch基礎FPGA
- FPGA入門筆記011_B——搭建串列埠收發與存取雙口RAM簡易應用系統FPGA筆記串列埠
- FPGA程式設計基礎(二)--常用行為模擬描述FPGA程式設計
- 基於FPGA的光口通訊開發案例|基於Kintex-7 FPGA SFP+光口的10G UDP網路通訊開發案例FPGAUDP
- 【iCore4 雙核心板_FPGA】實驗十八:Niosii——基於內部RAM建立第一個軟核FPGAiOS
- 併發程式設計基礎與原子操作程式設計
- FPGA程式設計基礎(一)--引數傳遞與暫存器使用FPGA程式設計
- 【硬體設計風口】RK3399實現雙網口
- 【iCore3 雙核心板_FPGA】實驗二十一:Niosii——基於內部RAM建立第一個軟核FPGAiOS
- (7)ram ip使用
- [.net 物件導向程式設計基礎] (7) 基礎中的基礎——流程控制語句物件程式設計
- 【JS基礎】阻止預設操作JS
- 收藏: 全面解析FPGA基礎知識FPGA
- 【設計模式基礎】行為模式 - 7 - 迭代器(Iterator)設計模式
- 程式設計基礎程式設計
- 7步做好雲端計算基礎設施的監控
- 網路程式設計基礎-socket基礎程式設計
- 【iCore3 雙核心板_FPGA】實驗二十七:基於SDRAM的TFT驅動器的設計FPGA
- 【iCore3 雙核心板_FPGA】實驗二十八:基於SDRAM 的VGA 驅動器的設計FPGA
- 【iCore4 雙核心板_FPGA】例程五:基礎邏輯閘實驗——邏輯閘使用FPGA
- 【iCore3 雙核心板_FPGA】例程七:基礎邏輯閘實驗——邏輯閘使用FPGA
- 《計算機基礎與程式設計》第7周學習總結計算機程式設計
- java 設計模式基礎Java設計模式
- Socket程式設計基礎程式設計
- Go程式設計基礎Go程式設計
- Java程式設計基礎Java程式設計
- Shell程式設計-基礎程式設計
- C程式設計基礎C程式程式設計
- shell程式設計基礎程式設計
- Java 基礎02Java程式設計基礎Java程式設計
- 【iCore4 雙核心板_FPGA】例程十三:基於SPI的ARM與FPGA通訊實驗FPGA