在進行模塊設計時,我們經常需要進行數據位寬的轉換,常見的兩種轉換場景有同步時鐘域位寬轉換和異步時鐘域位寬轉換。本文將介紹異步時鐘域位寬轉換
異步時鐘域的位寬轉換讀時鐘和寫時鐘屬于兩個時鐘。如下案例中,數據位寬由32bit轉40bit,寫時鐘頻率156.25MHz,讀時鐘頻率125Mhz,寫數據為32bit,讀數據位寬為40bit,通過計算得到入口數據速率和出口數據速率保持一致(156.25 *32==40 *125)。
存儲模塊是由寄存器搭建的。那么需要多大存儲模塊呢?32和40的最小公倍數為160,極限場景下,只需要160bit的寄存器作為存儲就夠了,但是讀操作通常晚于寫操作,并且考慮到時鐘有抖動有偏移,為了避免溢出,稍微增加一部分緩存,我們可以采用320bit作為存儲模塊。因此寫側32bit寫10次,讀側40bit讀8次,讀寫兩側所需的時間相等。
注意事項:寫地址(wr_addr)跳轉范圍是09,讀地址(rd_addr)跳轉范圍07。
如圖所示:
buff_array為320bit的數據存儲。
vld_array為80bit的有效標志位存儲:vld_array[n]為1表示buff_array[4n+3:4n]存在4bit的有效數據。
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文章
5343瀏覽量
120373 -
IC設計
+關注
關注
38文章
1296瀏覽量
103957 -
RAM
+關注
關注
8文章
1368瀏覽量
114701 -
CLK
+關注
關注
0文章
127瀏覽量
17171 -
異步時鐘
+關注
關注
0文章
17瀏覽量
9407
發(fā)布評論請先 登錄
相關推薦
評論