设为首页 加入收藏

TOP

同步FIFO design and IP level verification(一)
2019-09-23 11:16:56 】 浏览:306
Tags:同步 FIFO design and level verification

一、前言

  应聘IC前端相关岗位时,FIFO是最常考也是最基本的题目。FIFO经常用于数据缓存、位宽转换、异步时钟域处理。随着芯片规模的快速增长,灵活的system verilog成为设计/验证人员的基本功。本文从简易版的同步FIFO开始,熟悉IP设计与验证的基础技能。

二、IP设计

  FIFO这一IP核已经相当成熟,因此网上资料也是一抓一大把。其中笔者认为较好的一个在文末附录中,需要详细了解FIFO工作原理的朋友可以仔细看看。这里简单介绍下本文设计FIFO的原理与结构。FIFO的内部存储单元是常见的双口RAM,这个IP的精髓在于读写地址的对外屏蔽与自动管理。避免写满、读空至关重要。本文设计的FIFO顶层例化双口RAM和FIFO控制两大模块:前者仅作为存储单元响应读写信号,后者根据读写计数器产生读写指针和重要的空满指示信号。

  代码如下:

存储模块:

 1 `timescale 1ns/1ps
 2 module dpram
 3 #(parameter D_W=8,
 4             A_W=8)
 5 (
 6   input                   clk,
 7   input                   rst_n,
 8   //write ports
 9   input                   wr_en,
10   input       [D_W-1:0]   wr_data,
11   input       [A_W-1:0]   wr_addr,
12   //read ports
13   input                   rd_en,
14   input       [A_W-1:0]   rd_addr,
15   output reg  [D_W-1:0]   rd_data
16 );
17 //RAM
18 reg [D_W-1:0] memory [0:2**A_W-1];
19 
20 //write operation
21 always@(posedge clk)begin
22   if(wr_en)begin
23     memory[wr_addr] <= wr_data;
24   end
25 end
26 
27 //read operation
28 always@(posedge clk or negedge rst_n)begin
29   if(~rst_n)
30     rd_data <= 0;
31   else if(rd_en)begin
32     rd_data <= memory[rd_addr];
33   end
34   else if(rd_addr == 1)
35     rd_data <= memory[0];
36 end
37 
38 endmodule
dpram

FIFO控制模块:

 1 `timescale 1ns/1ps
 2 module fifo_ctrl
 3 #(parameter A_W = 8,
 4   parameter [0:0] MODE = 0//0- standard read 1- first word fall through
 5 )
 6 (
 7   input clk,
 8   input rst_n,
 9 
10   output [A_W-1:0] wr_addr,
11   output [A_W-1:0] rd_addr,
12 
13   output empty,
14   output full,
15   input wr_en,
16   input rd_en
17 );
18 localparam MAX_CNT = 2**A_W;
19 localparam FD_W = A_W;
20 
21 function [FD_W-1:0] abs;
22   input signed [FD_W-1:0] data;
23   begin
24     assign abs = data >= 0 ? data : -data;
25   end
26 endfunction
27 
28 reg [A_W-1:0] wr_cnt;
29 wire add_wr_cnt,end_wr_cnt;
30 reg wr_flag;
31 reg [A_W-1:0] rd_cnt;
32 wire add_rd_cnt,end_rd_cnt;
33 reg rd_flag;
34 wire [A_W+1-1:0] wr_ptr,rd_ptr;
35 
36 always@(posedge clk or negedge rst_n)begin
37   if(~rst_n)begin
38     wr_cnt <= 0;
39   end
40   else if(add_wr_cnt)begin
41     if(end_wr_cnt)
42       wr_cnt <= 0;
43     else
44       wr_cnt <= wr_cnt + 1'b1;
45   end
46 end
47 
48 assign add_wr_cnt =  wr_en & ~full;
49 assign end_wr_cnt = add_wr_cnt && wr_cnt == MAX_CNT - 1;
50 
51 always@(posedge clk or negedge rst_n)begin
52   if(~rst_n)begin
53     wr_flag <= 0;
54   end
55   else if(end_wr_cnt)begin
56     wr_flag <= ~wr_flag;
57   end
58 end
59 
60 always@(posedge clk or negedge rst_n)begin
61   if(~rst_n)begin
62     rd_cnt <= 0;
63   end
64   else if(add_rd_cnt)begin
65     if(end_rd_cnt)
66       rd_cnt <= 0;
67     else
68       rd_cnt <= rd_cnt + 1'b1;
69   end
70 end
71 
72 assign add_rd_cnt =  rd_en & ~empty;
73 assign end_rd_cnt = add_rd_cnt && rd_cnt ==  MAX_CNT - 1;
74 
75 always@(posedge clk or negedge rst_n)begin
76   if(~rst_n)begin
77     rd_flag <= 0;
78   end
79   else if(end_rd_cnt)begin
80     rd_flag <= ~rd_flag;
81   end
82 end
83 
84 assign wr_ptr = {wr_flag,wr_cnt};
85 assign rd_ptr = {rd_flag,rd_cnt};
86 
87 assign wr_addr = wr_cnt;
88 assign rd_addr = rd_cnt + MODE;
89 
90 assign empty = wr_ptr == rd_ptr;
91 assign full = (abs(wr_ptr[A_W-1:0] - rd_ptr[A_W-1:0]) < 1) && (wr_ptr[A_W] != rd_ptr[A_W]);
92 
93 endmodule
fifo_ctrl

同步FIFO顶层:

 1 `timescale 1ns/1ps
 2 module fifo_sync
 3 #(parameter D_W = 8,
 4             LOG_2_DEPTH = 8,//2^8 = 256
 5   parameter
首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇FPGA 开发详细流程你了解吗? 下一篇【FPGA】Verilog实现交通信号灯

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目