`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
/**********************************SFIFO************************************/
module sfifo#(
parameter WIDTH = 8,
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
);
//深度刚好是2的幂次方的情况
reg [$clog2(DEPTH):0] wp, rp;
wire wenc, renc;
assign wenc = winc & ~wfull;
assign renc = rinc & ~rempty;
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
wp <= 'd0;
else if(winc & ~wfull)
wp <= wp + 1'b1;
end
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
rp <= 'd0;
else if(rinc & ~rempty)
rp <= rp + 1'b1;
end
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
wfull <= 1'b0;
else
wfull <= ((wp[$clog2(DEPTH)] != rp[$clog2(DEPTH)]) && (wp[$clog2(DEPTH)-1:0] == rp[$clog2(DEPTH)-1:0])) ? 1'b1 : 1'b0;
end
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
rempty <= 1'b0;
else
rempty = (wp == rp) ? 1'b1 : 1'b0;
end
dual_port_RAM
#( .DEPTH(DEPTH),
.WIDTH(WIDTH)
)
u_dual_port_RAM
(
.wclk(clk),
.wenc(wenc),
.waddr(wp),
.wdata(wdata),
.rclk(clk),
.renc(renc),
.raddr(rp),
.rdata(rdata)
);
endmodule
`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
/**********************************SFIFO************************************/
//计数器方法
module sfifo#(
parameter WIDTH = 8,
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
);
reg [$clog2(DEPTH) :0] count;
reg [$clog2(DEPTH)-1:0] wp, rp;
wire wen, ren;
assign wen = winc & (~wfull);
assign ren = rinc & (~rempty);
//count
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
count <= 'd0;
else if(wen & ~ren) //只读
count <= count + 1'b1;
else if(ren & ~wen) //只写
count <= count - 1'b1;
end
//wfull
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
wfull <= 1'b0;
else if(count == DEPTH)
wfull <= 1'b1;
else
wfull <= 1'b0;
end
//rempty
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
rempty <= 1'b0;
else if(count == 'd0)
rempty <= 1'b1;
else
rempty <= 1'b0;
end
//wp
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
wp <= 'd0;
else if(wen && wp == (DEPTH-1))
wp <= 'd0;
else if(wen)
wp <= wp + 1'b1;
end
//rp
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
rp <= 'd0;
else if(ren && rp == (DEPTH-1))
rp <= 'd0;
else if(ren)
rp <= rp + 1'b1;
end
dual_port_RAM
#( DEPTH,
WIDTH )
u_dual_port_RAM
(
.wclk(clk),
.wenc(wen),
.waddr(wp),
.wdata(wdata),
.rclk(clk),
.renc(ren),
.raddr(rp),
.rdata(rdata)
);
endmodule