我在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
答案 0 :(得分:3)
您没有告诉Verilog该指令是二进制数,因此它将其解释为十进制数。你需要这个:
instruction = 32'b00100000000010000000000000000001;
#100
//add $8, $8, $8
instruction = 32'b00000001000010000100000000100000;
此外,您不应将assign
语句放在always
块中。如果您希望这些是寄存器,请使用verilog非阻塞赋值运算符<=
而不是assign
语句。或者如果你想让它们成为电线,你可以让assign
将它们移到总是阻挡之外。
另外,尽量不要混淆posedge和negedge。坚持假装。