FIFO 很重要,之前參加的各類電子公司的邏輯設計的筆試幾乎都會考到。
FIFO是英文First In First Out 的縮寫,是一種先進先出的數據緩存器,他與普通存儲器的區別是沒有外部讀寫地址線,這樣使用起來非常簡單,但缺點就是只能順序寫入數據,順序的讀出數據, 其數據地址由內部讀寫指針自動加1完成,不能像普通存儲器那樣可以由地址線決定讀取或寫入某個指定的地址。
?FIFO一般用于不同時鐘域之間的數據傳輸,比如FIFO的一端是AD數據采集, 另一端是計算機的PCI總線,假設其AD采集的速率為16位 100K SPS,那么每秒的數據量為100K×16bit=1.6Mbps,而PCI總線的速度為33MHz,總線寬度32bit,其最大傳輸速率為 1056Mbps,在兩個不同的時鐘域間就可以采用FIFO來作為數據緩沖。另外對于不同寬度的數據接口也可以用FIFO,例如單片機位8位數據輸出,而 DSP可能是16位數據輸入,在單片機與DSP連接時就可以使用FIFO來達到數據匹配的目的。
?
FIFO的分類根均FIFO工作的時鐘域,可以將FIFO分為同步FIFO和異步FIFO。同步FIFO是指讀時鐘和寫時鐘為同一個時鐘。在時鐘沿來臨時同時發生讀寫操作。異步FIFO是指讀寫時鐘不一致,讀寫時鐘是互相獨立的。
?
FIFO設計的難點 FIFO設計的難點在于怎樣判斷FIFO的空/滿狀態。為了保證數據正確的寫入或讀出,而不發生益處或讀空的狀態出現,必須保證FIFO在滿的情況下,不 能進行寫操作。在空的狀態下不能進行讀操作。怎樣判斷FIFO的滿/空就成了FIFO設計的核心問題。
.........................................................................................................................................
同步FIFO的Verilog代碼 之一
在modlesim中驗證過。
/******************************************************A fifo controller verilog description.******************************************************/module fifo(datain, rd, wr, rst, clk, dataout, full, empty);input [7:0] datain;input rd, wr, rst, clk;output [7:0] dataout;output full, empty;wire [7:0] dataout;reg full_in, empty_in;reg [7:0] mem [15:0];reg [3:0] rp, wp;assign full = full_in;assign empty = empty_in;// memory read outassign dataout = mem[rp];// memory write inalways@(posedge clk) begin??? if(wr && ~full_in) mem[wp]<=datain;end// memory write pointer incrementalways@(posedge clk or negedge rst) begin??? if(!rst) wp<=0;??? else begin????? if(wr && ~full_in) wp<= wp+1'b1;??? endend// memory read pointer incrementalways@(posedge clk or negedge rst)begin??? if(!rst) rp <= 0;??? else begin????? if(rd && ~empty_in) rp <= rp + 1'b1;??? endend// Full signal generatealways@(posedge clk or negedge rst) begin??? if(!rst) full_in <= 1'b0;??? else begin????? if( (~rd && wr)&&((wp==rp-1)||(rp==4'h0&&wp==4'hf)))????????? full_in <= 1'b1;????? else if(full_in && rd) full_in <= 1'b0;??? endend// Empty signal generatealways@(posedge clk or negedge rst) begin??? if(!rst) empty_in <= 1'b1;??? else begin????? if((rd&&~wr)&&(rp==wp-1 || (rp==4'hf&&wp==4'h0)))??????? empty_in<=1'b1;????? else if(empty_in && wr) empty_in<=1'b0;??? endendendmodule
...........................................................................................................................
同步FIFO的Verilog代碼 之二
這一種設計的FIFO,是基于觸發器的。寬度,深度的擴展更加方便,結構化跟強。以下代碼在modelsim中驗證過。
module fifo_cell (sys_clk, sys_rst_n, read_fifo, write_fifo, fifo_input_data,??????????????????????? next_cell_data, next_cell_full, last_cell_full, cell_data_out, cell_full);??????????????????????? parameter WIDTH =8;??????????????????????? parameter D = 2;??????????????????????? input sys_clk;??????????????????????? input sys_rst_n;??????????????????????? input read_fifo, write_fifo;??????????????????????? input [WIDTH-1:0] fifo_input_data;??????????????????????? input [WIDTH-1:0] next_cell_data;??????????????????????? input next_cell_full, last_cell_full;??????????????????????? output [WIDTH-1:0] cell_data_out;??????????????????????? output cell_full;??????????????????????? reg [WIDTH-1:0] cell_data_reg_array;??????????????????????? reg [WIDTH-1:0] cell_data_ld;??????????????????????? reg cell_data_ld_en;??????????????????????? reg cell_full;??????????????????????? reg cell_full_next;??????????????????????? assign cell_data_out=cell_data_reg_array;??????????????????????? always @(posedge sys_clk or negedge sys_rst_n)?????????????????????????? if (!sys_rst_n)????????????????????????????? cell_full <= #D 0;?????????????????????????? else if (read_fifo || write_fifo)????????????????????????????? cell_full <= #D cell_full_next;??????????????????????? always @(write_fifo or read_fifo or next_cell_full or last_cell_full or cell_full)?????????????????????????? casex ({read_fifo, write_fifo})?????????????????????????????? 2'b00: cell_full_next = cell_full;?????????????????????????????? 2'b01: cell_full_next = next_cell_full;?????????????????????????????? 2'b10: cell_full_next = last_cell_full;?????????????????????????????? 2'b11: cell_full_next = cell_full;?????????????????????????? endcase???????????????????????? always @(posedge sys_clk or negedge sys_rst_n)????????????????????????????? if (!sys_rst_n)???????????????????????????????? cell_data_reg_array [WIDTH-1:0] <= #D 0;????????????????????????????? else if (cell_data_ld_en)???????????????????????????????? cell_data_reg_array [WIDTH-1:0] <= #D cell_data_ld [WIDTH-1:0];???????????????????????? always @(write_fifo or read_fifo or cell_full or last_cell_full)???????????????????????????????? casex ({write_fifo,read_fifo,cell_full,last_cell_full})????????????????????????????????? 4'bx1_xx: cell_data_ld_en = 1'b1;????????????????????????????????? 4'b10_01: cell_data_ld_en = 1'b1;????????????????????????????????? default: cell_data_ld_en =1'b0;????????????????????????????? endcase???????????????????????? always @(write_fifo or read_fifo or next_cell_full or cell_full or last_cell_full or fifo_input_data or next_cell_data)????????????????????????????? casex ({write_fifo, read_fifo, next_cell_full, cell_full, last_cell_full})???????????????????????????????? 5'b10_x01: cell_data_ld[WIDTH-1:0] = fifo_input_data[WIDTH-1:0];???????????????????????????????? 5'b11_01x: cell_data_ld[WIDTH-1:0] = fifo_input_data[WIDTH-1:0];???????????????????????????????? default: cell_data_ld[WIDTH-1:0] = next_cell_data[WIDTH-1:0];????????????????????????????? endcaseendmodule
?
module fifo_4cell(sys_clk, sys_rst_n, fifo_input_data, write_fifo, fifo_out_data,????????????????? read_fifo, full_cell0, full_cell1, full_cell2, full_cell3);????????????????? parameter WIDTH = 8;????????????????? parameter D = 2;????????????????? input sys_clk;????????????????? input sys_rst_n;????????????????? input [WIDTH-1:0] fifo_input_data;????????????????? output [WIDTH-1:0] fifo_out_data;????????????????? input read_fifo, write_fifo;????????????????? output full_cell0, full_cell1, full_cell2, full_cell3;????????????????? wire [WIDTH-1:0] dara_out_cell0, data_out_cell1, data_out_cell2,?????????????????????????????????? data_out_cell3, data_out_cell4;????????????????? wire full_cell4;????????????????? fifo_cell #(WIDTH,D) cell0????????????????? ( .sys_clk (sys_clk),??????????????????? .sys_rst_n (sys_rst_n),??????????????????? .fifo_input_data (fifo_input_data[WIDTH-1:0]),??????????????????? .write_fifo (write_fifo),??????????????????? .next_cell_data (data_out_cell1[WIDTH-1:0]),??????????????????? .next_cell_full (full_cell1),??????????????????? .last_cell_full (1'b1),??????????????????? .cell_data_out (fifo_out_data [WIDTH-1:0]),??????????????????? .read_fifo (read_fifo),??????????????????? .cell_full (full_cell0)?????????????????? );
????????????????? fifo_cell #(WIDTH,D) cell1????????????????? ( .sys_clk (sys_clk),??????????????????? .sys_rst_n (sys_rst_n),??????????????????? .fifo_input_data (fifo_input_data[WIDTH-1:0]),??????????????????? .write_fifo (write_fifo),??????????????????? .next_cell_data (data_out_cell2[WIDTH-1:0]),??????????????????? .next_cell_full (full_cell2),??????????????????? .last_cell_full (full_cell0),??????????????????? .cell_data_out (data_out_cell1[WIDTH-1:0]),??????????????????? .read_fifo (read_fifo),??????????????????? .cell_full (full_cell1)?????????????????? );??????????????????????????????????? fifo_cell #(WIDTH,D) cell2????????????????? ( .sys_clk (sys_clk),??????????????????? .sys_rst_n (sys_rst_n),??????????????????? .fifo_input_data (fifo_input_data[WIDTH-1:0]),??????????????????? .write_fifo (write_fifo),??????????????????? .next_cell_data (data_out_cell3[WIDTH-1:0]),??????????????????? .next_cell_full (full_cell3),??????????????????? .last_cell_full (full_cell1),??????????????????? .cell_data_out (data_out_cell2[WIDTH-1:0]),??????????????????? .read_fifo (read_fifo),??????????????????? .cell_full (full_cell2)?????????????????? );??????????????????
????????????????? fifo_cell #(WIDTH,D) cell3????????????????? ( .sys_clk (sys_clk),??????????????????? .sys_rst_n (sys_rst_n),??????????????????? .fifo_input_data (fifo_input_data[WIDTH-1:0]),??????????????????? .write_fifo (write_fifo),??????????????????? .next_cell_data (data_out_cell4[WIDTH-1:0]),??????????????????? .next_cell_full (full_cell4),??????????????????? .last_cell_full (full_cell2),??????????????????? .cell_data_out (data_out_cell3[WIDTH-1:0]),??????????????????? .read_fifo (read_fifo),??????????????????? .cell_full (full_cell3)?????????????????? );??????????????????????? assign data_out_cell4[WIDTH-1:0] = {WIDTH{1'B0}};?????????????????? assign full_cell4 = 1'b0;endmodule??????????????????????????????
..........................................................................................................................
異步FIFO的Verilog代碼 之一
評論
查看更多