FIFO同步、异步以及Verilog代码实现

更新时间:2023-05-18 19:40:06 阅读: 评论:0

FIFO同步、异步以及Verilog代码实现
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 out
assign dataout = mem[rp];
// memory write in
always@(podge clk) begin
if(wr && ~full_in) mem[wp]<=datain;
end
// memory write pointer increment
报告结尾always@(podge clk or negedge rst) begin
if(!rst) wp<=0;
el begin
if(wr && ~full_in) wp<= wp+1'b1;
end
end
// memory read pointer increment
always@(podge clk or negedge rst)begin
if(!rst) rp <= 0;
el begin
if(rd && ~empty_in) rp <= rp + 1'b1;
end
end
// Full signal generate
always@(podge clk or negedge rst) begin
if(!rst) full_in <= 1'b0;
el begin
if( (~rd && wr)&&((wp==rp-1)||(rp==4'h0&&wp==4'hf)))          full_in <= 1'b1;
el if(full_in && rd) full_in <= 1'b0;
end
end
// Empty signal generate
always@(podge clk or negedge rst) begin
if(!rst) empty_in <= 1'b1;
el begin
if((rd&&~wr)&&(rp==wp-1 || (rp==4'hf&&wp==4'h0)))        empty_in<=1'b1;
el if(empty_in && wr) empty_in<=1'b0;
end
end
endmodule ...........................................................................................................................
同步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 @(podge sys_clk or negedge sys_rst_n)
if (!sys_rst_n)
cell_full <= #D 0;
el 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)
cax ({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;
endca
always @(podge sys_clk or negedge sys_rst_n)
if (!sys_rst_n)
cell_data_reg_array [WIDTH-1:0] <= #D 0;
el 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)
cax ({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;
endca
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)
cax ({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];
endca
endmodule
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代码之⼀
这个是基于RAM的异步FIFO代码,个⼈认为代码结构简单易懂,⾮常适合于考试中填写。记得10⽉份参加威盛的笔试的时候,就考过异步FIFO的实现。想当初要是早点复习,可能就可以通过威盛的笔试了。
与之前的⽤RAM实现的同步FIFO的程序相⽐,异步更为复杂。增加了读写控制信号的跨时钟域的同步。此外,判空与判满的也稍有不同。
module fifo1(rdata, wfull, rempty, wdata, winc, wclk, wrst_n,rinc, rclk, rrst_n);
parameter DSIZE = 8; parameter ASIZE = 4;
嘉平公子output [DSIZE-1:0] rdata;
output wfull;
output rempty;
input [DSIZE-1:0] wdata;
input winc, wclk, wrst_n;
input rinc, rclk, rrst_n;
reg wfull,rempty;
reg [ASIZE:0] wptr, rptr, wq2_rptr, rq2_wptr, wq1_rptr,rq1_wptr;
reg [ASIZE:0] rbin, wbin;
reg [DSIZE-1:0] mem[0:(1<<ASIZE)-1];
wire [ASIZE-1:0] waddr, raddr;
wire [ASIZE:0] rgraynext, rbinnext,wgraynext,wbinnext;
wire rempty_val,wfull_val;
//-----------------双⼝RAM存储器--------------------
assign rdata=mem[raddr];
always@(podge wclk)
if (winc && !wfull) mem[waddr] <= wdata;
//-------------同步rptr 指针-------------------------
细胞衰老的特征always @(podge wclk or negedge wrst_n)
if (!wrst_n) {wq2_rptr,wq1_rptr} <= 0;
el {wq2_rptr,wq1_rptr} <= {wq1_rptr,rptr};
//-------------同步wptr指针---------------------------
always @(podge rclk or negedge rrst_n)
if (!rrst_n) {rq2_wptr,rq1_wptr} <= 0;
el {rq2_wptr,rq1_wptr} <= {rq1_wptr,wptr};
演说//-------------rempty产⽣与raddr产⽣-------------------
always @(podge rclk or negedge rrst_n) // GRAYSTYLE2 pointer
begin
if (!rrst_n) {rbin, rptr} <= 0;

本文发布于:2023-05-18 19:40:06,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/913948.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:数据   读写   时钟   代码
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图