同步fifo的verilogHDL设计实例

时间:2024-01-12 14:41:38

原创

设计一个fifo,输入16bit,输出16bit的data,寻址宽度5bit,有空满标志。

top 层如下所示:

 /*
date : 2014/10/14
version : modelsim 10.1e-altera
design : pengxiaoen
function : 同步fifo设计
*/
module test2 (
clock ,
reset,
in_data , ou_data ,
wr_full ,
rd_empty ,
wr_en ,
rd_en
); input clock ,reset ;
input [:] in_data ; // 写入的数据
input wr_en ; //写使能
input rd_en ; //读使能 output [:] ou_data ; // 读出的数据
output wr_full ; //写满标志
output rd_empty ; //读空标志 wire [:] add_head; //ram地址头,当读使能有效+1
wire [:] add_end ; //ram地址尾,当写使能有效+1 //---------ram 模块,用来存储数据和输出数据--------------------------
data_memory U1_mem(
.clock (clock),
.reset (reset),
.wr_en (wr_en),
.rd_en (rd_en),
.add_head (add_head) ,
.add_end (add_end),
.in_data (in_data),
.ou_data (ou_data)
); //------------地址产生器 + 标志产生器---------------------------------
fifo_control U2_cont(
.clock (clock),
.reset (reset),
.wr_en (wr_en),
.rd_en (rd_en),
.wr_full (wr_full),
.rd_empty (rd_empty),
.add_head (add_head),
.add_end (add_end)
); endmodule
 module  data_memory (
clock ,reset ,
wr_en , rd_en ,
add_head ,add_end ,
in_data ,ou_data
);
input clock ,reset ; // system clock and system reset
input wr_en ; // write enable
input rd_en ; // read enable
input [:] add_head ; // memory address head
input [:] add_end ; // memory address end
input [:]in_data ; // data input to memory
output reg[:]ou_data ; // data output reg [:] mem [:] ; //define the memory
always @ (posedge clock )
if(!reset)
begin
ou_data <= 'dx ;
end
else
begin
case ({wr_en, rd_en})
'b00 : ou_data <= 16'dx ;
'b01 : ou_data <= mem[add_head] ;
'b10 : mem[add_end] <= in_data ;
'b11 : begin
ou_data <= mem[add_end] ;
mem[add_head] <= in_data ;
end
endcase
end endmodule
 module fifo_control (
clock ,reset ,
wr_en ,rd_en ,
wr_full ,rd_empty,
add_head,add_end
);
input clock ,reset ; // system clock and system reset
input wr_en ; // write enable
input rd_en ; // read enable
output reg wr_full ; // fifo full flag
output reg rd_empty ; // fifo empty
output reg [:] add_head ,add_end ; reg [:] head_temp , end_temp ;
//------地址产生块,依据读写使能进行相应地址递增,并保存原始的位置信息-----------------------
always @ (posedge clock)
if(!reset)
begin
head_temp <= 'd0 ;
end_temp <= 'd0 ;
add_head <= 'd0 ;
add_end <= 'd0 ;
end else
begin
case ({wr_en, rd_en})
'b00 : begin
head_temp <= add_head ;
end_temp <= add_end ;
end
'b01 : begin
end_temp <= add_end ;
add_head <= add_head + 'd1 ;
end
'b10 : begin
head_temp <= add_head ;
add_end <= add_end + 'd1 ;
end
'b11 : begin
add_head <= add_head + 'd1 ;
add_end <= add_end + 'd1 ;
end
endcase
end //--------标志产生块-------------------
always @ (posedge clock)
if(!reset)
begin
wr_full <= 'd0 ;
rd_empty <= 'd0 ;
end
else
begin
case ({wr_en , rd_en})
'b00 : begin
rd_empty <= 'd0 ;
wr_full <= 'd0 ;
end
'b01 : begin
wr_full <= 'd0 ; //写标志复位
if ((add_head + 'd1) == head_temp)
rd_empty <= 'd1 ; //只有切换到写使能才复位
end
'b10 : begin
rd_empty <= 'd0 ; //读标志复位
if ((add_end + 'd1) == end_temp)
wr_full <= 'd1 ; //只有切换到读使能才复位
end
'b11 : begin
rd_empty <= 'd0 ;
wr_full <= 'd0 ;
end
endcase
end endmodule

下面附上测试代码

 `timescale  1ns/1ps 

 module test2_tb ;
reg clock ,reset ;
reg [:] in_data ;
reg wr_en ;
reg rd_en ; wire [:] ou_data ;
wire wr_full ;
wire rd_empty ; test2 U_top (
.clock (clock),
.reset (reset),
.in_data (in_data), .ou_data (ou_data),
.wr_full (wr_full),
.rd_empty (rd_empty),
.wr_en (wr_en),
.rd_en (rd_en)
); integer i ; always # clock = ~clock ; initial
begin
clock ='d0 ; reset = 1'd0 ; wr_en <= 'd0 ; rd_en <= 1'd0 ;
in_data = 'd0 ;
# reset = 'd1 ; wr_en <= 1'd1 ;
for (i=;i<;i=i+) // 故意溢出
# in_data <= in_data + 'd1 ; rd_en <= 'd1 ; wr_en <= 1'd0 ;
#(* ) // 让读空标志位触发
$stop ; end endmodule