多週期CPU設計——流水燈

本設計分爲10個模塊加一個整體仿真激勵模塊,各模塊代碼如下:

流水燈的變換形式爲: 0000000 -> 00000001 -> 00000011 -> 00000111 -> 00001111 -> 00011111 -> 00111111 -> 01111111 -> 11111111

時間間隔爲1s。


`timescale 1ns / 1ps

//包括IR

module InsMem(
	input CLK,
	input InsMemRW, IRWre,
	input [31:0] pc_out,
	output reg [31:0] ins_out
    );

	reg [31:0] IDataOut;
	reg [7:0] InsMemory[0:255];
	
	initial begin
		$readmemb("instructions.txt", InsMemory);
	end
	
	always @ (pc_out or InsMemRW) begin
		if (InsMemRW) begin
			IDataOut[31:24] =  InsMemory[pc_out];
			IDataOut[23:16] =  InsMemory[pc_out+1];
			IDataOut[15:8]  =  InsMemory[pc_out+2];
			IDataOut[7:0]   =  InsMemory[pc_out+3];
		end
	end
	
	always @ (posedge CLK) begin
		if (IRWre)
			ins_out <= IDataOut;
	end
	
endmodule

module fp50m(clk,reset,newclk);
	input clk,reset;
	output newclk;
	reg newclk;
	reg [31:0] count,count1;
	always@(posedge clk or negedge reset)
	begin
		if(!reset)
		begin 
			newclk<=1'd0; 
			count<=32'd0;
		end 
		else if(count==32'd1250000)  //0.1s 2500000
		begin 
			count<=32'd0; 
			newclk<=~newclk;
		end//end begin 
		else count<=count+1'd1;
	end
endmodule

`timescale 1ns / 1ps

module Extend(
	input ExtSel,
	input [15:0] Imm_16,
	output reg [31:0] Imm
    );
	
	always @ (Imm_16 or ExtSel) begin
		if (ExtSel) begin
			Imm = {{16{Imm_16[15]}}, Imm_16[15:0]};
		end else begin
			Imm = {{16{0}}, Imm_16[15:0]};
		end
	end

endmodule

`timescale 1ns / 1ps

//包括2選1模塊,一個緩衝

module DataMem(
	input RD, WR, CLK,
	input ALUM2Reg,
	input [31:0] alu_out,
	input [31:0] result,
	input [31:0] reg_out2,
	output wire [31:0] data_out
    );
	
	reg [31:0] DataOut;
	reg [7:0] DataMemory[0:63];

	assign data_out = (ALUM2Reg ? DataOut : result);
	always @ (alu_out or reg_out2 or RD or WR) begin
		if (WR) begin //寫入
			DataMemory[alu_out]   = reg_out2[31:24];
			DataMemory[alu_out+1] = reg_out2[23:16];
			DataMemory[alu_out+2] = reg_out2[15:8];
			DataMemory[alu_out+3] = reg_out2[7:0];
		end else begin //讀出
			DataOut[31:24] = DataMemory[alu_out];
			DataOut[23:16] = DataMemory[alu_out+1];
			DataOut[15:8]  = DataMemory[alu_out+2];
			DataOut[7:0]   = DataMemory[alu_out+3];
		end
		//if (ALUM2Reg) data_out = DataOut;
		//else data_out = result;
	end
	
endmodule

`timescale 1ns / 1ps

