将线总线传递给模块时,位会发生变化

时间:2014-05-01 03:30:19

标签: module simulation verilog processor

我在Verilog中模拟MIPS处理器的课程,我遇到了最奇怪的问题。当我将指令(32位总线)传递给主模块时,它会以某种方式发生变化。例如,当我将指令设置为00100000000010000000000000000001时,在模块内部我打印出指令为00101001111010000000000000000001,这显然是不同的。没有内部模块直接与内部指令交互,因为它只是被分解成各种其他部分。只需将总线传递给模块,可能导致位变化的原因是什么?

这是主处理器代码和测试平台:

 module SingleCycleProc(clk, instruction);
// input    Reset_L, clk;
// input [31:0] startPC;
// output [31:0] dmemOut;
// reg [31:0] dmemOut;

input clk;
input [31:0] instruction;

//Fetch instruction and get new program counter
//wire [31:0] instruction, PC_out;
//reg [31:0] PC;
//InstrMem(PC, instruction);
wire [31:0] sign_extended;

//ProgramCounter(PC, PC_out, zero, sign_extended);


//Break up instruction into basic components
reg [5:0] opcode;
reg [5:0] funct;
reg [15:0] immediate;
reg [25:0] address;

reg [4:0] RSAddr, RTAddr, RDAddr;
wire [31:0] RSData, RTData, RDData;


SIGN_EXTEND(immediate, sign_extended);

//Generate CPU and ALU control bits
wire regDST, ALUSrc, memToReg, regWrite, memRead, memWrite, branch;
wire [1:0] ALUOp;
CPU_Control_unit(opcode, regDST, ALUSrc, memToReg, regWrite, memRead, memWrite, branch, ALUOp);

wire [3:0] alu_control;
ALU_Control_Unit(alu_control, funct, ALUOp);

//Generate the input addresses to the regfile, and retrieve data from regfile
wire [4:0] out;
MUX5_2to1(RTAddr, RDAddr, regDST, out);


RegFile(RSData, RTData, RSAddr, RTAddr, RDData, RDAddr, regWrite, clk);

//select intputs to the ALU and do calculation
wire [31:0] alu_in1;
MUX32_2to1(RTData, sign_extended, ALUSrc, alu_in1);

wire [31:0] alu_out;
wire overflow, cin, cout, zero, PCSrc;
wire [31:0] result;
and(PCSrc, branch, zero);
ALU_behav(RSData, alu_in1, alu_control, result, overflow, cin, cout, zero);

wire [31:0] memReadData;
DataMem(result, clk, memRead, memWrite, RTData, memReadData);
MUX32_2to1(result, memReadData, memToReg, RDData);

always @(negedge clk) begin
    // assign PC = PC + 4;
    assign opcode = instruction[31:26];
    assign funct = instruction[5:0];
    assign immediate = instruction[15:0];
    assign address = instruction[25:0];
    assign RSAddr = instruction[25:21];
    assign RTAddr = instruction[20:16];
    assign RDAddr = instruction[15:11];
    // assign dmemOut = RDData;
end

// always @(~Reset_L) assign PC = startPC;

//Monitor changes in the program counter
// always @(PC)
    // #10 $display($time," PC=%d Instr: op=%d rs=%d rt=%d rd=%d imm16=%d funct=%d",
    // PC,instruction[31:26],instruction[25:21],instruction[20:16],instruction[15:11],instruction[15:0],instruction[5:0]);



//Monitors memory writes
always @(clk)
    begin
        #1 $display($time, " clk=%b instruction=%b", clk, instruction);
    // #1 $display($time " clk=%b opcode=%b", clk, opcode);
    // #1 $display($time,
        // " clock=%b RSAddr=%d RSData=%d RTAddr=%d RTData=%d",
        // clk,        RSAddr,   RSData,   RTAddr,   RTData);
    // #1 $display($time, " clk=%b regDST=%b regWrite=%b ALUSrc=%b memRead=%b memWrite=%b memToReg=%b branch=%b ALUOp=%b ", clk, regDST, regWrite, ALUSrc, memRead, memWrite, memToReg, branch, ALUOp);
end

endmodule

module testCPU(clk, Reset_L, startPC, testData);
input clk;
input [31:0] testData;
output Reset_L;
output [31:0] startPC;
reg  Reset_L;
reg [31:0] startPC;

reg [31:0] instruction;
SingleCycleProc(clk, instruction);

initial begin
    // Your program 1
    // Reset_L = 0;  startPC = 0 * 4;
    // #101 // insures reset is asserted across negative clock edge
    // Reset_L = 1;
    // #10000; // allow enough time for program 1 to run to completion
    // Reset_L = 0;
    // #1 $display("Program 1: Result: %d", testData);

    //addi $8, $0, 1
    instruction = 00100000000010000000000000000001;
    #100
    //add $8, $8, $8
    instruction = 00000001000010000100000000100000;
    #100


  $finish;
end
endmodule // testCPU

module TopProcessor;
wire reset, clk, Reset_L;
wire [31:0] startPC;
wire [31:0] testData;

m555 system_clock(clk);
testCPU(clk, Reset_L, startPC, testData);
//SingleCycleProc SSProc(clk, Reset_L, startPC, testData);


endmodule // TopProcessor

1 个答案:

答案 0 :(得分:3)

您没有告诉Verilog该指令是二进制数,因此它将其解释为十进制数。你需要这个:

instruction = 32'b00100000000010000000000000000001;
#100
//add $8, $8, $8
instruction = 32'b00000001000010000100000000100000;

此外,您不应将assign语句放在always块中。如果您希望这些是寄存器,请使用verilog非阻塞赋值运算符<=而不是assign语句。或者如果你想让它们成为电线,你可以让assign将它们移到总是阻挡之外。

另外,尽量不要混淆posedge和negedge。坚持假装。