Verilog同步FIFO的电路设计

先入先出(FIFO:First In First Out)存储器是一种常用的数据缓冲器件,它没有外部读写地址线,使用起来非常简单,但缺点是只能顺序写入数据,顺序读出数据,其数据读写顺序由内部读写指针自动控制确定。

外部连接关系
同步FIFO外部连接关系图

电路结构
FIFO内部电路结构图

设计代码

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2020/07/27 09:29:18
// Design Name: 
// Module Name: Test0929
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 



module Test0929(clk,reset,wr_en,din,rd_en,dout,full,empty,afull,aempty,cnt);
input clk;
input reset;
input wr_en;
input rd_en;
input [7:0] din;
output [7:0] dout;
reg [7:0] dout;
output empty,full;
output aempty,afull;
output [4:0] cnt;
reg [4:0] cnt;
reg [7:0] fifo_ram[0:15];
reg [3:0] wr_pointer,rd_pointer;
wire full,empty;
wire afull,aempty;

/*下面的always块用于根据当前指针值执行数据写入操作*/
/*当时钟上升沿出现时,如果wr_en为1,则将数据写入到以wr_pointer为地址的fifo_ram空间中*/
always @(posedge clk)
   begin 
      if(wr_en)
         fifo_ram[wr_pointer]<=din;
   end

/*下面的always块用于根据当前指针值执行数据读出操作*/
/*当时钟上升沿出现时,如果rd_en为1,则将以rd_pointer为地址的fifo_ram的数据读出,并通过dout输出*/
always @(posedge clk)
   begin
      if(rd_en)
         dout<=fifo_ram[rd_pointer];
   end

/*下面的always块用于进行写指针更新*/
/*当时钟上升沿出现时,如果wr_en为1并且fifo_ram没有满,则wr_pointer增加1,wr_pointer的值在0000~1111之间进行循环计数*/
always @(posedge clk)
   begin
      if(reset)
         wr_pointer<=0;
      else
         wr_pointer<=(wr_en&(!full))?wr_pointer+1:wr_pointer;
   end

/*下面的always块用于进行读指针更新*/
/*当时钟上升沿出现时,如果rd_en为1并且fifo_ram非空,则rd_pointer增加1,rd_pointer的值在0000~1111之间进行循环计数*/
always @(posedge clk)
   begin
      if(reset)
         rd_pointer<=0;
      else
         rd_pointer<=(rd_en&(!empty))?rd_pointer+1:rd_pointer;
   end

/*下面的always块用于进行数据深度计数器值更新*/
/*当时钟上升沿出现时,有效的读写操作都会带来cnt数值的增加或减少*/
always @(posedge clk)
   begin
      if(reset)
         cnt<=0;
      else
      
      case({wr_en,rd_en})
         2'b00,2'b11:cnt<=cnt;
         2'b01:cnt<=(cnt==0)?0:cnt-1;
         2'b10:cnt<=(cnt==16)?16:cnt+1;
      endcase
   end

/*下面的语句用于根据fifo中的数据深度产生模块用户所关心的状态信息*/
assign afull=(cnt==15);//深度为15时指示 “将满”
assign aempty=(cnt==1);//深度为1时指示 “将空”
assign empty=(cnt==0);//深度为0时指示 “空”
assign full=(cnt==16);//深度为16时指示 “满”
endmodule

测试代码

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2020/07/27 09:53:14
// Design Name: 
// Module Name: Test0953
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module Test0953;
reg clk,reset,wr_en,rd_en;
reg [7:0] din;
wire [7:0] dout;
wire full,empty,afull,aempty;
wire [4:0] cnt;
reg [7:0] i;
always begin
   #10 clk=1;
   #10 clk=0;
end

initial begin
   clk=0;
   reset=1;
   wr_en=0;
   din=0;
   rd_en=0;
   i=0;
   #100;
   reset=0;
   //for循环控制连续写入16个数据
   for(i=1;i<=16;i=i+1)
      begin
         repeat(1)@(posedge clk)
         #2;
         din=i;
         wr_en=1;
      end
      repeat(1)@(posedge clk)
      #2;
      wr_en=0;
   //for循环控制连续读出16个数据
   for(i=1;i<=16;i=i+1)
      begin
         repeat(1)@(posedge clk)
         #2;
         rd_en=1;
      end
      repeat(1)@(posedge clk)
      #2;
      rd_en=0;
end
Test0929 x1(.clk(clk),
            .reset(reset),
            .wr_en(wr_en),
            .din(din),
            .rd_en(rd_en),
            .dout(dout),
            .full(full),
            .empty(empty),
            .afull(afull),
            .aempty(aempty),
            .cnt(cnt));
endmodule

仿真波形
仿真波形
仿真在vivado上成功运行,具体波形信息可以对照设计代码中的注释信息进行分析。
后面会写一篇由FIFO存储器所构成的接收串/并变换电路。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
同步FIFO是一种常用的电子电路,用于在两个或多个时钟域之间传输数据。它具有先入先出的性质,可以保证数据传输的顺序不变。 Verilog语言中,同步FIFO可以使用一组寄存器实现。下面是一个简单的同步FIFOVerilog代码: ``` module sync_fifo ( input clk_w, // 写时钟 input rst_w, // 写复位 input wr_en, // 写使能 input [7:0] wr_data, // 写数据 input clk_r, // 读时钟 input rst_r, // 读复位 input rd_en, // 读使能 output [7:0] rd_data, // 读数据 output full, // 满标志 output empty // 空标志 ); parameter WIDTH = 8; // 数据宽度 parameter DEPTH = 16; // 深度 reg [WIDTH-1:0] fifo [0:DEPTH-1]; // FIFO存储器 reg [WIDTH-1:0] rd_data_reg; // 读数据寄存器 reg [DEPTH-1:0] wr_ptr; // 写指针 reg [DEPTH-1:0] rd_ptr; // 读指针 wire [DEPTH-1:0] count; // 元素个数 // 写逻辑 always @(posedge clk_w or posedge rst_w) begin if (rst_w) begin wr_ptr <= 0; fifo <= 0; end else if (wr_en && ~full) begin fifo[wr_ptr] <= wr_data; wr_ptr <= wr_ptr + 1; end end // 读逻辑 always @(posedge clk_r or posedge rst_r) begin if (rst_r) begin rd_ptr <= 0; rd_data_reg <= 0; end else if (rd_en && ~empty) begin rd_data_reg <= fifo[rd_ptr]; rd_ptr <= rd_ptr + 1; end end // 元素个数计算 assign count = wr_ptr - rd_ptr; // 满标志 assign full = (count == DEPTH); // 空标志 assign empty = (count == 0); // 读数据输出 assign rd_data = rd_data_reg; endmodule ``` 在这个Verilog代码中,FIFO存储器使用一组寄存器实现,写指针和读指针分别指向下一个写入位置和读取位置。当写使能信号wr_en有效且FIFO未满时,写入数据wr_data,并将写指针加1;当读使能信号rd_en有效且FIFO非空时,读取数据并将读指针加1。元素个数count可以通过写指针和读指针的差值计算得到,满标志full和空标志empty分别表示FIFO是否已满和是否为空。最后,读数据rd_data通过一个寄存器输出,以保证读数据的正确性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值