module ControlUnit(
	input CLK, RST,
	input zero,
	input [5:0] op,
	output reg WrRegData, RegWre, ALUSrcA, ALUSrcB, InsMemRW, IRWre, PCWre, RD, WR, ExtSel, ALUM2Reg, 
	output reg [1:0] RegDst, PCSrc,
	output reg [2:0] ALUOp, state
    );
	
	reg [2:0] next_state;
	
	parameter [2:0] IF = 3'b000,    
						 ID = 3'b001,
						 EXE_1 = 3'b110,
						 EXE_2 = 3'b101,
						 EXE_3 = 3'b010,
						 MEM = 3'b011,
						 WB_1 = 3'b111,
						 WB_2 = 3'b100;

	parameter [5:0] _addu = 6'b000000,
					    _subu = 6'b000001,
						 _addiu = 6'b000010,
						 _or = 6'b010000,
						 _and = 6'b010001,
						 _ori = 6'b010010,
						 _sll = 6'b011000,
						 _sltu = 6'b100110,
						 _sltiu = 6'b100111,
						 _sw = 6'b110000,
						 _lw = 6'b110001,
						 _beq = 6'b110100,
						 _j = 6'b111000,
						 _jr = 6'b111001,
						 _jal = 6'b111010,
						 _halt = 6'b111111;

	initial begin
		PCWre = 0;
		ALUSrcA = 0;
		ALUSrcB = 0;
		ALUM2Reg = 0;
		RegWre = 0;
		WrRegData = 0;
		InsMemRW = 0;
		RD = 0;
		WR = 0;
		IRWre = 0;
		ExtSel = 0;
		PCSrc = 2'b00;
		RegDst = 2'b11;
		ALUOp = 3'b000;
		state = IF;
	end
	
	always @ (posedge CLK) begin // ״̬Ȑۻ
		if (RST == 0) begin
			state <= IF;
		end else begin
			state <= next_state;
		end
	end
	
	always @ (op or state) begin
		case (state)
			IF: next_state = ID;
			ID: begin
					if (op == _j || op == _jal || op == _jr || op == _halt) next_state = IF;
					else if (op == _sw || op == _lw) next_state = EXE_3;
					else if (op == _beq) next_state = EXE_2;
					else next_state = EXE_1;
				 end
			EXE_1: next_state = WB_1;
			EXE_2: next_state = IF;
			EXE_3: next_state = MEM;
			MEM: begin
					if (op == _lw) 
						next_state = WB_2;
					else
						next_state = IF;
				  end
			WB_1: next_state = IF;
			WB_2: next_state = IF;
			default: next_state = IF;
		endcase
	end
	
	always @ (state or op) begin

		//PCWre
		if (state == IF && op != _halt) PCWre = 1;
		else PCWre = 0;
		
		//ALUSrcA
		if (op == _sll) ALUSrcA = 1;
		else ALUSrcA = 0;
		
		//ALUSrcB
		if (op == _addiu || op == _ori || op == _sltiu || op == _sw || op == _lw) ALUSrcB = 1;
      else ALUSrcB = 0;
		
		//ALUM2Reg
		if (state == WB_2) ALUM2Reg = 1;
		else ALUM2Reg = 0;
		
		//RegWre
		if (state == WB_1 || state == WB_2 || op == _jal) RegWre = 1;
		else RegWre = 0;
		
		//WrRegData
		//if (state == WB_1 || state == WB_2) WrRegData = 1;
		if (op == _jal) WrRegData = 0;
		else WrRegData = 1;
		
		//InsMemRW
		InsMemRW = 1;
		
		//RD
		if (state == MEM && op == _lw) RD = 1;
		else RD = 0;
		
		//WR
		if (state == MEM && op == _sw) WR = 1;
		else WR = 0;
		
		//IRWre
		if (state == IF) IRWre = 1;
		else IRWre = 0;
		
		//ExtSel
		if (state == EXE_1 && (op == _ori || op == _sll)) ExtSel = 0;
		else ExtSel = 1;
		
		//PCSrc
		case (op)
			_j: PCSrc = 2'b11;
			_jal: PCSrc = 2'b11;
			_jr: PCSrc = 2'b10;
			_beq: begin
					if (zero) PCSrc = 2'b01;
					else PCSrc = 2'b00;
				  end
			default: PCSrc = 2'b00;
		endcase
		
		//RegDst
		if (op == _jal) RegDst = 2'b00;
		else if (op == _addiu || op == _ori || op == _sltiu || op == _lw) RegDst = 2'b01;
		else RegDst = 2'b10;
		
		//ALUOp
		case (op)
			_subu: ALUOp = 3'b001;
			_or: ALUOp = 3'b101;
			_and: ALUOp = 3'b110;
			_ori: ALUOp = 3'b101;
			_sltu: ALUOp = 3'b010;
			_sltiu: ALUOp = 3'b010;
			_sll: ALUOp = 3'b100;
			_beq: ALUOp = 3'b001;
			default: ALUOp = 3'b000;
		endcase
		
	end	
		
endmodule

`timescale 1ns / 1ps

//包括兩個2選1模塊,一個緩衝

module ALU(
	input CLK, ALUSrcA, ALUSrcB,
	input [2:0] ALUOp,
	input [31:0] reg_out1, reg_out2,
	input [31:0] ins_out, Imm,
	input [31:0] sa,
	output reg [31:0] result,
	output reg [31:0] alu_out,
	output zero
    );
	
	initial begin
		result = 0;
	end
	
	wire [31:0] A, B;
	assign A = (ALUSrcA ? sa : reg_out1);
	assign B = (ALUSrcB ? Imm : reg_out2);
	assign zero = (result ? 0 : 1);
	
	always @ (A or B or ALUOp) begin
		case (ALUOp)
			3'b000:	result = A + B;
			3'b001:	result = A - B;
			3'b010:	result = (A < B ? 1 : 0);
			3'b011:	result = B >> A;
			3'b100:	result = B << 1;
			3'b101:	result = A | B;
			3'b110:	result = A & B;
			3'b111:	result = (~A & B) | (A & ~B);
			default:	result = 0;
		endcase
		alu_out = result;
	end
	
endmodule

`timescale 1ns / 1ps

