为什么读不到内存内容? - verilog数字系统设计

Why the memory content is not read? - verilog digital system design

我创建了一个由两个时钟 SRAM 组成的微系统,一个用于存储指令代码,另一个用于存储一些输出值。指令SRAM有一个名为“用户”的接口模块,它提供了一种简化写入过程的机制,因此,在内存中写入数据时,无需指定必须存储这些指令的相应内存地址。类似地,当从第二个SRAM读取数据时,由于有了“显示”模块,因此无需指定从中提取数据的相应内存地址。更具体地说,当在指令存储器中写入数据时,计数器在每次写入后递增地址指针,而第二存储器有另一个计数器在每次读取后递增地址指针值。当一个人试图从指令存储器中读取信息时,他们必须指定应该从中读取数据的存储器地址,并且正如预期的那样,当一个人试图将信息写入输出存储器时,他们必须指定其中的存储器地址应该写入数据。此外,微系统有一个自动机,它从指令存储器中获取输入数据并对其进行处理。处理完信息后,自动机将一些输出值存储在输出存储器中。我在模拟时遇到一个问题,因为显然无法看到从 SRAM 存储器读取的值,即 rd_data_instrucions,因此,既无法找到自动机的输入值“in”,也无法找到输出值,只要它们取决于从第一个 SRAM 读取的数据。我在下面发布了代码和图表。

//wishbone module
module wishbone(
    input clk,rst,
    output reg [2:0]in,
    output reg wr_en_instructions,wr_en_display,
    input [2:0] wr_data_instructions,//created for usr, in order to make possible to write data
    output reg [3:0] wr_data_display,
    output [2:0] rd_data_instructions,
    output [3:0] rd_data_display,//created for user, in order to make possible the display
    output [12:0]o
);

reg [15:0] pointer_instructions,pointer_display;

initial wr_en_instructions = 1'b1;//?

control_unit i0(.clk(clk),.rst(rst),.in(in),.o(o));
user i1(.clk(clk),.wr_en(wr_en_instructions),.address_in(pointer_instructions),.wr_data(wr_data_instructions),.rd_data(rd_data_instructions));
display i2(.clk(clk),.wr_en(wr_en_display),.address_in(pointer_display),.wr_data(wr_data_display),.rd_data(rd_data_display));
integer i = 0;
always @ * begin
    wr_en_display = ~wr_en_instructions;
