写了一个同步fifo,初学者可以参考参考
fifo在 芯片和逻辑应用非常的广泛,是非常常见的基础模块,写了一个简单的fifo,module fifo_syn(
clk ,
rst_n ,
fifo_wr_en ,
fifo_wr_dat,
fifo_rd_en ,
fifo_rd_dat,
fifo_full,
fifo_empty ,
fifo_cnt
);
parameter WWIDTH = 8; //可参数化的地址位宽,
parameter DWIDTH = 8; //参数化的数据位宽
input clk ;
input rst_n ;
input fifo_wr_en ; //写使能
input fifo_wr_dat; //写数据
input fifo_rd_en ; //读使能
output fifo_rd_dat; //读数据
output fifo_full; //满信号
output fifo_empty ; //空信号
output fifo_cnt ; //fifo 计数,从0~255,256可以用满来表示
reg waddr ; //写地址
reg raddr ; //读地址
ram_ref//例化ram
#(
.DWIDTH(DWIDTH ),
.WWIDTH(WWIDTH )
)
u_ram_ref
(
.clk (clk ),
.wr_en (fifo_wr_en ),
.waddr (waddr ),
.wdata (fifo_wr_dat ),
.raddr (raddr ),
.rdata (fifo_rd_dat )
);
assign fifo_cnt =waddr - raddr;
assign fifo_full= (waddr == raddr)?1'b1:1'b0; //读写地址相等的时候,满信号拉起来
assign fifo_empty = ((waddr!=raddr)&&(waddr==raddr))?1'b1:1'b0;//最高位不相等,低位相等的时候,是空
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
waddr <= 'd0;
else if(fifo_wr_en == 1'b1 && fifo_full == 1'b0) //有写使能,并且fifo非满的时候写地址自增
waddr <= #1 waddr + 'd1;
end
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
raddr <= 'd0;
else if(fifo_rd_en == 1'b1&& fifo_empty == 1'b0) //有读使能,并且fifo非空的时候读地址自增
raddr <= #1 raddr + 'd1
end
endmodule
module ram_ref//ram模型,2个时钟周期出数据,在读地址给出之后,综合工具可以自己推断出RAM,或者自己用coregen生成ram
(
clk ,
wr_en ,//ram写使能
waddr ,//ram写地址
wdata ,//ram写数据
raddr ,//ram写地址
rdata //ram读数据
);
parameter WWIDTH = 8;
parameter DWIDTH = 8;
parameter DEPTH= 2**WWIDTH;
input wdata;
input waddr;
input wr_en;
input rdata;
output raddr;
reg mem_ram;
reg q;
always @(posedge clk)
begin
if(wr_en == 1'b1)
mem_ram <= #1 wdata;
end
always @(posedge clk)
begin
q <= #1 mem_ram;
rdata <= #1 q;
end
endmodule 支持,感谢分享 学习了
绝对的好东西,谢谢分享 原来的代码有些问题,重新上传 `timescale 1ns/1ns
module ram_ref//ram模型,2个时钟周期出数据,在读地址给出之后
(
clk ,
wr_en ,//ram写使能
waddr ,//ram写地址
wdata ,//ram写数据
raddr ,//ram写地址
rdata //ram读数据
);
parameter WWIDTH = 8;
parameter DWIDTH = 8;
parameter DEPTH= 2**WWIDTH;
input clk;
input wdata;
input waddr;
input wr_en;
output reg rdata;
input raddr;
reg mem_ram;
reg q;
always @(posedge clk)
begin
if(wr_en == 1'b1)
mem_ram <= #1 wdata;
end
always @(posedge clk)
begin
q <= #1 mem_ram;
rdata <= #1 q;
end
endmodule
`timescale 1ns/1ns
module fifo_syn
(
clk ,
rst_n ,
fifo_wr_en ,
fifo_wr_dat,
fifo_rd_en ,
fifo_rd_dat,
fifo_full,
fifo_empty ,
fifo_cnt
);
parameter WWIDTH = 8; //可参数化的地址位宽,
parameter DWIDTH = 8; //参数化的数据位宽
input clk ;
input rst_n ;
input fifo_wr_en ; //写使能
input fifo_wr_dat; //写数据
input fifo_rd_en ; //读使能
output fifo_rd_dat; //读数据
output fifo_full; //满信号
output fifo_empty ; //空信号
output fifo_cnt ; //fifo 计数,从0~255,256可以用满来表示
reg waddr ; //写地址
reg raddr ; //读地址
ram_ref//例化ram
#(
.DWIDTH(DWIDTH ),
.WWIDTH(WWIDTH )
)
u_ram_ref
(
.clk (clk ),
.wr_en (fifo_wr_en ),
.waddr (waddr ),
.wdata (fifo_wr_dat ),
.raddr (raddr ),
.rdata (fifo_rd_dat )
);
assign fifo_cnt =waddr - raddr;
assign fifo_empty= (waddr == raddr)?1'b1:1'b0; //读写地址相等的时候,满信号拉起来
assign fifo_full = ((waddr!=raddr)&&(waddr==raddr))?1'b1:1'b0;//最高位不相等,低位相等的时候,是空
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
waddr <= 'd0;
else if(fifo_wr_en == 1'b1 && fifo_full == 1'b0) //有写使能,并且fifo非满的时候写地址自增
waddr <= #1 waddr + 'd1;
end
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
raddr <= 'd0;
else if(fifo_rd_en == 1'b1&& fifo_empty == 1'b0) //有读使能,并且fifo非空的时候读地址自增
raddr <= #1 raddr + 'd1;
end
endmodule
`timescale 1ns/1ns
module tb();
reg clk;
reg rst_n;
reg fifo_wr_en ;
reg fifo_wr_dat;
reg fifo_rd_en ;
wire fifo_rd_dat;
initial
begin
fifo_rd_en = 'd0;
rst_n = 1;
#10;
rst_n = 0 ;
#10;
rst_n = 1;
end
initial
begin
clk =0;
forever clk = #50 ~clk;
end
task FIFO_WR;
input dat;
begin
@(posedge clk)
begin
fifo_wr_en<= #1 1'b1;
fifo_wr_dat <= #1 dat;
end
@(posedge clk)
begin
fifo_wr_en<= #1 1'b0;
fifo_wr_dat <= #1 dat;
end
end
endtask
task FIFO_RD ;
reg dat;
begin
@(posedge clk)
begin
fifo_rd_en <= #1 1'b1;
end
@(posedge clk)
begin
fifo_rd_en <= #1 1'b0;
end
@(posedge clk)
begin
dat <= #1 fifo_rd_dat;
end
$display("fifo read dat is %h",dat) ;
end
endtask
integer i;
initial
begin
for(i =0 ;i <256 ;i = i +1)
begin
FIFO_WR(i);
end
for(i =0 ;i <256 ;i = i +1)
begin
FIFO_RD;
end
end
fifo_syn u_fifo_syn
(
.clk (clk ),
.rst_n (rst_n ),
.fifo_wr_en (fifo_wr_en ),
.fifo_wr_dat(fifo_wr_dat),
.fifo_rd_en (fifo_rd_en ),
.fifo_rd_dat(fifo_rd_dat),
.fifo_full( ),
.fifo_empty ( ),
.fifo_cnt ( )
);
endmodule
下面是modelsim工程,直接下载用modelsim就可以跑起来 do文件,先把不必保存在这里怕这整丢了
vlib work
vmap work work
vlog fifo.v
vlog ram_ref.v
vlog tb.v
vsim -novopt work.tb
#add wave
add wave -position insertpoint sim:/tb/*
run 1ms 批处理文件
call D:\modeltech_10.1a\win32\vsim.exe -do wave.do
Fourier00 发表于 2013-9-15 21:58 static/image/common/back.gif
批处理文件
call D:\modeltech_10.1a\win32\vsim.exe -do wave.do
只要将上述的5个文件拷到一个projectname目录下,运行wave.bat就可以直接弹出波形
Fourier00 发表于 2013-9-15 22:04 static/image/common/back.gif
只要将上述的5个文件拷到一个projectname目录下,运行wave.bat就可以直接弹出波形
...
修改bat文件为你本人的modelsim安装路径,点击wave.bat就可以弹出波形 波形如下图所示 Fourier00 发表于 2013-9-15 22:10 static/image/common/back.gif
波形如下图所示
波形问题 RT 认真学习吧
好好看看
页:
[1]