Fourier00 发表于 2013-8-25 20:18:04

写了一个同步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

hyghyg1234 发表于 2013-8-25 21:00:09

支持,感谢分享

kongethan 发表于 2013-8-26 10:10:51

学习了

leo2012 发表于 2013-8-26 16:56:20

绝对的好东西,谢谢分享

Fourier00 发表于 2013-8-28 22:28:18

原来的代码有些问题,重新上传

Fourier00 发表于 2013-8-28 22:28:57

`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

Fourier00 发表于 2013-8-28 22:29:16

`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

Fourier00 发表于 2013-8-28 22:29:33

`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

Fourier00 发表于 2013-8-28 22:31:38

下面是modelsim工程,直接下载用modelsim就可以跑起来

Fourier00 发表于 2013-9-15 21:01:44

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

Fourier00 发表于 2013-9-15 21:58:48

批处理文件
call D:\modeltech_10.1a\win32\vsim.exe -do wave.do

Fourier00 发表于 2013-9-15 22:04:09

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:08:48

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:24

波形如下图所示

Fourier00 发表于 2013-9-15 22:10:54

Fourier00 发表于 2013-9-15 22:10 static/image/common/back.gif
波形如下图所示

波形问题 RT

jtc2006 发表于 2013-9-15 22:31:06

认真学习吧

bi大痣 发表于 2014-4-7 22:32:27

好好看看
页: [1]
查看完整版本: 写了一个同步fifo,初学者可以参考参考