您的位置:首页 > 其它

asyn_fifo

2016-02-01 22:17 369 查看
//Module Name:afifo_ctrl
//Description:parameterized afifo

module afifo_ctrl(
clk_push,
rst_push_n,
clk_pop,
rst_pop_n,
push,
push_data,
full,
pop,
pop_data,
empty,
mem_waddr,
mem_wen,
mem_wdata,
mem_raddr,
mem_ren,
mem_rdata,
almost_full
);

parameter DATAWIDTH = 32;         //the data width of AFIFO
parameter ADDRWIDTH = 8;          //the address bits of AFIFO and it must be >=2
//the AFIFO depth must be 2^ADDRWIDTH
//input declaration
input clk_push;                   //push clock
input rst_push_n;                 //reset signal in push clock domain

input clk_pop;                    //pop clock
input rst_pop_n;                  //reset signal in pop clock domain
input push ;                      //push enable to AFIFO
input [DATAWIDTH-1:0]  push_data; //push data to AFIFO
input pop  ;                      //pop enable to AFIFO
input [DATAWIDTH-1:0]  mem_rdata; //read data from memory stack

//output declaration
output full;                      //full indicator,and the logic of user can't push data when this signal is high                                                           //ok
output [DATAWIDTH-1:0] pop_data ; //pop data from AFIFO              //ok
output empty;                     //empty indicator, and the logic of user can't pop data when this signal is high                                                           //ok
output [ADDRWIDTH-1:0] mem_waddr; //write address to memory stack    //ok
output mem_wen;                   //write enable to memory stack     //ok
output [DATAWIDTH-1:0] mem_wdata; //write data to memory stack       //ok
output [ADDRWIDTH-1:0] mem_raddr; //read address to memory stack     //ok
output mem_ren;                   //read enable to memory stack      //ok
output almost_full;

//register declaration

reg [ADDRWIDTH-1:0]  mem_waddr;
reg [ADDRWIDTH-1:0]  mem_raddr;
reg [ADDRWIDTH-1:0]  gray_waddr_1r;
reg [ADDRWIDTH-1:0]  gray_waddr_2r_1_sync;
reg [ADDRWIDTH-1:0]  gray_waddr_3r_2_sync;
reg [ADDRWIDTH-1:0]  gray_raddr_1r;
reg [ADDRWIDTH-1:0]  gray_raddr_2r_1_sync;
reg [ADDRWIDTH-1:0]  gray_raddr_3r_2_sync;
reg [ADDRWIDTH-1:0]  gray_waddr_temp;
reg [ADDRWIDTH-1:0]  gray_raddr_temp;
reg [ADDRWIDTH-1:0]  biny_waddr;
reg [ADDRWIDTH-1:0]  biny_raddr;
reg [ADDRWIDTH-1:0]  biny_waddr_temp;
reg [ADDRWIDTH-1:0]  biny_raddr_temp;
reg [DATAWIDTH-1:0]  pop_data_r;
reg pop_r;
reg empty_flag;
reg full_flag;

//net declaration
wire mem_wen;
wire mem_ren;
wire [DATAWIDTH-1:0] mem_wdata;
wire [DATAWIDTH-1:0] pop_data;
wire [ADDRWIDTH-1:0] gray_waddr;
wire [ADDRWIDTH-1:0] gray_raddr;
wire pop_one_left;
wire pop_ptr_diff;
wire push_one_left;
wire push_ptr_diff;

integer i;

assign mem_wen = push;
assign mem_wdata[DATAWIDTH-1:0] = push_data[DATAWIDTH-1:0];
assign mem_ren = pop;

//for output signal pop_data
always@(posedge clk_pop or negedge rst_pop_n)
begin
if(~rst_pop_n)
pop_r<=1'b0;
else
pop_r<=pop;
end

always@(posedge clk_pop or negedge rst_pop_n)
begin
if(~rst_pop_n)
pop_data_r[DATAWIDTH-1:0] <= 0;
else
pop_data_r[DATAWIDTH-1:0] <= mem_rdata[DATAWIDTH-1:0];
end

assign pop_data[DATAWIDTH-1:0] = pop_r ? mem_rdata[DATAWIDTH-1:0]:pop_data_r[DATAWIDTH-1:0];

//for output signal mem_waddr
always@(posedge clk_push or negedge rst_push_n)
begin
if(~rst_push_n)
mem_waddr[ADDRWIDTH-1:0] <=0;
else
mem_waddr[ADDRWIDTH-1:0] <= mem_waddr[ADDRWIDTH-1:0] + 1'b1;
end

//for output signal mem_raddr
always@(posedge clk_pop or negedge rest_pop_n)
begin
if(~rst_pop_n)
mem_raddr[ADDRWIDTH-1:0]<=0;
else
mem_raddr[ADDRWIDTH-1:0] <= mem_raddr[ADDRWIDTH-1:0] + 1'b1;
end

