异步FIFO(二)——手撕代码

承接上一篇,FIFO的基础理论,理论基础参考《VerilogHDL高级数字设计》,Clifford的论文Simulation and Synthesis Techniques for Asynchronous FIFO Design以及张波的硕士论文:基于SOC异步FIFO的设计与形式验证。
代码为自己独立完成。
顶层代码:

module (
	clk_w,rst_w,b_w,full_w,
	clk_r,rst_r,b_r,empty_r,
	data_in,data_out,rst_n
	);
parameter WIDTH_A=8;	
parameter WIDTH_D=16;
parameter DEPTH=256;


input clk_w,rst_w,b_w;
input clk_r,rst_r,b_r;
input [WIDTH_D-1:0] data_in;
input rst_n;
output empty_r;
output full_w;
output [WIDTH_D-1:0]data_out;

//write wire
wire [WIDTH_A:0] addr_w,addr_w_g;
wire [WIDTH_A:0] syn_data_w,addr_w_syn;

//read
wire [WIDTH_A:0] addr_r,addr_r_g,syn_data_r,addr_r_syn;

//RAM
wire en_r,en_w;

write_controll #(
	.WIDTH_A(WIDTH_A)
)write_control(	.clk_w(clk_w),
	.rst_w(rst_w),
	.b_w(b_w),
	.addr_r_syn(addr_r_syn),
	.addr_w(addr_w),
	.full_w(full_w));
	
b2g #(
	.WIDTH_A(WIDTH_A)
)bin_gray_w(.bin(addr_w),
	.gray(addr_w_g));
	
generate
genvar i;
for (i=0;i<=WIDTH_A;i=i+1) begin:
	fast_syn_slow write_syn_read(
		.vcc(1'b1),
		.data_in(addr_w_g[i]),
		.clk_s(clk_r),
		.rst_s(rst_r),
		.syn_data(syn_data_w[i]));
end
endgenerate

g2b #(
	.WIDTH_A(WIDTH_A)
)gray_bin(
	.bin(addr_w_syn)
	.gray(syn_data_w)
	);


	
read_controll #(
	.WIDTH_A(WIDTH_A)
)read_control(.clk_r(clk_r),
	.rst_r(rst_r),
	.addr_w_syn(addr_w_syn),
	.b_r(b_r),
	.empty_r(empty_r),
	.addr_r(addr_r));

b2g #(
	.WIDTH_A(WIDTH_A)
)bin_gray_r(	.bin(addr_r),
	.gray(addr_r_g));

slow_syn_fast #(
	.WIDTH_A(WIDTH_A)
)read_syn_write(
	.clk_f(clk_w),
	.rst_f(rst_w),
	.data_in(addr_r_g),
	.syn_data(syn_data_r));

g2b #(
	.WIDTH_A(WIDTH_A)
)gray_bin(
	.bin(addr_r_syn)
	.gray(syn_data_r)
	);
	
	
assign en_r=(!empty_r)&b_r;
assign en_w=(!full_w)&b_w;

RAM #(
	.DEPTH(DEPTH),
	.WIDTH_A(WIDTH_A),
	.WIDTH_D(WIDTH_D)
)data_path(
	.clk_r(clk_r),.en_r(en_r),.addr_r(addr_r),
	.clk_w(clk_w),.en_w(en_w),.addr_w(addr_w),
	.data_in(data_in),.data_out(data_out),
	.rst_n(rst_n));
endmodule 


写控制模块

module write_controll(
	clk_w,
	rst_w,
	b_w,//begin write to stack
	
	addr_r_syn,//read address
	full_w,
	addr_w
	);
	parameter WIDTH_A=8;
	
	input clk_w,rst_w,b_w;
	input [WIDTH_A:0]addr_r_syn;
	
	output [WIDTH_A:0]addr_w;
	output full_w;
	
	always@(posedge clk_w)
		if (!rst_w)
			addr_w<='h00;
		else if (b_w&&(!w_full))
			addr_w<=addr_w+1'b1;
			
	assign w_full=({~addr_w[WIDTH_A],addr_w[WIDTH_A-1:0]}==addr_r_syn)?1'b1:1'b0;
endmodule 

读控制模块

module read_controll(
	clk_r,
	rst_r,
	b_r,//begin read from stack
	
	addr_w_syn,//write address
	empty_r,
	addr_r);
	parameter WIDTH_A=8;
	
	output empty_r ;
	output [WIDTH_A:0] addr_r;
	
	input clk_r,rst_r,b_r;
	input [WIDTH_A:0]addr_w;
	
	reg [WIDTH_A:0] addr_r;
	
	always@(posedge clk_r)
		if (! rst_r)
			addr_r<='h00;
		else if 
			addr_r<=addr_r+1'b1;
			
	assign empty_r=(addr_r==addr_w_syn)?1'b1:1'b0;
endmodule 

二进制码转格雷码

module b2g (bin,gray);

	parameter WIDTH_A=8
	
	output [WIDTH_A:0] gray;
	input [WIDTH_A:0] bin;
	
	wire h_b;   //high
	reg [WIDTH_A-1:0]gray_l; 
	assign h_b=bin[WIDTH_A];
	
	
	integer i;
	always@(*)
		for (i=0;i<WIDTH_A;i=i+1) begin
			gray_l[i] = bin[i]^bin[i+1];
		end
		
	assign gray={h_b,gray_l};
endmodule 

格雷码转二进制码

module g2b(
	bin,
	gray
	);
	
	parameter WIDTH_A=8;
	
	input [WIDTH_A:0] gray;
	output [WIDTH_A:0] bin;
	
	reg bin_reg;
	
	integer i;
	always @(*)
	begin
		bin_reg=gray;
		for (i=WIDTH_A-1;i>0;i=i-1) begin
			bin_reg[i]=bin_reg[i+1]^gray[i];
		end
	end
	assign bin=bin_reg;
endmodule 

同步器 慢时钟域到快时钟域

module slow_syn_fast( 
	clk_f,
	rst_f,
	data_in,
	syn_data
	);
	
	parameter WIDTH_A=8;
	
	input	clk_f,rst_f;
	input	[WIDTH_A:0]data_in;
	output	[WIDTH_A:0]data_out;
	
	reg [WIDTH_A:0] syn_reg_1,syn_reg_2;
	
	always@(posedge clk_f)
		if (!rst_f) begin
			syn_reg_1<='h00;
			syn_reg_2<='h00;
		end
		else begin
			syn_reg_1<=data_in;
			syn_reg_2<=syn_reg_1;
		end
	
	assign syn_data=syn_reg_2;
endmodule 

同步器 快时钟域到慢时钟域

module slow_syn_fast(
	vcc,
	data_in,
	clk_s,
	rst_s,
	syn_data);
	
	input vcc,clk_s,rst_s;
	input data_in;
	
	output syn_data;
	
	reg  syn_reg_1,syn_reg_2,syn_reg_3;
	
	wire rst_1,rst_2,rst_3;
	
	assign rst_1=((~data_in)&syn_reg_3)|rst_s;
	assign rst_2=((~data_in)&syn_reg_3)|rst_s;
	assign rst_3=rst_s;
	
	always@(posedge data_in)
		if (!rst_1)
			syn_reg_1<=1'b0;
		else 
			syn_reg_1<=vcc;
			
	always@(posedge clk_s)
		if (!rst_2)
			syn_reg_2<=1'b0;
		else
			syn_reg_2<=syn_reg_1;
			
	always@(posedge	clk_s)
		if (!rst_3)
			syn_reg_3<=1'b0;
		else
			syn_reg_3<=syn_reg_2;
			
	assign syn_data=syn_reg_3;
endmodule 

RAM

module RAM (
	clk_r,en_r,addr_r,
	clk_w,en_w,addr_w,
	data_in,data_out,
	rst_n);
	
	parameter DEPTH = 256;
	parameter WIDTH_A = 8;
	parameter WIDTH_D = 16;
	
	input clk_r,rst_r,en_r;
	input clk_w,rst_w,en_w;
	
	input [WIDTH_A:0]addr_r,addr_w;
	input [WIDTH_D-1:0]data_in;
	
	output [WIDTH_D-1:0]data_out;
	reg [WIDTH_D-1:0]data_out;
	
	reg [WIDTH_D-1:0] mem[0:DEPTH-1];
	
	integer i;
	
	always@(posedge clk_w)
		if (!rst_n) begin
			for (i=0;i<DEPTH;i=i+1)
				mem[i]<='h0000;
		end
		else if (en_w)
			mem[addr_r]<=data_out;
			
	always@(posedge clk_r)
		if (!rst_n)
			data_out<='h0000;
		else if (en_r)
			data_out<=mem[addr_r];
			
endmodule 

你可能感兴趣的:(数字电路设计,Verilog,HDL)