//包括3選1模塊,2選1模塊,兩個緩衝

module RegFile(
	input CLK,
	input RegWre, WrRegData,
	input [1:0] RegDst,
	input [31:0] pc_out,
	//input [31:0] PC4,
	input [4:0] rs, rt, rd,
	input [31:0] data_out,
	output reg [31:0] reg_out1, reg_out2,
	output reg [31:0] ReadData1, ReadData2, 
	output wire [31:0] WriteData,
	output reg [4:0] WriteReg,
	output wire [7:0] pin_out
    );
	
	reg [31:0] register[0:31];
	
	initial begin
		register[0] = 0;
	end
	
	assign pin_out = (register[1][15:8]);
	assign WriteData = (WrRegData ? data_out : (pc_out + 4));
	
	always @ (negedge CLK) begin
		case (RegDst)
			2'b00:	WriteReg <= 5'b11111; //$31
			2'b01:	WriteReg <= rt;
			2'b10:	WriteReg <= rd;
			default: WriteReg <= 0; //$0不能改值
		endcase
		//WriteData <= (WrRegData ? data_out : (pc_out + 4));
		//assign WriteData = (WrRegData ? data_out : PC4);
		ReadData1 <= register[rs];
		ReadData2 <= register[rt];
		if ((WriteReg != 0) && (RegWre == 1)) begin
			register[WriteReg] <= WriteData;
		end
	end
	
	always @ (negedge CLK) begin
		reg_out1 <= ReadData1;
		reg_out2 <= ReadData2;
	end

endmodule

`timescale 1ns / 1ps

//包括邏輯左移模塊

module PC_0(
	input [31:0] ins_out,
	input [31:0] pc_out,
	output reg [31:0] addr
    );
	
	wire [27:0] temp;
	
	assign temp = ins_out[25:0] << 2 ;
	
	always @ (ins_out) begin
		addr <= {pc_out[31:28], temp[27:0]};
	end
	
endmodule

`timescale 1ns / 1ps

//包括加4模塊,加立即數模塊,4選1模塊

module PC(
	input CLK, RST,
	input PCWre,
	input [1:0] PCSrc,
	input [31:0] Imm,
	input [31:0] ReadData1,
	input [31:0] addr,
	output reg [31:0] pc_out
    );
	
	always @ (negedge CLK or negedge RST) begin
		if (!RST) begin
			pc_out <= 0;
		end else if (PCWre) begin
			case (PCSrc)
				2'b00:	pc_out <= pc_out + 4;
				2'b01:	pc_out <= Imm * 4 + pc_out + 4;
				2'b10:	pc_out <= ReadData1;
				2'b11:	pc_out <= addr; // addr是跳轉地址
				default: pc_out <= 0;
			endcase
		end
	end
	
endmodule

