关于fifo和ram时序验证

一、前言

本文是基于altera系列fifo和ramFPGA学习笔记之IP核调用的补充,
(第二篇可以参照:Quartus基本IP核调用及仿真)
本次使用的FPGA型号是: 10CLO16YU484C8G
25M时钟:GCLK引脚G2,,

二、RAM时序验证

(一)代码

1.测试

module test_ram(
   input              clk,//25M时钟    
	input 	          rst_n
);

	parameter CNT_256 = 256 ;
	parameter CNT_32  = 32 ;

	reg	[7:0]     data;
	wire	[4:0]     rdaddress;
	wire	[4:0]     wraddress;
	wire  [7:0]     ram_q;
	reg	          rden;
	reg	          wren;
	
	


   reg     [8:0]    cnt_256         ;
   wire             add_cnt_256     ;
   wire             end_cnt_256     ;
   reg     [4:0]    cnt_32          ;
   wire             add_cnt_32      ;
   wire             end_cnt_32      ;
   reg     [4:0]    cnt_32_r        ;
   wire             add_cnt_32_r    ;
   wire             end_cnt_32_r    ;

pll	pll_inst (
	.areset ( ~rst_n ),
	.inclk0 ( clk    ),
	.c0     ( c0     ),
	.locked ( locked )
	);
//assign c0 = clk;

//
RAM_2_PORT	RAM_2_PORT_inst (
	.data      ( data      ),
	.rd_aclr   (~rst_n     ),
	.rdaddress ( rdaddress ),
	.rdclock   ( clk       ),
	.rden      ( rden      ),
	.wraddress ( wraddress ),
	.wrclock	  ( c0        ),
	.wren	     ( wren      ),
	.q 		  ( ram_q     )
);



//计数器cnt_256
always@(negedge clk or negedge rst_n)begin
   if(!rst_n)begin
      cnt_256 <= 0;
   end
   else if(add_cnt_256) begin
      if(end_cnt_256)begin
         cnt_256 <= 0;
      end
      else begin
         cnt_256 <= cnt_256 + 1;
      end
   end
end
assign add_cnt_256 =  1'b1;//开启条件
assign end_cnt_256 = add_cnt_256 && cnt_256 == CNT_256 - 1;//结束条件


//计数器
always@(negedge clk or negedge rst_n)begin
   if(!rst_n)begin
      cnt_32 <= 0;
   end
   else if(add_cnt_32) begin
      if(end_cnt_32)begin
         cnt_32 <= 0;
      end
      else begin
         cnt_32 <= cnt_32 + 1;
      end
   end
end
assign add_cnt_32 = rden ;//开启条件
assign end_cnt_32 = add_cnt_32 && cnt_32 == CNT_32 - 1;//结束条件


always@(negedge c0 or negedge rst_n)begin
   if(!rst_n)begin
      cnt_32_r <= 0;
   end
   else if(add_cnt_32_r) begin
      if(end_cnt_32_r)begin
         cnt_32_r <= 0;
      end
      else begin
         cnt_32_r <= cnt_32_r + 1;
      end
   end
end
assign add_cnt_32_r = wren ;//开启条件
assign end_cnt_32_r = add_cnt_32_r && cnt_32_r == CNT_32 - 1;//结束条件

always@(negedge c0 or negedge rst_n)begin
   if(!rst_n)begin
      data <= 0;
   end
   else begin
      data <= cnt_256;
   end
end

assign rdaddress = (rden==1)? cnt_32 :0;
assign wraddress = (wren==1)? cnt_32_r :0;

always@(negedge clk or negedge rst_n)begin
   if(!rst_n)begin
      wren <= 0;
   end
   else if(cnt_256 == 6)begin
      wren <= 1'b1;
   end
   else if (end_cnt_32_r)begin
      wren <= 1'b0;
   end
end

