【【萌新的FPGA学习之同步FIFO的代码与tb】】

萌新的FPGA学习之同步FIFO的代码与tb

对于FIFO的介绍在上一节
在这里主要介绍要用如何的判断方法使得FIFO 确定空满
空满信号产生
为产生 FIFO 空满标志,引入 cnt 计数器,cnt 计数器用于指示 FIFO 内部存储数据
个数。
(1)当只有写操作时,cnt 加 1;只有读操作是,cnt 减 1;其他情况下,cnt 保持;
(2)当 cnt 为 0 时,说明 FIFO 为空,empty 置位;
(3)当 cnt 等于 FIFO 深度时,说明 FIFO 已满,full 置位

下面附上同步 FIFO的代码

//synchronous  fifo
module FIFO_syn #(
    parameter 		WIDTH		=	16,                    //  the fifo wide
    parameter 		DEPTH		=	1024,                  //  deepth
    parameter 		ADDR_WIDTH	=	clogb2(DEPTH),         //  bit wide
    parameter 		PROG_EMPTY	=	100,                   //  this what we set to empty
    parameter 		PROG_FULL	=	800                     //  this what we set to full
  )
  (
    input   sys_clk                    ,
    input   sys_rst                    ,
    input   wr_en                      ,
    input   rd_en                      ,
    input   [WIDTH-1: 0] din           ,
    output  reg  full                  ,
    output  reg  empty                 ,         ///  1 is  real empty  0 is no empty
    output  reg  prog_full             ,
    output  reg  prog_empty            ,
    output  reg  [WIDTH-1:0]  dout     
  );

  //========================================================================================//
  //                              define parameter and internal signals                     //
  //======================================================================================//
  reg [WIDTH-1 : 0]          ram[DEPTH-1 : 0]   ;     // this we set a  15:0   total 1024 number ram
  reg [ADDR_WIDTH-1 : 0]     wr_addr            ;     // this is  write pointer
  reg [ADDR_WIDTH-1 : 0]     rd_addr            ;     // this is  read  pointer
  reg  [ADDR_WIDTH-1 : 0]     fifo_cnt          ;

  //=========================================================================================//
  //                             next  is  main code                                           //
  //=========================================================================================//

  //  we  set a function  let me to  count    the number
  function integer clogb2;                     //  remember integer has  symbol  reg  has no symbol
    input[31:0]value;
    begin
      value=value-1;
      for(clogb2=0;value>0;clogb2=clogb2+1)
        value=value>>1;
    end
  endfunction
  //   this  you can see from the  PPT 5-74


  //===================================================  next  is used to read

  always@(posedge sys_clk or posedge sys_rst)
  begin
    if(sys_rst)
      rd_addr		<=		{ADDR_WIDTH{1'b0}};
    else if(rd_en && !empty)
    begin
      rd_addr		<=		rd_addr+1'd1;
      dout		<=		ram[rd_addr];
    end
    else
    begin
      rd_addr		<=		rd_addr;
      dout		<=		dout;
    end
  end




  //===================================================  next  is used to write
  always@(posedge sys_clk  or posedge sys_rst)
  begin
    if(sys_rst == 1)
    begin
      wr_addr         <=    {ADDR_WIDTH{1'b0}}   ;         //  this  let pointer to zero
    end
    else if( wr_en  &&  !full )
    begin   // no full and  wr_en   and  whether to write prog_full there
      wr_addr          <=    wr_addr + 1'b1  ;
      ram[wr_addr]     <=    din             ;
    end
    else
      wr_addr          <=    wr_addr         ;
  end





  //==============================================================  next  is  used to set fifo_cnt
  always@(posedge sys_clk  or posedge sys_rst )
  begin
    if(sys_rst)
    begin
      fifo_cnt  <=  {ADDR_WIDTH{1'b0}};
    end
    else if(wr_en &&  !full  &&  !rd_en)
    begin
      fifo_cnt  <=   fifo_cnt + 1'b1 ;
    end
    else if(rd_en && !empty && !wr_en)
    begin
      fifo_cnt  <=  fifo_cnt - 1'b1 ;
    end
    else
      fifo_cnt  <=  fifo_cnt ;
  end


  //==========================================================     next is empty
  //  we set  counter  so  when the count is zero  empty
  always@(posedge sys_clk  or  posedge sys_rst)
  begin
    if(sys_rst == 1)
    begin
      empty <= 1'b1 ;      //  begin  we set empty to high
    end
    // there is  two possibilties first no write fifo_cnt is all zero
    //second is no write it will be change to zero  is just a will empty signal
    else
      empty <=  (!wr_en && (fifo_cnt[ADDR_WIDTH-1:1] == 'b0))&&((fifo_cnt[0] == 1'b0) || rd_en);
  end



  //============================================================  next is full

  always@(posedge sys_clk or posedge sys_rst)
  begin
    if(sys_rst)
      full	<=	1'b1;//reset:1
    else
      full	<=	(!rd_en	&&	(fifo_cnt[ADDR_WIDTH-1:1]=={(ADDR_WIDTH-1){1'b1}})) && ((fifo_cnt[0] == 1'b1) || wr_en);
  end




  //============================================================   next is prog_full

  //prog_full
  always@(posedge sys_clk or posedge sys_rst)
  begin
    if(sys_rst)
      prog_full<=	1'b1;//reset:1
    else if(fifo_cnt > PROG_FULL)
      prog_full<=	1'b1;
    else
      prog_full<=	1'b0;
  end

  //prog_empty
  always@(posedge sys_clk or posedge sys_rst)
  begin
    if(sys_rst)
      prog_empty<=1'b1;//reset:1
    else if(fifo_cnt < PROG_EMPTY)
      prog_empty<=1'b1;
    else
      prog_empty<=1'b0;
  end
endmodule

tb


```dart
`timescale 1ns/1ns
module tb;
parameter 			WIDTH		=	16		;
parameter 			DEPTH		=	512    	;
parameter 			ADDR_WIDTH	=	9       ;
parameter 			PROG_EMPTY	=	100     ;
parameter 			PROG_FULL	=	400     ;
reg 				sys_clk		;
reg 				sys_rst		;
reg  [WIDTH-1:0]	din    		;
reg 				wr_en  		;
reg 				rd_en  		;
reg	 [11:0]			cnt			;	
wire [WIDTH-1:0]	dout		;
wire 				full        ;
wire 				empty       ;
wire 				prog_full   ;
wire 				prog_empty  ;

 
initial	begin
	sys_clk		=	0;
	sys_rst		=	1;
	#100
	sys_rst		=	0;
end
always #5	sys_clk	=	~sys_clk;
 
always @ (posedge sys_clk or posedge sys_rst)begin
	if(sys_rst)
		cnt			<=		'b0;
	else
		cnt			<=		cnt + 1'd1;
end


always @ (posedge sys_clk or posedge sys_rst)begin
	if(sys_rst)begin
		wr_en		<=		1'b0;
		rd_en		<=		1'b0;
		din			<=		16'b0;
		end
	else if(cnt >= 'd10 && cnt <= DEPTH + 'd40)begin
		wr_en		<=		1'b1;
		rd_en		<=		1'b0;
		din			<=		din + 1'd1;
		end
	else if((cnt >= 'd100 + DEPTH) && (cnt <= 2*DEPTH + 'd140))begin
		wr_en		<=		1'b0;
		rd_en		<=		1'b1;
		din			<=		'b0;
		end
	else begin
		wr_en		<=		1'b0;
		rd_en		<=		1'b0;
		din			<=		'b0;
		end
end

FIFO_syn#(
    .WIDTH       ( WIDTH       ),
    .DEPTH       ( DEPTH       ),
    .ADDR_WIDTH  ( ADDR_WIDTH  ),
    .PROG_EMPTY  ( PROG_EMPTY  ),
    .PROG_FULL   ( PROG_FULL   )
)u_FIFO_syn(
    .sys_clk     ( sys_clk     ),
    .sys_rst     ( sys_rst     ),
    .wr_en       ( wr_en       ),
    .rd_en       ( rd_en       ),
    .din         ( din         ),
    .full        ( full        ),
    .empty       ( empty       ),
    .prog_full   ( prog_full   ),
    .prog_empty  ( prog_empty  ),
    .dout        ( dout        )

);


endmodule





你可能感兴趣的:(FPGA学习,fpga开发,学习)