w_str92 2016-07-13 10:39 采纳率: 0%
浏览 2666

自己写的异步fifo在读数据时与写入的不一至,时序暂时还没有发现问题

使用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

  • 写回答

2条回答 默认 最新

  • _1_1_7_ 2016-07-14 03:15
    关注

    写入数据前,先初始化

    评论

报告相同问题?

悬赏问题

  • ¥15 fluent的在模拟压强时使用希望得到一些建议
  • ¥15 STM32驱动继电器
  • ¥15 Windows server update services
  • ¥15 关于#c语言#的问题:我现在在做一个墨水屏设计,2.9英寸的小屏怎么换4.2英寸大屏
  • ¥15 模糊pid与pid仿真结果几乎一样
  • ¥15 java的GUI的运用
  • ¥15 Web.config连不上数据库
  • ¥15 我想付费需要AKM公司DSP开发资料及相关开发。
  • ¥15 怎么配置广告联盟瀑布流
  • ¥15 Rstudio 保存代码闪退