在進行模塊設計時,我們經(jīng)常需要進行數(shù)據(jù)位寬的轉換,常見的兩種轉換場景有同步時鐘域位寬轉換和異步時鐘域位寬轉換。本文將介紹異步時鐘域位寬轉換
異步時鐘域的位寬轉換讀時鐘和寫時鐘屬于兩個時鐘。如下案例中,數(shù)據(jù)位寬由32bit轉40bit,寫時鐘頻率156.25MHz,讀時鐘頻率125Mhz,寫數(shù)據(jù)為32bit,讀數(shù)據(jù)位寬為40bit,通過計算得到入口數(shù)據(jù)速率和出口數(shù)據(jù)速率保持一致(156.25 *32==40 *125)。
存儲模塊是由寄存器搭建的。那么需要多大存儲模塊呢?32和40的最小公倍數(shù)為160,極限場景下,只需要160bit的寄存器作為存儲就夠了,但是讀操作通常晚于寫操作,并且考慮到時鐘有抖動有偏移,為了避免溢出,稍微增加一部分緩存,我們可以采用320bit作為存儲模塊。因此寫側32bit寫10次,讀側40bit讀8次,讀寫兩側所需的時間相等。
注意事項:寫地址(wr_addr)跳轉范圍是09,讀地址(rd_addr)跳轉范圍07。
如圖所示:
buff_array為320bit的數(shù)據(jù)存儲。
vld_array為80bit的有效標志位存儲:vld_array[n]為1表示buff_array[4n+3:4n]存在4bit的有效數(shù)據(jù)。
always @(posedge wr_clk or negedge wr_rst_n) begin
if (~wr_rst_n) begin
buff_array <= {DATA_FIFO_DEPTH{1'b0}};
vld_array <= {VALID_FIFO_DEPTH{1'b0}};
end else begin
if (wr_en) begin
buff_array[ wr_addr*32 +: 32] <= wr_data_i;
vld_array[wr_addr*8 +: 8] <= {8{wr_valid_i}};
end
end
end
reg [10-1:0] rd_valid_bus;
reg [40-1:0] rd_data_bus;
always @(*) begin
rd_data_bus[40-1:0] = buff_array[ rd_addr*40 +: 40];
rd_valid_bus[10-1:0] = vld_array[rd_addr*10 +: 10];
end
integer i;
reg [40-1:0] rd_data_valid_mask;
always @(*) begin
for(i = 0; i < 40; i = i + 1) begin
rd_data_valid_mask[i] = rd_valid_bus[i/4];
end
end
always @(posedge rd_clk or negedge rd_rst_n) begin
if (~rd_rst_n) begin
rd_data_o <= {40{1'b0}};
rd_valid_o <= 1'b0;
end else begin
if (rd_en) begin
rd_data_o <= rd_data_bus & rd_data_valid_mask;
rd_valid_o <= |rd_valid_bus;
end else begin
rd_data_o <= {40{1'b0}};
rd_valid_o <= 1'b0;
end
end
end
-
寄存器
+關注
關注
31文章
5430瀏覽量
123987 -
IC設計
+關注
關注
38文章
1354瀏覽量
105501 -
RAM
+關注
關注
8文章
1391瀏覽量
117144 -
CLK
+關注
關注
0文章
127瀏覽量
17575 -
異步時鐘
+關注
關注
0文章
17瀏覽量
9501
發(fā)布評論請先 登錄
關于異步時鐘域的理解問題:
FPGA請重視異步時鐘域問題
如何處理好FPGA設計中跨時鐘域問題?
探尋FPGA中三種跨時鐘域處理方法
異步FIFO的設計分析及詳細代碼

評論