always@(negedge clk or negedge rst_n)begin
   if(!rst_n)begin
       rden <= 0;
   end
   else if(cnt_256  == 200)begin
       rden <= 1'b1;
   end
   else if(end_cnt_32)begin
       rden <= 1'b0;
   end
end
endmodule

2.仿真测试


`timescale 1ns/1ps

module tb ();

    reg        clk     ;
    reg        rst_n   ;

	 always #20   clk = ~clk;
    integer i = 0 , j =0 ;//用于产生地址,写入数据
    initial begin
	 
        clk = 1'b1;
        rst_n   = 1'b1;
        #200.1;
        rst_n     = 1'b0;
        #200;
        rst_n     = 1'b1;
        #20000;
        $stop;
    end
    	 
	 test_ram  ram_tb(
		.clk        (clk   )   ,//25M时钟    
		.rst_n      (rst_n )
	 );
    endmodule

3.SignalTap

module test_ram(
   input              clk,//25M时钟    
//	input 	[7:0]     data,
//	input 	[4:0]     rdaddress,
//	input 	 	       rdclock,
//	input 	          rden,
//	input 	[4:0]     wraddress,
//	input 	          wrclock.
//	input 	          wren,
	output	[7:0]     q,
   output             rst_n
);

	parameter CNT_256 = 256 ;
	parameter CNT_32  = 32 ;

	reg	[7:0]     data;
	wire	[4:0]     rdaddress;
	wire	[4:0]     wraddress;
	wire  [7:0]     ram_q;
	reg	          rden;
	reg	          wren;
	
	


   reg     [8:0]    cnt_256         ;
   wire             add_cnt_256     ;
   wire             end_cnt_256     ;
   reg     [4:0]    cnt_32          ;
   wire             add_cnt_32      ;
   wire             end_cnt_32      ;
   reg     [4:0]    cnt_32_r        ;
   wire             add_cnt_32_r    ;
   wire             end_cnt_32_r    ;


pll	pll_inst (
	.inclk0 ( clk    ),
	.c0     ( c0     ),
   .c1     ( c1     ),
   .locked ( rst_n  )
	);

//
RAM_2_PORT	RAM_2_PORT_inst (
	.data      ( data      ),
	.rd_aclr   (~rst_n     ),
	.rdaddress ( rdaddress ),
	.rdclock   ( clk       ),
	.rden      ( rden      ),
	.wraddress ( wraddress ),
	.wrclock	  ( c0        ),
	.wren	     ( wren      ),
	.q 		  ( ram_q     )
);



//计数器cnt_256
always@(negedge clk or negedge rst_n)begin
   if(!rst_n)begin
      cnt_256 <= 0;
   end
   else if(add_cnt_256) begin
      if(end_cnt_256)begin
         cnt_256 <= 0;
      end
      else begin
         cnt_256 <= cnt_256 + 1;
      end
   end
end
assign add_cnt_256 =  1'b1;//开启条件
assign end_cnt_256 = add_cnt_256 && cnt_256 == CNT_256 - 1;//结束条件


//计数器
always@(negedge clk or negedge rst_n)begin
   if(!rst_n)begin
      cnt_32 <= 0;
   end
   else if(add_cnt_32) begin
      if(end_cnt_32)begin
         cnt_32 <= 0;
      end
      else begin
         cnt_32 <= cnt_32 + 1;
      end
   end
end
assign add_cnt_32 = rden ;//开启条件
assign end_cnt_32 = add_cnt_32 && cnt_32 == CNT_32 - 1;//结束条件


always@(negedge c0 or negedge rst_n)begin
   if(!rst_n)begin
      cnt_32_r <= 0;
   end
   else if(add_cnt_32_r) begin
      if(end_cnt_32_r)begin
         cnt_32_r <= 0;
      end
      else begin
         cnt_32_r <= cnt_32_r + 1;
      end
   end
end
assign add_cnt_32_r = wren ;//开启条件
assign end_cnt_32_r = add_cnt_32_r && cnt_32_r == CNT_32 - 1;//结束条件

always@(negedge c0 or negedge rst_n)begin
   if(!rst_n)begin
      data <= 0;
   end
   else begin
      data <= (cnt_256>>1) + 2;
   end
end

assign rdaddress = cnt_32;
assign wraddress = cnt_32_r;

always@(negedge c0 or negedge rst_n)begin
   if(!rst_n)begin
      wren <= 0;
   end
   else if(cnt_256 <= 6)begin
      wren <= 1'b1;
   end
   else if (end_cnt_32_r)begin
      wren <= 1'b0;
   end
end

always@(negedge clk or negedge rst_n)begin
   if(!rst_n)begin
       rden <= 0;
   end
   else if(cnt_256  == 200)begin
       rden <= 1'b1;
   end
   else if(end_cnt_32)begin
       rden <= 1'b0;
   end
end
endmodule

(二)寄存输出q

1.配置IP

在这里插入图片描述

2.仿真波形

(1)写数据
在这里插入图片描述
由波形图可以看出,写时钟(wrclk)上升沿寄存值,下降沿改变写地址(wradress)和数据(data)的值。
地址1放的值为7,地址2值为9,以此类推。


(2)读数据
在这里插入图片描述
可以看出由于寄存了输出q的值,故输出延迟了一个读时钟(rdclk)周期。


3.下板验证

(1)写入数据

地址存放数据
02
13
3133

在这里插入图片描述
(2)读取数据
在这里插入图片描述
可以看出由于寄存了q的值,相比于未寄存q的输出晚了一个rdclock

(三)无寄存输出q

1.配置IP

在这里插入图片描述

2.仿真波形

(1)写数据同上
在这里插入图片描述
地址1放的值为7,地址2值为9,以此类推。


(2)读数据
在这里插入图片描述
可以看出没有寄存输出q的值,直接输出,无延时。地址1输出的值q为7,地址2输出的值q为9,以此类推


3.下板验证

(1)写入数据

地址存放数据
02
13
3133

在这里插入图片描述

(2)读取数据
在这里插入图片描述

三、FIFO验证

(一)代码

1.测试

module test_fifo(
   input              clk,//25M时钟    
	input 	          rst_n

);



	parameter CNT_512 = 512 ;
	parameter CNT_128  = 128 ;

	reg	   [7:0]  data ;
	reg      	    rdreq;
	reg      	    wrreq;
	wire 	   [7:0]  q    ;
	wire   	       rdempty;
	wire   	       rdfull ;
	wire   	[6:0]  rdusedw;
	wire   	       wrempty;
	wire   	       wrfull ;
	wire   	[6:0]  wrusedw;
	


   reg     [9:0]    cnt_512         ;
   wire             add_cnt_512     ;
   wire             end_cnt_512     ;

   reg     [6:0]    cnt_128          ;
   wire             add_cnt_128      ;
   wire             end_cnt_128      ;


pll	pll_inst (
	.areset ( ~rst_n ),
	.inclk0 ( clk    ),
	.c0     ( c0     ),
	.locked ( locked )
	);
//assign c0 = clk;

//
FIFO	FIFO_inst (
	.aclr     ( ~rst_n  ),
	.data     ( data    ),
	.rdclk    ( clk     ),
	.rdreq    ( rdreq   ),
	.wrclk    ( c0      ),
	.wrreq    ( wrreq   ),
	.q        ( q       ),
	.rdempty  ( rdempty ),
	.rdfull   ( rdfull  ),
	.rdusedw  ( rdusedw ),
	.wrempty  ( wrempty ),
	.wrfull   ( wrfull  ),
	.wrusedw  ( wrusedw )
	);




//计数器cnt_512
always@(negedge c0 or negedge rst_n)begin
   if(!rst_n)begin
      cnt_512 <= 0;
   end
   else if(add_cnt_512) begin
      if(end_cnt_512)begin
         cnt_512 <= 0;
      end
      else begin
         cnt_512 <= cnt_512 + 1;
      end
   end
end
assign add_cnt_512 =  1'b1;//开启条件
assign end_cnt_512 = add_cnt_512 && cnt_512 == CNT_512 - 1;//结束条件


always@(negedge c0 or negedge rst_n)begin
   if(!rst_n)begin
      data <= 0;
   end
   else begin
      data <= cnt_512;
   end
end


always@(negedge c0 or negedge rst_n )begin
   if(!rst_n)begin
     wrreq <= 0;
   end
   else if(cnt_512 == 2)begin
     wrreq <= 1'b1;
   end
   else if (cnt_512 == 300)begin
     wrreq <= 1'b0;
   end
end

always@(negedge clk or negedge rst_n)begin
   if(!rst_n)begin
       rdreq <= 0;
   end
   else if(cnt_512  == 350)begin
       rdreq <= 1'b1;
   end
   else if(end_cnt_128)begin
       rdreq <= 1'b0;
   end
end




//计数器
always@(negedge clk or negedge rst_n)begin
   if(!rst_n)begin
      cnt_128 <= 0;
   end
   else if(add_cnt_128) begin
      if(end_cnt_128)begin
         cnt_128 <= 0;
      end
      else begin
         cnt_128 <= cnt_128 + 1;
      end
   end
end
assign add_cnt_128 = rdreq ;//开启条件
assign end_cnt_128 = add_cnt_128 && cnt_128 == CNT_128 - 1;//结束条件


endmodule



2.仿真


`timescale 1ns/1ps

