Question

I am simulating a MIPS processor in Verilog for class, I am having the strangest problem. When I pass an instruction (a 32-bit bus) to the main module, it somehow changes. For example, when I set the instruction to 00100000000010000000000000000001, inside the module I print out the instruction as 00101001111010000000000000000001, which is clearly different. No inner modules directly interact with the inside instruction, as it just gets broken up into various other parts. What could be causing the bits to change simply by passing the bus to a module?

Here is the main processor code and test bench:

 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
Était-ce utile?

La solution

You are not telling Verilog that the instruction is a binary number, so it is interpreting it as decimal. You need this:

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

Additionally, you should not be putting assign statements inside an always block. If you want these to be registers, use the verilog non-blocking assignment operator <= rather than the assign statement. Or if you want them to be wires, you can keep the assign just move them outside the always block.

Also, try not to mix posedge and negedge. Stick to posedge.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top