//for output signal empty
assign gray_addr[ADDRWIDTH-1:0] = {mem_waddr[ADDRWIDTH-1],gray_waddr_temp[ADDRWIDTH-2:0]};
always@(* )
for(i=0;i<(ADDRWIDTH-1);i=i+1)
gray_waddr_temp[i] = mem_waddr[i]^mem_waddr[i+1];

always@(posedge clk_push or negedge rst_push_n)
begin
if(~rst_push_n)
gray_waddr_1r[ADDRWIDTH-1:0] <=0 ;
else
gray_waddr_1r[ADDRWIDTH-1:0] <= gray_waddr[ADDRWIDTH-1:0];
end

always@(posedge clk_pop or negedge rst_pop_n)
begin
if(~rst_pop_n) begin
gray_waddr_2r_1_sync[ADDRWIDTH-1:0] <=0;
gray_waddr_3r_2_sync[ADDRWIDTH-1:0] <=0;
end
else begin
gray_waddr_2r_1_sync[ADDRWIDTH-1:0] <= gray_waddr_1r[ADDRWIDTH-1:0];
gray_waddr_3r_2_sync[ADDRWIDTH-1:0] <= gray_waddr_2r_1_sync[ADDRWIDTH-1:0];
end
end

always@(*)
biny_waddr[ADDRWIDTH-1] = gray_waddr_3r_2_sync[ADDRWIDTH-1];

always@(*)
for(i=0;i<(ADDRWIDTH-1);i=i+1)
biny_waddr[ADDRWIDTH-2-i] = gray_waddr_3r_2_sync[ADDRWIDTH-2-i]^biny_waddr_temp[ADDRWIDTH-1-i];

always@(*)
biny_waddr_temp[ADDRWIDTH-1:0] = biny_waddr[ADDRWIDTH-1:0];

assign pop_one_left = (biny_waddr[ADDRWIDTH-1:0] ==(mem_raddr[ADDRWIDTH-1:0] + 1'b1));
assign pop_ptr_diff = (biny_waddr[ADDRWIDTH-1:0] != mem_raddr[ADDRWIDTH-1:0]);

always@(posedge clk_pop or negedge rst_pop_n)
begin
if(~rst_pop_n)
empty_flag <=1'b1;
else if(pop_one_left && pop)
empty_flag <= 1'b1;
else if(empty_flag && pop_ptr_diff)
empty_flag <= 1'b0;
end

assign empty = ~pop_ptr_diff && empty_flag;

//for output signal full
assign gray_raddr[ADDRWIDTH-1:0] = {mem_raddr[ADDRWIDTH-1],gray_raddr_temp[ADDRWIDTH-2:0]};

always@(*)
for(i=0;i<(ADDRWIDTH-1);i=i+1)
gray_raddr_temp[i] = mem_raddr[i] ^ mem_raddr[i+1];

always@(posedge clk_pop or negedge rst_pop_n)
begin
if(~rst_pop_n)
gray_raddr_1r[ADDRWIDTH-1:0] <=0;
else
gray_raddr_1r[ADDRWIDTH-1:0] <= gray_raddr[ADDRWIDTH-1:0];
end

always@(posedge clk_push or negedge rst_push_n)
begin
if(~rst_push_n)begin
gray_raddr_2r_1_sync[ADDRWIDTH-1:0]<=0;
gray_raddr_3r_2_sync[ADDRWIDTH-1:0]<=0;
end
else begin
gray_raddr_2r_1_sync[ADDRWIDTH-1:0] <= gray_raddr_1r[ADDRWIDTH-1:0]:
gray_raddr_3r_2_sync[ADDRWIDTH-1:0] <= gray_raddr_2r_sync[ADDRWIDTH-1:0];
end
end

always@(*)
biny_raddr[ADDRWIDTH-1] = gray_raddr_3r_2_sync[ADDRWIDTH-1];
always@(*)
for(i=0;i<(ADDRWIDTH-1);i=i+1)
biny_raddr[ADDRWIDTH-2-i] = gray_raddr_3r_2_sync[ADDRWIDTH-2-i] ^biny_raddr_temp[ADDRWIDTH-1-i];

always@(*)
biny_raddr_temp[ADDRWIDTH-1:0] = biny_raddr[ADDRWIDTH-1:0];

assign push_one_left = (biny_raddr[ADDRWIDTH-1:0] ==(mem_waddr[ADDRWIDTH-1:0] + 1'b1));
assign push_ptr_diff = (biny_raddr[ADDRWIDTH-1:0] !=(mem_waddr[ADDRWIDTH-1:0]));

always@(posedge clk_push or negedge rst_push_n)
begin
if(~rst_push_n)
full_flag <= 1'b0;
else if(push_one_left && push)
full_flag <= 1'b1;
else if(full_flag && push_ptr_diff)
full_flag <=1'b0
end

assign full= ~push_ptr_diff && full_flag;
assign almost_full = push_one_left;

endmodule
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: