「Verilog学习笔记」异步FIFO

专栏前言

本专栏的内容主要是记录本人学习Verilog过程中的一些知识点,刷题网站用的是牛客网

`timescale 1ns/1ns

/***************************************RAM*****************************************/
module dual_port_RAM #(parameter DEPTH = 16,
					   parameter WIDTH = 8)(
	 input wclk
	,input wenc
	,input [$clog2(DEPTH)-1:0] waddr  //深度对2取对数,得到地址的位宽。
	,input [WIDTH-1:0] wdata      	//数据写入
	,input rclk
	,input renc
	,input [$clog2(DEPTH)-1:0] raddr  //深度对2取对数,得到地址的位宽。
	,output reg [WIDTH-1:0] rdata 		//数据输出
);

reg [WIDTH-1:0] RAM_MEM [0:DEPTH-1];

always @(posedge wclk) begin
	if(wenc)
		RAM_MEM[waddr] <= wdata;
end 

always @(posedge rclk) begin
	if(renc)
		rdata <= RAM_MEM[raddr];
end 

endmodule  

/***************************************AFIFO*****************************************/
module asyn_fifo#(
	parameter	WIDTH = 8,
	parameter 	DEPTH = 16
)(
	input 					wclk	, 
	input 					rclk	,   
	input 					wrstn	,
	input					rrstn	,
	input 					winc	,
	input 			 		rinc	,
	input 		[WIDTH-1:0]	wdata	,

	output wire				wfull	,
	output wire				rempty	,
	output wire [WIDTH-1:0]	rdata
);
	localparam ADDR_WIDTH = $clog2(DEPTH) ;

	reg [ADDR_WIDTH:0] waddr, raddr ;

	always @ (posedge wclk or negedge wrstn) begin 
		if (~wrstn) waddr <= 'b0 ; 
		else 
			if (winc && ~wfull) waddr <= waddr + 1'b1 ; 
			else waddr <= waddr ; 
	end

	always @ (posedge rclk or negedge rrstn) begin 
		if (~rrstn) raddr <= 'b0 ; 
		else 
			if (rinc && ~rempty) raddr <= raddr + 1'b1 ; 
			else raddr <= raddr ; 
	end

	wire [ADDR_WIDTH:0] waddr_gray, raddr_gray ;

	assign waddr_gray = waddr ^ (waddr >> 1) ; 
	assign raddr_gray = raddr ^ (raddr >> 1) ; 

	reg [ADDR_WIDTH:0] waddr_gray_reg, raddr_gray_reg ; 

	always @ (posedge wclk or negedge wrstn) begin 
		if (~wrstn) waddr_gray_reg <= 'd0 ;
		else waddr_gray_reg <= waddr_gray ; 
	end

	always @ (posedge rclk or negedge rrstn) begin 
		if (~rrstn) raddr_gray_reg <= 'd0 ;
		else raddr_gray_reg <= raddr_gray ; 
	end

	reg [ADDR_WIDTH:0] addr_r2w_t, addr_r2w ; 

	always @ (posedge wclk or negedge wrstn) begin 
		if (~wrstn) begin 
			addr_r2w_t <= 'd0 ;
			addr_r2w <= 'd0 ;
		end
		else begin
			addr_r2w_t <= raddr_gray_reg ;
			addr_r2w <= addr_r2w_t ;
		end
	end

	reg [ADDR_WIDTH:0] addr_w2r_t, addr_w2r ; 

	always @ (posedge rclk or negedge rrstn) begin 
		if (~rrstn) begin 
			addr_w2r_t <= 'd0 ;
			addr_w2r <= 'd0 ;
		end
		else begin
			addr_w2r_t <= waddr_gray_reg ;
			addr_w2r <= addr_w2r_t ;
		end
	end

	assign wfull = (waddr_gray_reg == {~addr_r2w[ADDR_WIDTH:ADDR_WIDTH - 1], addr_r2w[ADDR_WIDTH - 2 : 0]}) ;
	assign rempty = (raddr_gray_reg == addr_w2r) ;

	dual_port_RAM # (.DEPTH(DEPTH), .WIDTH(WIDTH)) dual_port_RAM_U0 
	(
        .wclk(wclk),
        .wenc(winc&&~wfull),
        .waddr(waddr[ADDR_WIDTH-1:0]),  //深度对2取对数,得到地址的位宽。
        .wdata(wdata),        //数据写入
        .rclk(rclk),
        .renc(rinc&&~rempty),
        .raddr(raddr[ADDR_WIDTH-1:0]),  //深度对2取对数,得到地址的位宽。
        .rdata(rdata)      //数据输出		
	);
    
endmodule
相关推荐
安冬的码畜日常11 分钟前
【Vim Masterclass 笔记24】S10L43 + L44:同步练习10 —— 基于 Vim 缓冲区的各类基础操作练习(含点评课)
笔记·vim·自学笔记·vim同步练习·vim缓冲区·vim buffer·vim缓冲区练习
lozhyf15 分钟前
Go语言-学习一
开发语言·学习·golang
一只码代码的章鱼20 分钟前
粒子群算法 笔记 数学建模
笔记·算法·数学建模·逻辑回归
圆圆滚滚小企鹅。26 分钟前
刷题笔记 贪心算法-1 贪心算法理论基础
笔记·算法·leetcode·贪心算法
mascon33 分钟前
U3D的.Net学习
学习
加德霍克36 分钟前
【机器学习】使用scikit-learn中的KNN包实现对鸢尾花数据集或者自定义数据集的的预测
人工智能·python·学习·机器学习·作业
漂亮_大男孩36 分钟前
深度学习|表示学习|卷积神经网络|局部链接是什么?|06
深度学习·学习·cnn
杨过姑父42 分钟前
ES6 简单练习笔记--变量申明
前端·笔记·es6
l1x1n01 小时前
No.37 笔记 | Python面向对象编程学习笔记:探索代码世界的奇妙之旅
笔记·python·学习
骇客野人1 小时前
【人工智能】循环神经网络学习
人工智能·rnn·学习