使用altera的双端口只读只写ram完成异步fifo功能时,当读到地址为341的数据时,数据和原来写入的不一至,是不是官方提供的ram模块有问题?
我是用modelsim仿真的,前边读到的数据都没有问题。双端口ram:M9K、1024x16bit。
异步fifo代码:
module lcd_fifo(
reset_n,
wrclk,
rdclk,
wren,
rden,
full,
empty,
data,
q);
input reset_n;
input wrclk; //Frequency of wrclk must greater or equal than that of rdclk four times
input rdclk;
input wren;
input rden;
output full;
output empty;
input [15:0]data;
output [15:0]q;
parameter NONE=0;
parameter FIFO_SIZE=1024;
reg state;
reg full;
reg empty;
reg empty1;
reg wren1;
reg rden1;
reg [10:0]address_wr;
reg [10:0]address_wr1;
reg [10:0]address_rd;
reg [10:0]address_rd1;
wire [10:0]address_rd_gray;
wire [10:0]address_sync;
reg [10:0]address_sync_gray;
reg [10:0]address_sync1_gray;
ram2p_1kx16 ram(.wrclock(wrclk), .wren(wren), .wraddress(address_wr[9:0]), .data(data),
.rdclock(rdclk), .rden(rden), .rdaddress(address_rd[9:0]), .q(q));
gray2bin gray2bin1(.gray(address_sync1_gray), .bin(address_sync));
always @(posedge wrclk or negedge reset_n) begin
if(!reset_n)
address_sync1_gray <= 0;
else
address_sync1_gray <= address_sync_gray;
end
always @(address_wr1 or address_sync) begin
case (address_wr1-address_sync)
FIFO_SIZE: begin
full = 1;
empty1 = 0;
end
NONE: begin
full = 0;
empty1 = 1;
end
default: begin
full = 0;
empty1 = 0;
end
endcase
end
always @(negedge wrclk or negedge reset_n)
if(!reset_n)
empty <= 1;
else
empty <= empty1;
always @(posedge wrclk or negedge reset_n) begin
if(!reset_n) begin
wren1 <= 0;
address_wr1 <= 0;
end
else begin
if(wren) begin
wren1 <= 1;
address_wr1 <= address_wr+1;
end
else
wren1 <= 0;
end
end
always @(negedge wrclk or negedge reset_n) begin
if(!reset_n) begin
address_wr <= 0;
end
else begin
if(wren1)
address_wr <= address_wr1;
end
end
bin2gray bin2gray1(.bin(address_rd1), .gray(address_rd_gray));
always @(negedge rdclk or negedge reset_n) begin
if(!reset_n)
address_sync_gray <= 0;
else
address_sync_gray <= address_rd_gray;
end
always @(posedge rdclk or negedge reset_n) begin
if(!reset_n) begin
address_rd1 <= 0;
rden1 <= 0;
end
else begin
if(rden) begin
address_rd1 <= address_rd+1;
rden1 <= 1;
end
else
rden1 <= 0;
end
end
always @(negedge rdclk or negedge reset_n) begin
if(!reset_n) begin
address_rd <= 0;
end
else begin
if(rden1)
address_rd <= address_rd1;
end
end
endmodule
module bin2gray(
gray, bin);
parameter WIDTH=11;
input [WIDTH-1:0]bin;
output [WIDTH-1:0]gray;
assign gray[WIDTH-1] = bin[WIDTH-1]^0;
genvar i;
generate
for(i=0; i<WIDTH-1; i=i+1)
begin: a
assign gray[i] = ^bin[i+1:i];
end
endgenerate
endmodule
module gray2bin(
bin, gray);
parameter WIDTH=11;
input [WIDTH-1:0]gray;
output [WIDTH-1:0]bin;
assign bin[WIDTH-1] = gray[WIDTH-1];
genvar i;
generate
for(i=0; i<WIDTH-1; i=i+1)
begin: a
assign bin[i] = gray[i]^bin[i+1];
end
endgenerate
endmodule
测试代码:
module lcdfifo_test(
reset_n,
wrclk,
rdclk,
wren,
rden,
full,
empty,
data,
q);
`timescale 1ns/1ns
output reset_n;
output wrclk; //Frequency of wrclk must greater or equal than that of rdclk four times
output rdclk;
output wren;
output rden;
input full;
input empty;
output [15:0]data;
input [15:0]q;
parameter NONE=0;
parameter FIFO_SIZE=1024;
parameter MEMSIZE=2048;
reg [15:0] mem1[MEMSIZE-1:0];
reg [15:0] mem2[MEMSIZE-1:0];
reg reset_n;
reg wren;
reg wren1;
reg full1;
reg full2;
reg wrclk;
reg [15:0]data;
reg rdclk;
reg rden;
reg rden1;
reg empty1;
lcd_fifo fifo(.reset_n(reset_n), .wrclk(wrclk), .rdclk(rdclk), .wren(wren), .rden(rden),
.full(full), .empty(empty), .data(data), .q(q));
integer i, j, k, y;
wire wrclk_n;
wire rdclk_n;
assign wrclk_n = ~wrclk;
assign rdclk_n = ~rdclk;
initial fork
reset_n = 0;
wrclk = 0;
wren = 0;
wren1 = 0;
full1 = 0;
full2 = 0;
empty1 = 0;
data = 0;
#10 reset_n = 1;
#18 wren1 = 1;
rdclk = 0;
rden = 0;
rden1 = 0;
join
initial begin
i = ~0;
j = 0;
k = 0;
y = 0;
end
initial begin
for(y=0; y<MEMSIZE; y=y+1) begin
mem1[y] = $random % 2**15;
end
end
always #5 wrclk = ~wrclk; //generate 100Mhz frequency
always #20 rdclk = ~rdclk; //generate 25Mhz frequency
always @(posedge wrclk, posedge wrclk_n, negedge reset_n) begin
if(reset_n) begin
if(wrclk) begin
if(!full2) begin
if(i == 1500) begin
if(j<120) begin
j <= j+1;
wren1 <= 0;
end
else begin
i <= i+1;
wren1 <= 1;
end
end
else if(i < MEMSIZE-1) begin
i <= i+1;
wren1 <= 1;
end
else begin
wren1 <= 0;
end
end
end
else begin
if(wren1) begin
data <= mem1[i];
wren <= 1;
end
else
wren <= 0;
end
end
end
always @(posedge wrclk_n)
if(full)
full1 <= 1;
else
full1 <= 0;
always @(posedge wrclk_n) begin
if(full1)
full2 <= 1;
else
full2 <= 0;
end
always @(posedge rdclk or negedge reset_n) begin
if(reset_n) begin
if(rden)
rden1 <= 1;
else
rden1 <= 0;
end
end
always @(posedge rdclk_n or negedge reset_n) begin
if(reset_n) begin
if(rden1) begin
mem2[k] <= q;
k <= k+1;
end
if(empty)
rden <= 0;
else
rden <= 1;
end
end
integer z;
always @(k) begin
if(k == MEMSIZE-1) begin
#50;
for(z=0; z<MEMSIZE; z=z+1)
if(mem1[z] != mem2[z]) begin
$display("Error occured at the address %d in memory when transfer data through fifo.", z);
$display("Simulation aborted");
$writememh("fifomem1.txt", mem1);
$writememh("fifomem2.txt", mem2);
$finish;
end
$display("Transfer data without error!");
$writememh("fifomem1.txt", mem1);
$writememh("fifomem2.txt", mem2);
$finish;
end
end
endmodule