赞
踩
只写不读时:若FIFO满,则写失败,写地址不变;若FIFO不满,则写一定成功,写地址加1。
又写又读时:若FIFO满,读写为同一单元,因读操作只需读取旧数据,所以读写都成功,写地址加1;若FIFO不满,则进行读写操作的是两个不同单元,所以写一定成功,所以写地址也加1。
总结,wr_en && (!full || (full && rd_en))时,写地址加1;其他情况,写地址不变。因为只有写成功(写地址加1)的情况,才能让RAM的写使能有效,所以RAM的写使能也为wr_en && (!full || (full && rd_en))。
只读不写时:若FIFO空,则读失败,读地址不变;若FIFO不空则读一定成功,读地址加1.。
又读又写时:若FIFO空,则读写为同一单元,由于单元内无旧数据,读失败,只有写成功,此时读地址不变;若FIFO不空,则进行读写操作的是两个不同单元,所以读一定成功,读地址加1。
总结,(re有效&&empty标志无效)时,读地址加1;其他情况,读地址不变。因为只有读成功(读地址加1)的情况,才能让RAM的读使能有效,所以RAM的读使能也为(re有效&&empty标志无效)。
module sync_fifo( clk, rst, //async wr_data, wr_en, rd_data, rd_en, full, empty ); parameter DATA_WIDTH = 32, DATA_DEPTH = 8, ADD_WIDTH = 3; input clk; input rst; input wr_data; input wr_en; input rd_en; output rd_data; output full; output empty; reg [DATA_WIDTH-1:0] wr_data; reg [DATA_WIDTH-1:0] rd_data; reg [DATA_WIDTH-1:0] ram_32_8[DATA_DEPTH-1:0]; reg [ADD_WIDTH-1:0] wr_add; reg [ADD_WIDTH-1:0] rd_add; reg [ADD_WIDTH-1+1:0] data_count; wire full; wire empty; reg wr_enbuf; reg rd_enbuf; assign wr_enbuf = wr_en && (!full || (full && rd_en)); assign rd_enbuf = rd_en && !empty; //写指针移动 always@(posedge clk or negedge rst)begin if(!rst) wr_add <= 3'b0; else if(wr_enbuf) wr_add <= wr_add + 1'b1; end //读指针移动 always@(posedge clk or negedge rst)begin if(!rst) rd_add <= 3'b0; else if(rd_enbuf) rd_add <= rd_add + 1'b1; end //数据计数器 always@(posedge clk or negedge rst)begin//case is good if(!rst) data_count <= 4'b0; else begin if(rd_enbuf && wr_enbuf) //writing while reading data_count <= data_count; else if(wr_enbuf) //writing data_count <= data_count + 1'b1; else if(rd_enbuf) //reading data_count <= data_count - 1'b1; end end //满空判断 // always@(posedge clk or negedge rst)begin // if(!rst) // full <= 1'b0; // else // //full <= (!rd_enbuf && data_count == 4'b1000)||(!rd_enbuf && data_count == 4'b0111 && wr_enbuf)||(rd_enbuf && wr_enbuf && data_count == 4'b1000); // end assign full = data_count == 4'b1000; // always@(posedge clk or negedge rst)begin // if(!rst) // empty <= 1'b1; // else // //empty <= (!wr_enbuf && data_count == 3'b000)||(!wr_enbuf && data_count ==3'b001 && rd_enbuf); // end assign empty = data_count == 0; //ram写读数据 always@(posedge clk or negedge rst)begin if(!rst)begin integer i ; for(i=0;i < DATA_DEPTH;i=i+1) begin ram_32_8[i] <= 32'b0; end end else if(wr_enbuf)begin ram_32_8[wr_add] <= wr_data; end end always@(posedge clk or negedge rst)begin if(!rst)begin rd_data <= 32'b0; end else if(rd_enbuf)begin rd_data <= ram_32_8[rd_add]; end end endmodule
`timescale 1ps/1ps module test; //data type spicifiction reg clk; reg rst; reg [31:0] wr_data; reg wr_en; reg rd_en; wire [31:0] rd_data; wire full; wire empty; //reset all initial begin clk = 0; rst = 1; wr_en = 0; rd_en = 0; wr_data = 32'b0; #2 rst = 0; #5 rst = 1; end //clock genarating always #0.5 clk = ~clk; //stimulate initial begin #10 wr_en = 1; rd_en = 0; #10 wr_en = 0; rd_en = 1; #10 wr_en = 1; rd_en = 0; #3 rd_en = 1; #10 repeat(100) begin #5 wr_en = {$random}%2; rd_en = {$random}%2; end end always #1 wr_data = {$random}%10; //module instantiation sync_fifo u_sync_fifo( .clk (clk ), .rst (rst ), .wr_data (wr_data), .wr_en (wr_en ), .rd_data (rd_data), .rd_en (rd_en ), .full (full ), .empty (empty ) ); //stop initial begin forever begin #100 //$display("---gyc---:%d",$time); if($time >= 2000)begin $finish; end end end endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。