1

Our assignment is to build a rudimentary single-cycle CPU in Verilog, but I'm not getting even more fundamental modules of it correct. For instance, to test the Instruction Memory module, we've been given a text file "hw3Test.txt" with instructions in hex, and I'm trying to slurp that into the IM.

00221820
AC010000
8C240000
10210001
00001820
00411822

When I run a testbench, I see that the only instructions that get into memory are the second, third, and fourth lines. Here's the IM module:

module IM(addr, clk, inst);

   input [31:0] addr;
   input clk;
   output reg [31:0] inst;


   reg [31:0] mem [255:0];
   initial begin
          $readmemh("hw3Test.txt", mem);
   end
   always @( posedge clk) begin
          inst=mem[addr[31:2]];
   end
endmodule

And the testbench:

module imtest;
    // Inputs
    reg [31:0] addr;
    reg clk;
    // Outputs
    wire [31:0] inst;
    // Instantiate the Unit Under Test (UUT)
    IM uut (
        .addr(addr), 
        .clk(clk), 
        .inst(inst)
    );
    initial begin
        // Initialize Inputs
        addr = 0;
        clk = 0;
        // Wait 100 ns for global reset to finish
        #100;
        // Add stimulus here
        clk = 0;
        addr = 0;
        #100;
        forever begin
            #20;
            clk = ~clk;
            addr = addr + 4;
        end 
    end      
endmodule

I'm also not sure I'm even getting the PC-to-IM module correct, because aside from the initialized values, everything but the rst and clk signals show no valid values. Can anyone point out where I'm going wrong?

module pc_im(
    // Inputs
    rst, clk, PCin,

    // Outputs
    inst, PCout
    );

    input clk, rst;
    input [31:0] PCin;
    output reg [31:0] inst;
    output reg [31:0] PCout;

    PC mypc (
        .clk(clk),
        .rst(rst),
        .PCin(PCin),
        .PCout(PCout)
    );

    IM myim(
        .clk(clk),
        .addr(PCout),
        .inst(inst)
    );

endmodule

Here's the PC.v module:

module PC(rst, clk, PCin, PCout);
    input clk, rst;
    input [31:0] PCin;
    output reg [31:0] PCout;

    always @(posedge clk) begin
        if (rst) PCout <= 0;
        else PCout <= PCin + 4;
    end

endmodule

And finally, the testbench:

module pcimtest;

    // Inputs
    reg rst;
    reg clk;
    reg [31:0] PCin;

    // Outputs
    wire [31:0] inst;
    wire [31:0] PCout;

    // Instantiate the Unit Under Test (UUT)
    pc_im uut (
        .rst(rst), 
        .clk(clk), 
        .PCin(PCin), 
        // Outputs
        .inst(inst), 
        .PCout(PCout)
    );

    initial begin
        // Initialize Inputs
        rst = 1;
        clk = 0;
        PCin = 0;

        // Wait 100 ns for global reset to finish
        #100;
        rst = 0;

        forever begin
            #100;
            clk <= ~clk;
            PCin <= PCout;
        end

        // Add stimulus here

    end

endmodule
4

1 回答 1

2

以下是一些看起来可疑的事情。

问题 1

通常最好在用于推断寄存器的块中使用非阻塞分配。

即改变

always @( posedge clk) begin
      inst=mem[addr[31:2]];
end

always @( posedge clk) begin
      inst<=mem[addr[31:2]];
end

问题 2

您在每个时钟周期更改信号两次,一次在下降沿,一次在上升沿。

改变:

    forever begin
        #20;
        clk = ~clk;
        addr = addr + 4;
    end 

    forever begin
        #20;
        clk = 1;
        #20;
        clk = 0;
        addr = addr + 4;
    end

问题 3

您正在使用同步复位,但在复位期间不提供时钟。

考虑代码

always @(posedge clk) begin
    if (rst) PCout <= 0;
    else PCout <= PCin + 4;
end

该模块仅在正时钟沿激活。但是,您在时钟暂停时将复位设置为高电平,因此不会发生复位。

改变

    rst = 1;
    clk = 0;
    PCin = 0;

    // Wait 100 ns for global reset to finish
    #100;

    rst = 1;
    clk = 0;
    PCin = 0;
    #20
    clk = 1;
    #20
    clk = 0;

    // Wait 100 ns for global reset to finish
    #100;
于 2013-06-02T19:14:01.243 回答