module tb ();

    reg        clk     ;
    reg        rst_n   ;

	 always #20   clk = ~clk;
    integer i = 0 , j =0 ;//用于产生地址,写入数据
    initial begin
	 
        clk = 1'b1;
        rst_n   = 1'b1;
        #200.1;
        rst_n     = 1'b0;
        #200;
        rst_n     = 1'b1;
        #50000;
        $stop;
    end
 
	test_fifo  fifo_tb(
		.clk        (clk   )   ,//25M时钟    
		.rst_n      (rst_n )
	);
    endmodule

3.Signal Tap

module test_fifo(
   input              clk,//25M时钟    
	// input 	          rst_n,
	// input 	   [7:0]  data   ,
	// input       	    rdreq  ,
	// input       	    wrreq  ,
   output  	   [7:0]  q      ,
	output    	       rdempty,
	output    	       rdfull ,
	output    	[6:0]  rdusedw,
	output    	       wrempty,
	output    	       wrfull ,
	output    	[6:0]  wrusedw,
   output             rst_n

);



	parameter CNT_512 = 512 ;
	parameter CNT_128  = 128 ;

 

	reg	   [7:0]  data ;
	reg      	    rdreq;
	reg      	    wrreq;
   wire            c1   ;
   wire            c0   ;
   // reg             c0;
	// wire 	   [7:0]  q    ;
	// wire   	       rdempty;
	// wire   	       rdfull ;
	// wire   	[6:0]  rdusedw;
	// wire   	       wrempty;
	// wire   	       wrfull ;
	// wire   	[6:0]  wrusedw;
	


   reg     [9:0]    cnt_512         ;
   wire             add_cnt_512     ;
   wire             end_cnt_512     ;

   reg     [6:0]    cnt_128          ;
   wire             add_cnt_128      ;
   wire             end_cnt_128      ;


pll	pll_inst (
	.inclk0 ( clk    ),
	.c0     ( c0     ),
   .c1     ( c1     ),
   .locked ( rst_n  )
	);
//assign c0 = clk;

//
FIFO	FIFO_inst (
	.aclr     ( ~rst_n  ),
	.data     ( data    ),
	.rdclk    ( c1      ),
	.rdreq    ( rdreq   ),
	.wrclk    ( c0      ),
	.wrreq    ( wrreq   ),
	.q        ( q       ),
	.rdempty  ( rdempty ),
	.rdfull   ( rdfull  ),
	.rdusedw  ( rdusedw ),
	.wrempty  ( wrempty ),
	.wrfull   ( wrfull  ),
	.wrusedw  ( wrusedw )
	);



//计数器cnt_512
always@(negedge c1 or negedge rst_n)begin
   if(!rst_n)begin
      cnt_512 <= 0;
   end
   else if(add_cnt_512) begin
      if(end_cnt_512)begin
         cnt_512 <= 0;
      end
      else begin
         cnt_512 <= cnt_512 + 1;
      end
   end
end
assign add_cnt_512 =  1'b1;//开启条件
assign end_cnt_512 = add_cnt_512 && cnt_512 == CNT_512 - 1;//结束条件


always@(negedge c0 )begin
      data <= cnt_512>>1;
