2014-05-01 5 views
0

클래스에 대해 Verilog에서 MIPS 프로세서를 시뮬레이션 중이며 가장 이상한 문제가 있습니다. 주 모듈에 명령어 (32 비트 버스)를 전달하면 어떻게 든 바뀝니다. 예를 들어, 명령을 00100000000010000000000000000001로 설정하면 모듈 내에서 분명히 다른 00101001111010000000000000000001과 같은 명령어를 인쇄합니다. 내부 모듈은 내부 명령어와 직접 상호 작용하지 않습니다. 단지 다른 여러 부분으로 분해되기 때문입니다. 버스를 모듈에 전달하여 비트가 변경되는 원인은 무엇입니까?와이어 버스를 모듈에 연결할 때 비트가 변경됩니다.

다음은 메인 프로세서 코드와 테스트 벤치입니다 : 당신은 명령이 진수임을 Verilog를 이야기하지 않는

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

주석이 너무 많습니다. 코드를 정리하고 다시 붙여 넣을 수 있습니까? 독자가 더 쉽게 사용할 수 있습니다. – chitranna

답변

3

, 그래서 진수로 해석된다.

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

또한, 당신이 always 블록 내부에 assign 문을 넣어해서는 안 : 당신이 필요합니다. 이들을 레지스터로 사용하려면 assign 문 대신 Verilog 비 차단 할당 연산자 <=을 사용하십시오. 또는 와이어가되도록하려면 assign을 항상 블록 외부로 이동 시키십시오.

또한 posedge와 negedge를 섞어 사용하지 마십시오. posedge에 집착하십시오.