비동기식 FIFO(二)-손찢기 코드

전편에서 FIFO의 기초 이론을 계승하고 이론적 기초는, 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 

2진 코드 변환 그레코드
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 

좋은 웹페이지 즐겨찾기