end


always@(negedge c0 or negedge rst_n )begin
   if(!rst_n)begin
     wrreq <= 0;
   end
   else if(cnt_512 <= 2)begin
     wrreq <= 1'b1;
   end
   else if (cnt_512>= 300)begin
     wrreq <= 1'b0;
   end
end

always@(negedge c1 or negedge rst_n)begin
   if(!rst_n)begin
       rdreq <= 0;
   end
   else if(cnt_512  == 350)begin
       rdreq <= 1'b1;
   end
   else if(end_cnt_128)begin
       rdreq <= 1'b0;
   end
end




//计数器
always@(negedge c1 or negedge rst_n)begin
   if(!rst_n)begin
      cnt_128 <= 0;
   end
   else if(add_cnt_128) begin
      if(end_cnt_128)begin
         cnt_128 <= 0;
      end
      else begin
         cnt_128 <= cnt_128 + 1;
      end
   end
end
assign add_cnt_128 = rdreq ;//开启条件
assign end_cnt_128 = add_cnt_128 && cnt_128 == CNT_128 - 1;//结束条件


endmodule

(二)前显模式

1.配置ip

在这里插入图片描述

2.波形图

(1)写入数据
在这里插入图片描述
wrreq写请求信号拉高,写时钟(wrclk)上升沿数据写入,下降沿数据改变.开始写入第一个数据,fifo不为空,wrempty由高拉低。
延迟一个时钟周期(wrclk)可以看到写入第一个数据(data=8’d2)完成,此时(wrusedw=wrusedw+1=1)。


在这里插入图片描述

数据写满后,wrfull拉高,最后一个数据(data=8’d129)


(2)读数据
在这里插入图片描述开始读完第一个数据后,rdempty由高拉低,rdusedw相较于wrreq延迟(2·wrclk+1·rdclk)个周期。相较于wrusedw延时(1·wrclk+1·rdclk)个周期.
读取的第一个数据(q=8‘d2).可以看出数据有效在wrreq有效之前读出,当wrreq有效后读出第二个数据data=8’d3.


在这里插入图片描述

读完第一个数据的同时rdfull拉低


在这里插入图片描述

读完最后一个数据(q=8’d129),rdempty拉高,数据全部读出

3.下板验证

为了方便观察,data +2,第一个数据为2

在这里插入图片描述
在这里插入图片描述
可以看出在rdreq有效之前已经输出了第一个数据,在wrreq有效·之后已经是从第二个数据开始输出的。


(三)正常模式

1.配置ip

在这里插入图片描述

2.波形图

在这里插入图片描述

可以看出在rdreq有效后读出数据,读出第一个数据(data=8’d2)

3.下板验证

(1)存入第一个数据
在这里插入图片描述
(2)存入最后一个数据
在这里插入图片描述
(3)读取第一个数据、
在这里插入图片描述

(4)读取最后一个数据
在这里插入图片描述

参考资料

FPGA如果没有外部复位信号,如何产生复位信号,初始化所有寄存器

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值