`timescale 1ns/1ns /**********************************RAM************************************/ module dual_port_RAM #(parameter DEPTH = 16, parameter WIDTH = 8)( input wclk ,input wenc ,input [$clog2(DEPTH)-1:0] waddr ,input [WIDTH-1:0] wdata ,input rclk ,input renc ,input [$clog2(DEPTH)-1:0] raddr ,output reg [WIDTH-1:0] rdata ); reg [WIDTH-1:0] RAM_MEM [0:DEPTH-1]; always @(posedge wclk) begin if(wenc) RAM_MEM[waddr] <= wdata; end always @(posedge rclk) begin if(renc) rdata <= RAM_MEM[raddr]; end endmodule // 请设置 带有空满信号 的同步FIFO. /**********************************SFIFO************************************/ module sfifo#( parameter WIDTH = 8, // FIFO,本质是 先进先出,可以同时读写. parameter DEPTH = 16 // )( input clk , input rst_n , input winc , input rinc , input [WIDTH-1:0] wdata , output reg wfull , output reg rempty , output wire [WIDTH-1:0] rdata ); // 加寄存器计数,来判断 空满. parameter ADDR_WIDTH = $clog2(DEPTH); // 4 // waddr[4] == raddr[4]; 如果相等,则要么相等是1,要么相等是0. // 代码 reg [ADDR_WIDTH:0] waddr; // reg [4:0] waddr; reg [ADDR_WIDTH:0] raddr; // 采用计数器方法:fifo_cnt reg [ADDR_WIDTH:0] fifo_cnt; always@(posedge clk or negedge rst_n) begin if(!rst_n) begin waddr <= 'd0; raddr <= 'd0; fifo_cnt <= 'd0; end else if(!wfull && winc && fifo_cnt < DEPTH) begin waddr <= waddr + 1'd1; fifo_cnt <= fifo_cnt + 1'd1; end else if(!rempty && rinc && fifo_cnt > 0) begin raddr <= raddr + 1'd1; fifo_cnt <= fifo_cnt - 1'd1; end end always@(posedge clk or negedge rst_n) begin if(!rst_n) begin wfull <= 'd0; rempty <= 'd0; end else if(fifo_cnt == 'd0) // 如果 rempty <= 1'd1; else if(fifo_cnt == DEPTH) wfull <= 1'd1; else begin wfull <= 'd0; rempty <= 'd0; end end /* // 写,写满后,保持 always@(posedge clk or negedge rst_n) begin if(!rst_n) waddr <= 'd0; else if(!wfull && winc) // 只要有效,就一直写下去. waddr <= waddr + 1'd1; end // 读,读满后,保持 always@(posedge clk or negedge rst_n) begin if(!rst_n) raddr <= 'd0; else if(!rempty && rinc) // 只要有效,就一直读下去. raddr <= raddr + 1'd1; end /* // full empty gen wire [ADDR_WIDTH:0] fifo_cnt; // 判断 写地址、读地址是:0, DEPTH。 /* 如果最高位相等,则可能相等, 判断 是否相等是 0; 如果最高位不等,则一定不等, 判断 是否是 DEPTH. */ /* // [4:0] - [4:0]. assign fifo_cnt = (waddr[ADDR_WIDTH] == raddr[ADDR_WIDTH]) ? (waddr[ADDR_WIDTH:0] - raddr[ADDR_WIDTH:0]) : (DEPTH + waddr[ADDR_WIDTH-1:0] - raddr[ADDR_WIDTH-1:0]); // DEPTH + [3:0] - [3:0]. */ // RAM_MEM wire wen; wire ren; wire wren; // 1, write. assign wen = winc & !wfull; // 写使能有效,写不满 assign ren = rinc & !rempty; // 读使能有效,读不空 // dual_port_RAM u1_dual_port_RAM( .wclk (clk ), .wenc (wen ), .waddr (waddr ), .wdata (wdata ), // 写数据 .rclk (clk ), .renc (ren ), .raddr (raddr ), .rdata (rdata ) // 读数据 ); endmodule /* // 读空 always@(posedge clk or negedge rst_n) begin if(!rst_n) begin rempty <= 1'd0; raddr <= 4'd0; end else if(rinc == 1 && raddr >= 4'd15) begin rempty <= 1'd0; raddr <= end end // 写满 always@(posedge clk or negedge rst_n) begin if(!rst_n) begin wfull <= 1'd0; rempty <= 1'd0; addr <= 4'd0; end // 写地址 else if(winc == 1 && addr < 4'd15) begin wfull <= 1'd0; rempty <= 1'd0; addr <= addr + 1'd1; end else if(winc == 1 && addr == 4'd15) begin wfull <= 1'd1; rempty <= 1'd0; addr <= addr; // 写满后,保持 end // 读空 else if(rinc == 1 && addr > 4'd0) begin wfull <= 1'd0; rempty <= 1'd0; addr <= addr - 1'd1; end else if(rinc == 1 && addr == 4'd0) begin wfull <= 1'd0; rempty <= 1'd1; addr <= addr; // 读空后,保持 end end */