end
always @(posedge clk) begin
    if(rst) begin
        wr_en_instructions <= 1'b1;
        pointer_instructions <= 16'd0;
        pointer_display <= 16'd0;
    end
    else begin
        if(wr_en_instructions) begin
            if(wr_data_instructions[2] == 1'b1) begin
                pointer_instructions <= 16'd0;
                pointer_display <= 16'd0;
                wr_en_instructions <= 1'b0;
            end
        end
        else begin
            in <= rd_data_instructions;
            pointer_instructions <= pointer_instructions + 1;
            if(rd_data_instructions == 3'b010) begin
                wr_data_display <= o;
                pointer_display <= pointer_display + 1;
            end
            else if(rd_data_instructions == 3'b100) begin
               wr_en_instructions <= 1'b1;
            end
        end
    end
end

endmodule

//testbench for top module
module wishbone_tb(
    output reg clk,rst,
    output [2:0]in,
    output wr_en_instructions,wr_en_display,
    output reg [2:0] wr_data_instructions,//created for usr, in order to make possible to write data
    output [3:0] wr_data_display,
    output [2:0] rd_data_instructions,
    output [3:0] rd_data_display,//created for user, in order to make possible the display
    output [12:0]o
);

wishbone cut(
    .clk(clk),.rst(rst),
    .in(in),
    .wr_en_instructions(wr_en_instructions),.wr_en_display(wr_en_display),
    .wr_data_instructions(wr_data_instructions),
    .wr_data_display(wr_data_display),
    .rd_data_instructions(rd_data_instructions),
    .rd_data_display(rd_data_display),
    .o(o)
);

initial $dumpvars(0,wishbone_tb);

initial begin
    clk = 1'b1;
    repeat (600000)
    #100 clk = ~clk;
end

initial begin
    rst = 1'b1;
    #400 rst = 1'b0;
end

initial begin
    wr_data_instructions = 3'd1;
    #3000400 wr_data_instructions = 3'd2;
    #1000000 wr_data_instructions = 3'd1;
    #3000000 wr_data_instructions = 3'd0;
    #2000000 wr_data_instructions = 3'd3;
    #1000000 wr_data_instructions = 3'd1;
    #3000000 wr_data_instructions = 3'd4;//halt
end

endmodule

//code for the first memory:

//stores instructions
module sram_1port_instructions(
    input clk,//clocked memory
    input wr_en,//when high, data is writeen, otherwise is read
    input [15:0] address_in,//suppose timer cannot count more than 13ms
    input [2:0] wr_data,//3 bit instructions
    output reg [2:0] rd_data
);

reg [2:0] memory [2 ** 15 - 1 : 0];

always @(posedge clk) begin
    if(wr_en) memory[address_in] <= wr_data;
    else rd_data <= memory[address_in];
end

endmodule

//user interface designed for the first memory
module user(
    input clk,
    input wr_en,
    input [15:0] address_in,
    input [2:0] wr_data,
    output [2:0] rd_data
);

reg [15:0] pointer,address;

initial pointer = 16'd0;

sram_1port_instructions i0(.clk(clk),.wr_en(wr_en),.address_in(address),.wr_data(wr_data),.rd_data(rd_data));

always @(posedge clk) begin
    if(wr_en) begin
        address <= pointer;
        pointer <= pointer + 1;
    end 
    else begin
        address <= address_in;
        pointer <= 16'd0;
    end
end

endmodule

//user tb
module user_tb(
    output reg clk, wr_en, 
    output reg [15:0] address_in,
    output reg [2:0] wr_data,
    output [2:0] rd_data
);

user cut(.clk(clk),.wr_en(wr_en),.address_in(address_in),.wr_data(wr_data),.rd_data(rd_data));

initial $dumpvars(0,user_tb);

initial begin
    clk = 1'd1;
    repeat (2000)
    #100 clk = ~clk;
end

initial begin
    wr_en = 1'd1;
    #100000 wr_en = 1'd0;
end

integer i;

initial begin
    wr_data = 3'd0;
    for(i = 1;i < 500;i = i + 1) begin
    #200 wr_data = i;
    end
end

initial begin
    address_in = 16'd0;
    #100000 address_in = 16'd0;
    for(i = 1;i < 500;i = i + 1) begin
    #200 address_in = i;
    end
end

endmodule

//code for the second memory:

//stores output data
module sram_1port_data(
    input clk,//clocked memory
    input wr_en,//when high, data is written, otherwise is read
    input [15:0] address_in,//suppose timer cannout count more than 13ms
    input [3:0] wr_data,//memory does not sotre values greater than 13(ms)
    output reg [3:0] rd_data
);

reg [3:0] memory [2 ** 15 - 1 : 0];

always @(posedge clk) begin
    if(wr_en) memory[address_in] <= wr_data;
    else rd_data <= memory[address_in];
end

endmodule

//display interfacedesigned for the second memory
module display(
    input clk,
    input wr_en,
    input [15:0] address_in,
    input [3:0] wr_data,
    output [3:0] rd_data
);

reg [15:0] pointer,address;

initial pointer = 16'd0;

sram_1port_data i0(.clk(clk),.wr_en(wr_en),.address_in(address),.wr_data(wr_data),.rd_data(rd_data));

always @(posedge clk) begin
    if(!wr_en) begin
        address <= pointer;
        pointer <= pointer + 1;
    end 
    else begin
        address <= address_in;
        pointer <= 16'd0;
    end
end

endmodule

//tb for display
module display_tb(
    output reg clk,
    output reg wr_en,
    output reg [15:0] address_in,
    output reg [3:0] wr_data,
    output [3:0] rd_data
);

display i0(.clk(clk),.wr_en(wr_en),.address_in(address_in),.wr_data(wr_data),.rd_data(rd_data));

initial $dumpvars(0,display_tb);

initial begin
    clk = 1'd1;
    repeat (2000)
    #100 clk = ~clk;
end

initial begin
    wr_en = 1'd1;
    #100000 wr_en = 1'd0;
end

integer i;

initial begin
    wr_data = 3'd0;
    address_in = 16'd0;
    for(i = 1;i < 500;i = i + 1) begin
    #200;
    wr_data = i;
    address_in = i;
    end
end

endmodule

//code for the control unit:

//control unit
module control_unit(
    input clk,rst,
    input [2:0]in,
    output [12:0]o
);

wire f,g;

automaton i0(.clk(clk),.rst(rst),.in(in),.clr(f),.en(g));
circuit i1(.clk(clk),.clr(f),.en(g),.o(o));

endmodule

//code for automaton:

//atuomaton
module automaton(
    input clk,rst,
    input [2:0]in,
    output reg clr,en
);

localparam S0_ST = 2'b00;
localparam S1_ST = 2'b01;
localparam S2_ST = 2'b10;

reg [1:0] st_reg,st_nxt;

always @ * begin
    case(st_reg)
        S0_ST: if(!in[1]) st_nxt = S0_ST;
               else if(in[0]) st_nxt = S2_ST;
               else st_nxt = S1_ST;
        S1_ST: if(!in[0]) st_nxt = S1_ST;
               else if(in[1]) st_nxt = S2_ST;
               else st_nxt = S0_ST;
        S2_ST: if(in == 2'd1) st_nxt = S0_ST;
               else st_nxt = S2_ST; 
    endcase
end

always @ * begin
    case(st_reg)
        S0_ST: {clr,en} = 2'd1; 
        S1_ST: {clr,en} = 2'd0;
        S2_ST: clr = 1'd1;
    endcase
end

always @(posedge clk) begin
    if(rst) st_reg <= S2_ST;
    else st_reg <= st_nxt;
end

endmodule

//code for circuit:

//circuit
module circuit(
    input clk,clr,en,
    output [12:0] o
);

wire f;

generator i0(.clk(clk),.clr(clr),.en(en),.o(f));
counter i1(.clk(clk),.clr(clr),.en(f),.o(o));

endmodule

//code for counter:

//counter
module counter(
    input clk,clr,en,
    output reg [12:0] o
);

reg [12:0] st_nxt;

always @ (posedge clk) begin
    if(clr) o <= 13'd0;
    else o <= st_nxt;
end

always @ *
    if(en) st_nxt = o + 1;
    else st_nxt = o;

endmodule

//code for generator:

//pulse generator
module generator(
    input clk,clr,en,
    output reg o
);

reg [12:0] st_reg,st_nxt;

always @(posedge clk) begin
    if(clr) st_reg <= 13'd0;
    else st_reg <= st_nxt;
end

always @ * begin
    if(en) begin
        if(st_reg == 13'd4999) begin
            st_nxt = 13'd0;
            o = 1'b1;
        end
        else begin
            st_nxt = st_reg + 1;
            o = 1'b0;
        end
    end
    else begin
        if(st_reg == 13'd4999) begin
            st_nxt = 13'd0;
            o = 1'b0;
        end
        else begin
            st_nxt = st_reg;
            o = 1'b0;
        end
    end
end

endmodule

当您从地址 0x8001 读取时,这超出了您的内存大小限制。你可以增加你的记忆力。变化:

reg [2:0] memory [2 ** 15 - 1 : 0];

至:

reg [2:0] memory [2 ** 16 - 1 : 0];

当您从地址 0x8001 读取时,这会删除未知数 (X)。

或者,如果您不想扩大内存,请确保限制您的地址。