尝试在Verilog中的单周期CPU中调试程序计数器/指令存储器模块

时间:2013-06-02 19:05:04

标签: verilog

我们的任务是在Verilog中构建一个基本的单循环CPU,但我没有得到更正确的基本模块。例如,为了测试指令存储器模块,我们已经给出了一个文本文件“hw3Test.txt”,其中包含十六进制指令,我正试图将其粘贴到IM中。

00221820
AC010000
8C240000
10210001
00001820
00411822

当我运行测试平台时,我发现进入内存的唯一指令是第二,第三和第四行。这是IM模块:

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

测试平台:

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

我也不确定我是否正确使用PC-to-IM模块,因为除了初始值之外,除了rst和clk信号之外的所有信号都没有显示有效值。谁能指出我哪里出错?

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

这是PC.v模块:

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

最后,测试平台:

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

1 个答案:

答案 0 :(得分: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;