`timescale 1ns / 1ps

module MultiCycleCPU(
	input clk, RST,

	output [7:0] pin_out
    );
	wire CLK;
	wire [31:0] WriteData, pc_out, addr;
	wire [31:0] reg_out1, reg_out2, data_out;
	wire [31:0] alu_out,sa;
	wire [5:0] op;
	wire [4:0] rs,rt, WriteReg; 
	wire [2:0] state,ALUOp;
	wire [1:0] RegDst; 
	wire zero;
	//WrRegData;
	
	
	//wire CLK;
	wire [31:0] result, ReadData1, ReadData2, ins_out, /*addr, */Imm;
	wire [15:0] Imm_16;
	wire [4:0] rd;
	//wire [2:0] ALUOp;
	wire [1:0] /*RegDst, */PCSrc;
	wire PCWre, InsMemRW, IRWre, RegWre, WrRegData, ExtSel, ALUSrcA, ALUSrcB, RD, WR, ALUM2Reg;
	
		assign op = ins_out[31:26];	
	assign rs = ins_out[25:21];
	assign rt = ins_out[20:16];
	assign rd = ins_out[15:11];
	assign Imm_16 = ins_out[15:0];	
	assign sa = {{27{0}}, ins_out[10:6]};
	
	fp50m fp50m(clk,RST,CLK);
	
	PC PC(CLK, RST, PCWre, PCSrc, Imm, ReadData1, addr, pc_out);
	
	PC_0 PC_0(ins_out, pc_out, addr);
	
	InsMem InsMem(CLK, InsMemRW, IRWre, pc_out, ins_out);
	
	RegFile RegFile(CLK, RegWre, WrRegData, RegDst, pc_out, rs, rt, rd, data_out, reg_out1, reg_out2, ReadData1, ReadData2, WriteData, WriteReg ,pin_out);
	
	Extend Extend(ExtSel, Imm_16, Imm);
	
	ALU ALU(CLK, ALUSrcA, ALUSrcB, ALUOp, reg_out1, reg_out2, ins_out, Imm, sa, result, alu_out, zero);
	
	DataMem DataMem(RD, WR, CLK, ALUM2Reg, alu_out, result, reg_out2, data_out);
	
	ControlUnit ControlUnit(CLK, RST, zero, op, WrRegData, RegWre, ALUSrcA, ALUSrcB, InsMemRW, IRWre, PCWre, RD, WR, ExtSel, ALUM2Reg, RegDst, PCSrc, ALUOp, state);

endmodule


`timescale 1ns / 1ps
//仿真激勵模塊
module MultiCycleCOU_tf;

	// Inputs
	reg CLK;
	reg RST;

	// Outputs
	wire [31:0] Imm;
	/*wire [31:0] ReadData1;
	wire [31:0] ReadData2;*/
	wire [31:0] WriteData;
	wire [31:0] addr;
	wire [31:0] pc_out;
	wire [31:0] reg_out1;
	wire [31:0] reg_out2;
	//wire [31:0] ins_out;
	wire [31:0] data_out;
	//wire [31:0] result;
	wire [31:0] alu_out;
	wire [31:0] sa;
	/*wire [31:0] A;
	wire [31:0] B;*/
	//wire [15:0] Imm_16;
	wire [5:0] op;
	wire [4:0] rs;
	wire [4:0] rt;
	wire [4:0] rd;
	wire [4:0] WriteReg;
	wire [2:0] ALUOp;
	wire [2:0] state_out;
	wire [2:0] state;
	wire [1:0] RegDst;
	wire [1:0] PCSrc;
	wire zero;
	wire PCWre;
	wire InsMemRW;
	wire IRWre;
	wire RegWre;
	wire WrRegData;
	wire ExtSel;
	wire ALUSrcA;
	wire ALUSrcB;
	//wire DataMemRW;
	wire RD;
	wire WR;
	wire ALUM2Reg;

	// Instantiate the Unit Under Test (UUT)
	MultiCycleCPU uut (
		.CLK(CLK), 
		.RST(RST), 
		.Imm(Imm), 
		/*.ReadData1(ReadData1), 
		.ReadData2(ReadData2),*/
		.WriteData(WriteData),
		.addr(addr), 
		.pc_out(pc_out), 
		.reg_out1(reg_out1), 
		.reg_out2(reg_out2), 
		//.ins_out(ins_out), 
		.data_out(data_out), 
		//.result(result), 
		.alu_out(alu_out), 
		.sa(sa),
		/*.A(A),
		.B(B),*/
		//.Imm_16(Imm_16), 
		.op(op), 
		.rs(rs), 
		.rt(rt), 
		.rd(rd),
		.WriteReg(WriteReg),  
		.ALUOp(ALUOp), 
		.state_out(state_out),
		.state(state),
		.RegDst(RegDst), 
		.PCSrc(PCSrc), 
		.zero(zero), 
		.PCWre(PCWre), 
		.InsMemRW(InsMemRW), 
		.IRWre(IRWre), 
		.RegWre(RegWre), 
		.WrRegData(WrRegData), 
		.ExtSel(ExtSel), 
		.ALUSrcA(ALUSrcA), 
		.ALUSrcB(ALUSrcB), 
		//.DataMemRW(DataMemRW),
		.RD(RD),
		.WR(WR),
		.ALUM2Reg(ALUM2Reg)
	);
always #30 CLK = !CLK;
	
	initial begin
		// Initialize Inputs
		CLK = 1;
		RST = 0;

		// Wait 60ns for global reset to finish
		#90;
		RST = 1;
        
		// Add stimulus here

	end
      
endmodule



指令代碼設計文件(instruction.txt)

00001000 
00000001 
00000000 
11111111


11000000
00000001 
00000000 
11111111


11100000
00000000 
00000000 
00000011


01100000
00100001 
00001000 
00000001


11000000
00000001 
00000000 
11111111


11100000
00000000
00000000 
00000110


01100000
00100001 
00001000 
00000001


11000000
00000001
00000000 
11111111


11100000
00000000
00000000
00001001


01100000
00100001 
00001000 
00000001


11000000
00000001
00000000
11111111


11100000
00000000
00000000
00001100


01100000
00100001 
00001000 
00000001


11000000
00000001
00000000
11111111


11100000
00000000
00000000
00001111


01100000
00100001 
00001000 
00000001


11000000
00000001
00000000
11111111


11100000
00000000
00000000
00010010


01100000
00100001 
00001000 
00000001


11000000
00000001
00000000
11111111


11100000
00000000
00000000
00010101


01100000
00100001 
00001000 
00000001


11000000
00000001
00000000
11111111


11100000
00000000
00000000
00011000


01100000
00100001 
00001000 
00000001


11000000
00000001
00000000
11111111


11100000
00000000
00000000
00000000






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章