在计算机体系结构中,指令可以分为不同的类型,通常有R-type、I-type和J-type指令。
R-type指令(Register-type指令):
R-type指令通常用于执行寄存器之间的操作,如加法、减法、逻辑运算等。这些指令通常涉及两个寄存器的操作,其中一个寄存器用于存储操作的结果。R-type指令的操作码字段用于指示要执行的具体操作,例如加法(ADD)或逻辑与(AND)。
I-type指令(Immediate-type指令):
I-type指令通常用于执行包含立即数(常数)的操作,这些立即数与寄存器之间执行某种操作,如加载、存储、分支等。I-type指令的操作码字段指示要执行的操作类型,并包括一个立即数字段,该字段包含要用于操作的常数值。
J-type指令(Jump-type指令):
J-type指令通常用于分支和跳转操作,例如跳转到程序的某个地址或执行子例程。这些指令通常不涉及寄存器操作,而是直接影响程序计数器(PC),用于改变程序的控制流。J-type指令的操作码字段用于指示分支或跳转的类型。
这些不同的指令类型在计算机体系结构中有不同的编码和操作。多周期CPU设计需要考虑如何正确解码和执行这些不同类型的指令。通常,每种指令类型都需要一个不同的控制路径来执行相应的操作。在多周期CPU中,不同的指令类型可能需要不同数量的时钟周期来完成。因此,在设计多周期CPU时,要考虑如何有效地处理这些不同类型的指令。
“Clock skew”(时钟偏移)是指在一个同步电路中,由于信号传输延迟或其他因素导致时钟信号在不同部分的电路中到达的时间不同。时钟信号用于同步各个电路元件的操作,因此时钟偏移可能导致电路的不正常功能或性能问题。
时钟偏移可能导致以下问题:
数据不稳定性:如果时钟信号到达某个电路元件的时间比其他元件晚,可能会导致数据在电路中不稳定。这可能导致数据损坏或不一致。
时序冲突:时钟偏移可能导致时序冲突,即在某些情况下,数据信号在时钟信号的上升沿或下降沿之间变化,而不是在特定的时钟沿上稳定。这会使电路操作不可预测。
性能问题:时钟偏移还可能导致电路性能问题,因为某些电路元件可能需要等待时钟信号的到达,从而降低了电路的时钟频率。
时钟偏移可以由多种因素引起,包括信号传输线的长度、电路板布线的不均匀性、温度变化等。为了解决时钟偏移问题,通常采取以下方法:
时钟缓冲器(Clock Buffers):时钟缓冲器可以帮助均衡时钟信号的到达时间,确保它们尽量同时到达各个电路元件。
时钟网络设计:精心设计时钟网络,考虑信号传播时间,以最小化时钟偏移。
时序分析工具:使用时序分析工具来检测潜在的时钟偏移问题,并对电路进行优化以解决这些问题。
时钟同步协议:在多个时钟域之间进行数据传输时,使用时钟同步协议,确保数据在不同时钟域之间正确同步。
时钟偏移是复杂的电子设计中需要考虑的一个重要方面,特别是在高性能或高速电路中。处理时钟偏移问题需要深入了解电子设计和时序分析的原理。
(1) 状态机第一段,时序逻辑,非阻塞赋值,传递寄存器的状态。
(2) 状态机第二段,组合逻辑,阻塞赋值,根据当前状态和当前输入,确定下一个状态机的状态。
(3) 状态机第三代,时序逻辑,非阻塞赋值,因为是 Mealy 型状态机,根据当前状态和当前输入,确定输出信号。
`ifndef MULTI_CYCLE_CPU_H
//alu
`define MULTI_CYCLE_CPU_H
`define Add 2'b00
`define Sub 2'b01
`define Ori 2'b10
//ct`define l
`define Ifetch 4'd1
`define Rfetch_Decode 4'd2
`define BrComplete 4'd3
`define OriExec 4'd4
`define RExec 4'd5
`define AdrCal 4'd6
`define OriFinish 4'd7
`define Rfinish 4'd8
`define SWMem 4'd9
`define LWmem 4'd10
`define LWwr 4'd11
//if`define
`define RType 6'b000000
`define BEQ 6'b000100
`define ORI 6'b001101
`define SW 6'b101011
`define LW 6'b100011
`define JAL 6'b000011
`endif
`include "multi_cycle_cpu.h"
//`define Add 2'b00
module Alu(
input [31:0] A,
input [31:0] B,
input [1:0] ALUOp, //2位ALU控制信号
output reg [31:0] ALUOut,
output reg zero //零标志位
);
//reg [31:0] ALUOut;
always@(A,B,ALUOp) begin
case(ALUOp)//决定ALU操作
`Add:
begin
ALUOut <= A+B;
end
`Sub:
begin
ALUOut <= A-B;
end
`Ori:
begin
ALUOut <= A|B;
end
default:
begin
ALUOut <= 32'h0000_0000;
//$display($time,,"(ALU)(DEFAULT)");
end
endcase
end
always @(A,B) begin
if (A == B) zero <= 1'b1;
else zero <= 1'b1;
end
endmodule
`include "multi_cycle_cpu.h"
module ctrl(
input clk,
input reset,
input [5:0] opcode,
output reg PCWr,
output reg PCWrCond,
output reg IorD,
output reg MemWr,
output reg IRWr,
output reg RegDst,
output reg RegWr,
output reg ALUSelA,
output reg [1:0] ALUSelB,
output reg PCSrc,
output reg BrWr,
output reg [1:0] ExtOp,
output reg MemtoReg,
output reg [1:0] ALUOp
);
reg [3:0] CurState,NextState;
always @(posedge clk or posedge reset) begin
if (reset) begin
CurState <= 4'b0000; // 初始化状态
end else begin
CurState <= NextState;
end
end
always @(CurState,opcode,NextState) begin
case(CurState)
4'b0000: NextState <= `Ifetch;
`Ifetch: begin
NextState <= `Rfetch_Decode;
end
`Rfetch_Decode:begin
if (opcode == `BEQ) begin
NextState <= `BrComplete;
end else if (opcode == `ORI) begin
NextState <= `OriExec;
end else if (opcode == `RType) begin
NextState <= `RExec;
end else if (opcode == `LW || opcode == `SW) begin
NextState <= `AdrCal;
end
end
`BrComplete:
NextState <= `Ifetch;
`OriExec:
NextState <= `OriFinish;
`RExec:
NextState <= `Rfinish;
`AdrCal: begin
if (opcode == `SW)
NextState <= `SWMem;
else if(opcode == `LW)
NextState <= `LWmem;
end
`OriFinish:
NextState <= `Ifetch;
`Rfinish:
NextState <= `Ifetch;
`SWMem:
NextState <= `Ifetch;
`LWmem:
NextState <= `LWwr;
`LWwr:
NextState <= `Ifetch;
default:
NextState <= CurState;
endcase
end
always @(posedge reset) begin
if (reset) begin
ALUOp <= 2'b00;
PCWr <= 1'b0;
PCWrCond <= 1'b0;
IorD <= 1'b0;
MemWr <= 1'b0;
IRWr <= 1'b0;
RegDst <= 1'b0;
RegWr <= 1'b0;
ALUSelA <= 1'b0;
ALUSelB <= 2'b00;
PCSrc <= 1'b0;
BrWr <= 1'b0;
ExtOp <= 2'b00;
MemtoReg <= 1'b0;
BrWr <= 1'b0;
end
end
always @(CurState) begin
case(CurState)
`Ifetch: begin
ALUOp <= `Add;
PCWr <= 1'b1;
MemWr <= 1'b0;
RegWr <= 1'b0;
ALUSelA <= 1'b0;
ALUSelB <= 2'b00;
PCSrc <= 1'b0;
IRWr <= 1'b1;
PCWrCond <= 1'bx;
IorD <= 1'b0;
RegDst <= 1'bx;
MemtoReg <= 1'bx;
BrWr <= 1'b0;
ExtOp <= 2'b00;
end
`Rfetch_Decode: begin
PCWr <= 1'b0;
PCWrCond <= 1'b0;
MemWr <= 1'b0;
IRWr <= 1'b0;
RegWr <= 1'b0;
ALUOp <= `Add;
BrWr <= 1'b1;
ExtOp <= 1'b1;
ALUSelA <= 1'b0;
ALUSelB <= 2'b10;
RegDst <= 1'bx;
PCSrc <= 1'bx;
IorD <= 1'bx;
MemtoReg <= 1'bx;
BrWr <= 1'b0;
end
`BrComplete: begin
PCWr <= 1'b0;
MemWr <= 1'b0;
IRWr <= 1'b0;
RegWr <= 1'b0;
ALUOp <= `Sub;
ALUSelB <= 2'b01;
PCWrCond <= 1'b1;
ALUSelA <= 1'b1;
PCSrc <= 1'b1;
IorD <= 1'bx;
MemtoReg <= 1'bx;
RegDst <= 1'bx;
ExtOp <= 1'bx;
BrWr <= 1'b0;
end
`OriExec: begin
PCWr <= 1'b0;
MemWr <= 1'b0;
IRWr <= 1'b0;
RegDst <= 1'b0;
RegWr <= 1'b0;
ALUOp <= `Ori;
ALUSelA <= 1'b1;
ALUSelB <= 2'b11;
MemtoReg <= 1'bx;
IorD <= 1'bx;
PCSrc <= 1'bx;
PCWrCond <= 1'b0;
BrWr <= 1'b0;
ExtOp <= 2'b00;
end
`RExec: begin
PCWr <= 1'b0;
PCWrCond <= 1'b0;
MemWr <= 1'b0;
RegDst <= 1'b1;
IRWr <= 1'b0;
RegWr <= 1'b0;
ALUSelA <= 1'b1;
ALUSelB <= 2'b01;
ALUOp <= `RType;
PCSrc <= 1'bx;
IorD <= 1'bx;
MemtoReg <= 1'bx;
ExtOp <= 1'bx;
BrWr <= 1'b0;
end
`AdrCal: begin
PCWr <= 1'b0;
MemWr <= 1'b0;
PCWrCond <= 1'b0;
IRWr <= 1'b0;
RegDst <= 1'b0;
RegWr <= 1'b0;
IorD <= 1'b0;
ExtOp <= 1'b1;
ALUSelA <= 1'b1;
ALUSelB <= 2'b11;
ALUOp <= `Add;
MemtoReg <= 1'bx;
PCSrc <= 1'bx;
BrWr <= 1'b0;
end
`OriFinish: begin
PCWr <= 1'b0;
MemWr <= 1'b0;
IRWr <= 1'b0;
RegDst <= 1'b0;
PCWrCond <= 1'b0;
ALUOp <= `Ori;
IorD <= 1'bx;
PCSrc <= 1'bx;
ALUSelB <= 2'b11;
ALUSelA <= 1'b1;
RegWr <= 1'b1;
BrWr <= 1'b0;
ExtOp <= 2'b00;
MemtoReg <= 1'b0;
end
`Rfinish: begin
PCWr <= 1'b0;
PCWrCond <= 1'b0;
MemWr <= 1'b0;
IRWr <= 1'b0;
ALUOp <= `RType;
RegDst <= 1'b1;
RegWr <= 1'b1;
ALUSelA <= 1'b1;
ALUSelB <= 2'b01;
IorD <= 1'bx;
PCSrc <= 1'bx;
ExtOp <= 1'bx;
BrWr <= 1'b0;
MemtoReg <= 1'b0;
end
`SWMem: begin
PCWr <= 1'b0;
PCWrCond <= 1'b0;
IorD <= 1'b0;
IRWr <= 1'b0;
ExtOp <= 1'b1;
MemWr <= 1'b1;
RegWr <= 1'b0;
ALUSelA <= 1'b1;
ALUSelB <= 2'b11;
ALUOp <= `Add;
PCSrc <= 1'bx;
RegDst <= 1'bx;
MemtoReg <= 1'bx;
BrWr <= 1'b0;
end
`LWmem: begin
PCWr <= 1'b0;
PCWrCond <= 1'b0;
MemWr <= 1'b0;
IRWr <= 1'b0;
RegDst <= 1'b0;
RegWr <= 1'b0;
ExtOp <= 1'b1;
ALUSelA <= 1'b1;
IorD <= 1'b1;
ALUSelB <= 2'b11;
ALUOp <= `Add;
MemtoReg <= 1'bx;
PCSrc <= 1'bx;
BrWr <= 1'b0;
end
`LWwr: begin
PCWr <= 1'b0;
PCWrCond <= 1'b0;
MemWr <= 1'b0;
IRWr <= 1'b0;
RegDst <= 1'b0;
ALUSelA <= 1'b1;
RegWr <= 1'b1;
ExtOp <= 1'b1;
MemtoReg <= 1'b1;
ALUSelB <= 2'b11;
ALUOp <= `Add;
PCSrc <= 1'bx;
BrWr <= 1'b0;
IorD <= 1'bx;
end
default: begin
ALUOp <= `Add;
PCWr <= 1'b0;
PCWrCond <= 1'b0;
IorD <= 1'b0;
MemWr <= 1'b0;
IRWr <= 1'b0;
RegDst <= 1'b0;
RegWr <= 1'b0;
ALUSelA <= 1'b0;
ALUSelB <= 2'b00;
PCSrc <= 1'b0;
BrWr <= 1'b0;
ExtOp <= 2'b00;
MemtoReg <= 1'b0;
end
endcase
end
endmodule
module EXT(
input [15:0] Imm16,
input [1 :0] ExtOp,
output reg [31:0] Imm32
);
// wire [1 :0] ExtOp;
always @(ExtOp,Imm16) begin
case (ExtOp)
2'b00:
Imm32 <= {{16{1'b0}},Imm16};
2'b01://符号扩展
Imm32 <= {{16{Imm16[15]}},Imm16};
2'b10://将立即数扩展到高位
Imm32 <= {Imm16,{16{1'b0}}};
default:
Imm32 <= {{16{1'b0}},Imm16};
endcase
end
endmodule
module im_4k( clk,RAdr,WrAdr,MemWr,Din,Dout );
input [11:2] RAdr;
input [11:2] WrAdr;
input MemWr;
input [31:0] Din;
input clk;
output [31:0] Dout;
reg [31:0] imem[1023:0];
always @(posedge clk) begin
if (MemWr) imem[WrAdr] <= Din;
end
assign Dout = imem[RAdr];
endmodule
module IR(
input IRWr,
input clk,
input [31:0] in,
output reg [31:0] IRout
);
always @(posedge clk) begin
if (IRWr)
IRout <= in;
end
endmodule
module mips( clk, reset );
input clk;
input reset;
wire zero ;
wire [31:0] PC ;
wire [31:0] ALUOut ;
// wire [1 :0] ALUOp ;
wire [31:0] pc_im_mux_out;
wire [4 :0] ir_reg_mux_out;
wire [31:0] im_reg_mux_out;
wire [31:0] alu_pc_mux_out;
wire [31:0] reg_alu_mux_out;
wire [31:0] reg_alu_mux2_out;
// wire [31:0] muxout1 ;
wire [31:0] im_dout,dm_dout;
wire [31:0] busA,busB;
wire [31:0] in,IRout;
//wire [31:0] rdata1,rdata2;
wire [31:0] Imm32 ;
wire [2 :0] opcode ;
wire PCWr ;
wire PCWrCond;
wire IorD ;
wire MemWr ;
wire IRWr ;
wire RegDst ;
wire RegWr ;
wire ALUSelA ;
wire [1 :0] ALUSelB ;
wire PCSrc ;
wire BrWr ;
wire [1 :0] ExtOp ;
wire MemtoReg;
wire [1 :0] ALUOp ;
wire [31:0] tar_out ;
PC U_PC(
.PCWr ( PCWr |( PCWrCond & zero )),
.NPC ( alu_pc_mux_out ),
.clk ( clk ),
.reset ( reset ),
.PC ( PC )
);
// im_4k U_IM (
// .addr(pc_im_mux_out[11:2]),
// .dout(im_dout)
// );
im_4k U_IM(
.clk ( clk ),
.RAdr ( pc_im_mux_out[11:2] ),
.WrAdr ( ALUOut[11:2] ),
.MemWr ( MemWr ),
.Din ( busB ),
.Dout ( im_dout )
);
// dm_4k U_DM (
// .addr(ALUOut[11:2]),
// .din(busB),
// .DMWr(MemWr),
// .clk(clk),
// .dout(dm_dout)
// );
Alu U_Alu(
.A ( reg_alu_mux_out ),
.B ( reg_alu_mux2_out ),
.ALUOp ( ALUOp ),
.ALUOut ( ALUOut ),
.zero ( zero )
);
target U_target(
.clk ( clk ),
.reset ( reset ),
.tar_in ( ALUOut ),
.BrWr ( BrWr ),
.tar_out ( tar_out )
);
IR U_IR(
.clk ( clk ),
.IRWr ( IRWr ),
.in ( im_dout ),
.IRout( IRout )
);
regfile U_regfile(
.clk ( clk ),
.raddr1 ( IRout[25:21] ),
.rdata1 ( busA ),
.raddr2 ( IRout[20:16] ),
.rdata2 ( busB ),
.RFWr ( RegWr ),
.waddr ( ir_reg_mux_out ),
.wdata ( im_reg_mux_out )
);
ctrl U_ctrl(
.clk ( clk ),
.reset ( reset ),
.opcode ( IRout[31:26] ),
.PCWr ( PCWr ),
.PCWrCond ( PCWrCond ),
.IorD ( IorD ),
.MemWr ( MemWr ),
.IRWr ( IRWr ),
.RegDst ( RegDst ),
.RegWr ( RegWr ),
.ALUSelA ( ALUSelA ),
.ALUSelB ( ALUSelB ),
.PCSrc ( PCSrc ),
.BrWr ( BrWr ),
.ExtOp ( ExtOp ),
.MemtoReg ( MemtoReg ),
.ALUOp ( ALUOp )
);
mutiplexer32_1 U_PC_IM(
.s ( IorD ),
.d0 ( PC ),
.d1 ( ALUOut ),
.out32_1 ( pc_im_mux_out )
);
mutiplexer5_1 U_IR_Regfile(
.s ( RegDst ),
.d0 ( IRout[20:16] ),
.d1 ( IRout[15:11] ),
.out5_1 ( ir_reg_mux_out )
);
mutiplexer32_1 U_IM_Regfile(
.s ( MemtoReg ),
.d0 ( ALUOut ),
.d1 ( im_dout ),
.out32_1 ( im_reg_mux_out )
);
mutiplexer32_1 U_Regfile_Alu_1(
.s ( ALUSelA ),
.d0 ( PC ),
.d1 ( busA ),
.out32_1 ( reg_alu_mux_out )
);
EXT U_EXT(
.Imm16 ( IRout[15:0] ),
.ExtOp ( ExtOp ),
.Imm32 ( Imm32 )
);
mutiplexer32_1 U_Alu_PC(
.s ( PCSrc ),
.d0 ( ALUOut ),
.d1 ( tar_out ),
.out32_1 ( alu_pc_mux_out )
);
mutiplexer32_2 U_Regfile_Alu_2(
.s ( ALUSelB ),
.d0 ( 32'h4 ),
.d1 ( busB ),
.d2 ( {Imm32[29:0],2'b00} ),
.d3 ( Imm32 ),
.out32_2 ( reg_alu_mux2_out )
);
endmodule
module PC(
input PCWr, //控制PC是否更改
input [31:0] NPC,
input clk,
input reset,
output reg [31:0] PC
);
// always@(posedge clk, posedge reset) begin
// if(reset) PC <= 32'h0000_3000;//PC复位后初值为0x0000_3000
// else if(PCWr) begin
// PC <= NPC;
// end else begin
// PC <= PC;
// end
// end
always @(posedge clk or posedge reset) begin
if (reset) PC <= 32'h0000_3000;
else if (PCWr)
PC <= NPC;
end
endmodule
module target(
input clk,
input reset,
input [31:0] tar_in,
input BrWr,
output reg[31:0] tar_out
);
always @(posedge clk) begin
if (!BrWr)
tar_out <= tar_in;
end
endmodule
module regfile(
input clk,
// READ PORT 1
input [ 4:0] raddr1,
output [31:0] rdata1,
// READ PORT 2
input [ 4:0] raddr2,
output [31:0] rdata2,
// WRITE PORT
input RFWr, //write enable, HIGH valid
input [ 4:0] waddr,
input [31:0] wdata
);
reg [31:0] rf[31:0];
//WRITE
always @(posedge clk) begin
if (RFWr) rf[waddr] <= wdata;
end
//READ OUT 1
assign rdata1 = (raddr1 == 5'b0) ? 32'b0 : rf[raddr1];
//READ OUT 2
assign rdata2 = (raddr2 == 5'b0) ? 32'b0 : rf[raddr2];
endmodule
module mips_tb();
reg clk, reset;
mips U_MIPS(
.clk(clk), .reset(reset)
);
initial begin
$readmemh( "code.txt" , U_MIPS.U_IM.imem ) ;
//$monitor("PC = 0x%8X, IR = 0x%8X", U_MIPS.U_PC.PC, U_MIPS.instr );
clk = 1 ;
reset = 0 ;
#5 ;
reset = 1 ;
#20 ;
reset = 0 ;
end
always
#(50) clk = ~clk;
endmodule