Vivado 使用 ROM ip输出未知值

Vivado 使用 ROM ip输出未知值
/**
*cache driver
*TODO 搜索整个组, 确定是否有效
*TODO 读命中的活动
*TODO 读缺失的活动
*/
`timescale 1ns / 1ps
module cache_top (//
    input           clk,
    input           resetn,
    //Sram-Like接口信号定义
    input           cpu_req,//cpu 读信号
    input[31:0]     cache_addr,// cpu 给出的cache地址
    output[31:0]    cache_rdata,// cpu 读出数据
    output          cache_addr_ok,// 若命中, 则为1
    output          cache_data_ok,// 数据准备完毕, 则为1
    //AXI接口信号定义 暂时可以不用管下列接口(2022年11月22日)
    output[3:0]     arid,
    output          arvalid,
    input           arready,

    input[3:0]      rid,
    input[31:0]     rdata,
    input           rlast,
    input           rvalid,
    output          rready    
);
wire rst=~resetn;
/**DFA
*IDLE:空转->random stat
*RUN:运行状态
*SEL_WAY:未命中
*MISS:这个状态时,cache会更新LRU, 并发起AXI请求, 从存储器中读取未命中的行, 如果允许读,就转向REFILE
*FINISH:数据传输完成,Cache在下一个状态回到IDLE状态
*RESETN:重置DFA,持续128个周期,直到专用计数器为127时回到IDLE状态
*/
localparam IDLE = 4'b0000,
            RUN = 4'b0001,
            WAIT = 4'b0010,
            SEL_WAY = 4'b0011,
            MISS = 4'b0100,
            REFILL2=4'b101,
            FINISH = 4'b0110,
            REFILL = 4'b0111,
            RESETN = 4'b1000,
            CACHE_GROUP_NUM=2047,
            WAIT_LATENCY=4'ha;
reg[3:0]    cur_stat;
reg[3:0]    next_stat;
reg[6:0]    rst_latency;
// reg[1:0]    LRU[0:2047][0:1];
reg[1:0]    LRU[0:2047];
// cache_line[161:0]   [valid(1) |tag(16) |block(64)|valid(1)|tag(16)|block(64)]
// cpu_addr     [tag(16) |group idx(11)|block offset(5)]

wire[161:0]  cache_line;
    
wire[10:0]  idx_from_cpu=cache_addr[15:5];// 组号

wire[15:0]  tag_from_cpu=cache_addr[31:16];// cpu给出的tag

wire[4:0]   ofs_from_cpu=cache_addr[4:0];// 块内偏移

wire        valid1_from_cache=cache_line[161:161];
wire        valid2_from_cache=cache_line[80:80];// 有效位

wire[15:0]        tag1_from_cache=cache_line[160:145];
wire[15:0]        tag2_from_cache=cache_line[79:64];// cache读出的tag

reg replaceOver=0;
wire hit  =(((tag1_from_cache==tag_from_cpu)||(tag2_from_cache==tag_from_cpu)) && (cur_stat==RUN) && (valid1_from_cache||valid2_from_cache));
wire miss = !hit;

reg    cache_data_ok_reg=0;
assign cache_data_ok = cache_data_ok_reg;
assign cache_addr_ok = cur_stat==RUN;

reg[161:0]      data_to_mem=162'b0;
reg             wea=0;
reg[31:0]       reg4b=0;
wire[63:0]       data_from_rom=0;
assign cache_rdata=hit?((tag1_from_cache==tag_from_cpu)?cache_line[144-ofs_from_cpu-:32]:cache_line[63-ofs_from_cpu-:32]):data_from_rom[63-ofs_from_cpu-:32];

wire tag_match_flag=(tag1_from_cache==tag_from_cpu)||(tag2_from_cache==tag_from_cpu);


reg axiOver;

reg[6:0]        initCnt=0;
wire initEnd=(initCnt==31);
// 复位
always @(posedge clk) begin
        if(cur_stat==RESETN) initCnt<=initCnt+1;
        else if(initEnd) initCnt<=0;
        else initCnt<=initCnt;
end


// DFA
always @(posedge clk or negedge resetn) begin
    if(!resetn) cur_stat<=RESETN;
    else        cur_stat<=next_stat;
end

always@(*)begin
    case (cur_stat)
        IDLE:   begin 
                next_stat=RUN;
                cache_data_ok_reg=0;
                replaceOver=0;   
                end
        RUN:    if(hit&&cpu_req) begin//握手成功
                next_stat=FINISH;
                cache_data_ok_reg=0;
                replaceOver=0;
                end
                else if(cpu_req&&miss) begin // miss
                        next_stat=SEL_WAY;
                        cache_data_ok_reg=0;
                        replaceOver=0;
                end
                else begin 
                        next_stat=RUN;
                        cache_data_ok_reg=0;
                        replaceOver=0;
                end

        SEL_WAY:begin 
                next_stat=MISS;
                cache_data_ok_reg=0;
                replaceOver=0;
                end

        MISS:   
                begin
                next_stat=REFILL;
                cache_data_ok_reg=0;
                replaceOver=1;
                end

        REFILL: begin 
                next_stat=REFILL2;
                cache_data_ok_reg=0;
                replaceOver=1;
                end
        REFILL2:begin 
                next_stat=FINISH;
                cache_data_ok_reg=0;
                replaceOver=0;
                end
        RESETN: if(initEnd) begin 
                next_stat=IDLE;
                cache_data_ok_reg=0;
                replaceOver=0;
                end
                else begin 
                next_stat=RESETN;
                cache_data_ok_reg=0;
                replaceOver=0;
                end
    FINISH:    begin
                next_stat=IDLE;
                cache_data_ok_reg=1;//持续两个周期?
                replaceOver=0;
                end
        // default: next_stat=next_stat;
    endcase
end
// 读命中,读时序
// HERE with A BUG TODO

// 给存储器的地址, 理论上只有命中了之后才会执行,


cache_mem mem(
    .clka   (clk            ),
    .addra  (idx_from_cpu   ),
    .dina   (data_to_mem    ),
    .wea    (wea            ),
    .douta  (cache_line     )
);

/********************************
*这里处理缺失的相关处理
*********************************/
reg free_way=0;
//LRU
generate
        genvar i;
        for(i=0;i<2047;i=i+1)begin:lru_generator
        always @(negedge resetn) begin
                if(!resetn)begin
                LRU[i]<=2'b0;
                end else if(cur_stat==RUN&&next_stat==FINISH)begin
                        if(i==idx_from_cpu) LRU[i]<=(tag1_from_cache==tag_from_cpu)?2'b10:2'b01;
                        else LRU[i]<=LRU[i];
                end
        end
        end
endgenerate
always @(negedge resetn or posedge clk) begin
        if(!resetn)begin
                free_way<=0;
        end else if(cur_stat==SEL_WAY)begin
                free_way<=(LRU[idx_from_cpu][1]==0);
        end else if(cur_stat==RUN&&next_stat==FINISH)begin
                free_way<=0;
        end else free_way<=free_way;
end

/**
*将从rom中读取的数据写入mem
*/
always @(posedge clk) begin
        if(cur_stat==REFILL&&next_stat==REFILL2)begin
                wea<=1;
                data_to_mem<=data_to_mem;
        end
        else if(cur_stat==MISS&&next_stat==REFILL)begin
                wea<=0;
                data_to_mem<=free_way? {cache_line[161:81], 1'b1,tag_from_cpu[15:0],data_from_rom[63:0]}:{1'b1,tag_from_cpu[15:0],data_from_rom[63:0],cache_line[80:0]};
        end
        else begin
                wea<=0;
                data_to_mem<=0;
        end
end
/*
*REFILL TODO
*/


main_mem1 rom(
        .clka   (clk          ),
        .addra  (tag_from_cpu  ),
        // .ena    (replaceOver  ),
        .douta  (data_from_rom)
);
endmodule

似乎和时序没有关系?