FIFO 很重要,之前參加的各類電子公司的邏輯設(shè)計(jì)的筆試幾乎都會(huì)考到。
FIFO是英文First In First Out 的縮寫,是一種先進(jìn)先出的數(shù)據(jù)緩存器,他與普通存儲(chǔ)器的區(qū)別是沒有外部讀寫地址線,這樣使用起來非常簡(jiǎn)單,但缺點(diǎn)就是只能順序?qū)懭霐?shù)據(jù),順序的讀出數(shù)據(jù), 其數(shù)據(jù)地址由內(nèi)部讀寫指針自動(dòng)加1完成,不能像普通存儲(chǔ)器那樣可以由地址線決定讀取或?qū)懭肽硞€(gè)指定的地址。
?FIFO一般用于不同時(shí)鐘域之間的數(shù)據(jù)傳輸,比如FIFO的一端是AD數(shù)據(jù)采集, 另一端是計(jì)算機(jī)的PCI總線,假設(shè)其AD采集的速率為16位 100K SPS,那么每秒的數(shù)據(jù)量為100K×16bit=1.6Mbps,而PCI總線的速度為33MHz,總線寬度32bit,其最大傳輸速率為 1056Mbps,在兩個(gè)不同的時(shí)鐘域間就可以采用FIFO來作為數(shù)據(jù)緩沖。另外對(duì)于不同寬度的數(shù)據(jù)接口也可以用FIFO,例如單片機(jī)位8位數(shù)據(jù)輸出,而 DSP可能是16位數(shù)據(jù)輸入,在單片機(jī)與DSP連接時(shí)就可以使用FIFO來達(dá)到數(shù)據(jù)匹配的目的。
?
FIFO的分類根均FIFO工作的時(shí)鐘域,可以將FIFO分為同步FIFO和異步FIFO。同步FIFO是指讀時(shí)鐘和寫時(shí)鐘為同一個(gè)時(shí)鐘。在時(shí)鐘沿來臨時(shí)同時(shí)發(fā)生讀寫操作。異步FIFO是指讀寫時(shí)鐘不一致,讀寫時(shí)鐘是互相獨(dú)立的。
?
FIFO設(shè)計(jì)的難點(diǎn) FIFO設(shè)計(jì)的難點(diǎn)在于怎樣判斷FIFO的空/滿狀態(tài)。為了保證數(shù)據(jù)正確的寫入或讀出,而不發(fā)生益處或讀空的狀態(tài)出現(xiàn),必須保證FIFO在滿的情況下,不 能進(jìn)行寫操作。在空的狀態(tài)下不能進(jìn)行讀操作。怎樣判斷FIFO的滿/空就成了FIFO設(shè)計(jì)的核心問題。
.........................................................................................................................................
同步FIFO的Verilog代碼 之一
在modlesim中驗(yàn)證過。
/******************************************************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代碼 之二
這一種設(shè)計(jì)的FIFO,是基于觸發(fā)器的。寬度,深度的擴(kuò)展更加方便,結(jié)構(gòu)化跟強(qiáng)。以下代碼在modelsim中驗(yàn)證過。
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代碼 之一
評(píng)論
查看更多