多周期CPU设计(verilog)
文章目录
- 一、设计思路
- **1.主要参照:**
- **2.多周期处理器**:
- **3.指令周期:**
- **4.MIPS指令:**
- 二、主要模块设计
- **1.总体模块构成**
- **2. MultiCycleCPU.v**
- **3. PCctr.v**
- 3. ControlUnit.v
- **控制信号的生成**
- 状态转换
- 输入、输出端口声明:
- **3. 其他模块**
- 四、模块间主要信号传递
- 五、功能仿真
- **1. 仿真文件**
- **2. 存储的指令**
- **3. 测试**
- 六、模块代码
- 1. MultiCycleCPU
- 2. PCctr
- 3. PC_in_out
- 4. InstructionMem
- 5. ControlUnit
- 6. RegisterFile
- 7. Extender
- 8. ALUSrc_select
- 9. ALU32
- 10. DataMem
- 11. Data_select
一、设计思路
1.主要参照:
计算机组成与系统结构(第2版)(袁春风)中央处理器
及所学知识
2.多周期处理器:
把每条指令的执行分成多个大致相等的阶段,每个阶段在一个时钟周期内完成;各阶段内最多完成一次访存或一次寄存器读写或一次ALU操作;各阶段的执行结果在下一次时钟到来时保存到相应存储单元或稳定的保持在组合电路中;时钟周期的宽度以最复杂阶段所用时间为准,通常取一次存储器读写的时间。
3.指令周期:
- 取指令(IF):根据程序计数器PC中的指令地址,从存储器中取出一条指令。同时,PC根据指令子长度自动递增产生下一条指令所需要的指令地址,但遇到地址转移指令时,则控制器把转移地址送入PC,得到的地址做些变换送入PC。
- 指令译码(ID):对取指令操作中得到的指令进行分析和译码,确定这条指令需要完成的操作,从而产生相应的操作控制信号,用于驱动执行状态中的各种操作。
- 指令执行(EXE):跟据指令译码得到的操作控制信号,具体的执行指令动作,然后转移到结果写回状态。
- 存储器访问(MEM):所有需要访问存储器的操作都将在这个步骤中执行,该步骤给出存储器的数据地址,把数据写入到存储器中数据地址所指定的存储单元或者从存储器中得到数据地址单元中的数据。
- 结果写回(WB):指令执行的结果或者访问存储器中得到的数据写回相应的目的寄存器中。
4.MIPS指令:
MIPS指令可以分为三种类型,每种类型的指令需要不同的时钟周期数。
寄存器型(R型)指令
op rs rt rd shamt funct 6位 5位 5位 5位 5位 6位 立即数型(I型)指令
op rs rt immediate 6位 5位 5位 16位 跳转型(J型)指令
op addr 6位 26位 op:操作码
rs:第1个源操作数寄存器
rt:第2个源操作数寄存器,或目的操作数寄存器
rd:目的操作数寄存器
shamt:位移量,移位指令用于指定移多少位
func:功能码,在R类型指令中用来指定指令的功能
immediate:16位立即数
addr:地址
二、主要模块设计
1.总体模块构成
2. MultiCycleCPU.v
MultiCycleCPU作为顶层模块,只有一个CLK(时钟信号)作为输入,时钟周期在仿真模块中设置。
MultiCycleCPU通过调用每个模块,并控制信号在相应模块间的传递来实现多周期CPU的功能。
3. PCctr.v
PCctr计算下一条指令的地址,并对pc在刚开始进行置0初始化。
对于pc的改变有三种形式,beq指令,jump指令,其他。
要实现pc地址的正确计算,需要在取一条指令后,进行+4指向下一条指令,但是对于jump指令并不需要进行+4的操作。所以增加PCWre信号,当不为jump指令时设置位1。当PCWre为1时进行pc+4,对于jump指令则不进行这个操作。对于beq指令,则在译码产生Branch信号后在已经+4的pc基础上在加上扩展后的立即数即可。
PCctr模块设计如下,左侧是输入信号,右侧是输出信号。
端口名称 | 说明 |
---|---|
pc_in | 输入pc值 |
PCWre | pc写使能 |
imm | 取自指令后26位,对于beq则在此基础上截取后16位 |
Zero | 控制信号,用于beq指令 |
Branch | 控制信号,用于beq指令 |
Jump | 控制信号,用于jump指令 |
pc_out | 输出pc值 |
3. ControlUnit.v
ControlUnit模块主要根据当前指令的op和func生成对应的控制信号,同时根据当前状态和操作码确定下一状态。
控制信号的生成
参照书上的11条MIPS指令,加上addu
指令,共兼容12条MIPS指令。
func | op | ALUctr | |
---|---|---|---|
addu | 000000 | 100001 | 000 |
- ALUctr(ALU控制信号)编码方案:
addiu
、lw
、sw
、addu
的ALU控制信号取值一样,都是进行加法运算并不判溢出,记为addu操作。
subu
和beq
判0操作的ALU控制信号可看成一样,都做减法运算并不判溢出,记为subu操作。
ALU操作类型 | func | ALUctr |
---|---|---|
addu | 100001 | 000 |
add | 100000 | 001 |
or | 010 | |
subu | 100011 | 100 |
sub | 100010 | 101 |
sltu | 101011 | 110 |
slt | 101010 | 111 |
对于R-type型指令,除了ALUctr信号以外,其余控制信号的取值都相等
R—型指令的ALUctr信号的取值由其func字段决定
由上面func与ALUctr的对应关系,可得:
ALUctr[2]=!func[2] & func[1]ALUctr[1]=func[3] & func[2] & func[1]ALUctr[0]=!func[3] & !func[2] & !func[1] & !func[0] + !func[2] + func[1] + !func[0]
I—型指令,J—型指令的ALUctr控制信号的取值由op字段决定,可得编码方案:
ALUctr[2]=beq= !op[5] & !op[4] & !op[3] & op[2] & !op[1] & !op[0]ALUctr[1]=ori= !op[5] & !op[4] & op[3] & op[2] & !op[1] & op[0]ALUctr[0]=R-type= !op[5] & !op[4] & !op[3] & !op[2] & !op[1] & !op[0]
对于其他控制信号,采用编码方案有些复杂,采用判断的形式来生成它们的信号。
状态转换
有限状态机控制器思想:
用一个有限状态机描述指令执行过程,由当前状态和操作码确定下一状态,每来一个时钟发生一次状态改变,不同状态输出不同的控制信号值,然后送到数据通路来控制指令的执行。
在设计时采用与书上的有限状态机控制器思想有些不同的思路,不采用不同状态输出不同控制信号。控制信号在ID(指令译码)阶段同时生成,增加输出信号IF_clk、ID_clk、ALU_clk、MEM_clk、WB_clk区分指令的不同阶段,根据不同的状态来修改这些信号的值。通过这些信号来触发指令的不同执行阶段。
在多周期CPU中,不同的指令分别占用不同的周期数。查阅资料,不同的指令参照如下的状态转移图:
最后,ControlUnit
模块设计如下(具体实现代码太多,只选取端口声明部分):
module ControlUnit(
clk,Opcode,func,
Branch,Jump,RegDst,ALUSrc,ALUctr,MemorReg,RegWr,MemWr,ExtOp,PCWre,
IF_clk,ID_clk,ALU_clk,MEM_clk,WB_clk,
state_out);input clk;input [5:0] Opcode;input [5:0] func;output reg Branch;output reg Jump;output reg RegDst;output reg ALUSrc;output reg [2:0] ALUctr;output reg MemorReg;output reg RegWr;output reg MemWr;output reg ExtOp;output reg PCWre;output reg [2:0] state_out;output reg IF_clk;output reg ID_clk;output reg ALU_clk;output reg MEM_clk;output reg WB_clk;
输入、输出端口声明:
端口名称 | 说明 |
---|---|
clk | 时钟周期 |
Opcode | 操作码 |
func | 功能码,在R类型指令中用来指定指令的功能 |
Branch | beq |
Jump | jump |
RegDst | 选择写回结果的寄存器编号 |
ALUSrc | ALU输入来源 |
ALUctr | ALU操作码 |
MemorReg | 数据来自存储器还是ALU结果 |
RegWr | RegisterFile写使能 |
MemWr | 存储器写使能 |
ExtOp | 扩展方式 |
PCWre | 修改pc值 |
state_out | 状态输出 |
IF_clk | 取指信号 |
ID_clk | 指令译码信号 |
ALU_clk | 指令执行信号 |
MEM_clk | 存储器访问信号 |
WB_clk | 结果写回信号 |
3. 其他模块
ALU32.v
总体与第一次课程设计相同,根据此次多周期CPU进行适当修改。
其他模块的实现也比较简单,前面总体模块构成已大概介绍。比较难实现的是考虑各种信号在不同模块间的传递,以及将模块组合后可以协调工作顺利实现多周期CPU的功能。
四、模块间主要信号传递
这里只标识了主要信号的传递,别的信号大致采用同名表示同一信号传递。
除MultiCycleCPU外,主要模块大致都是左侧是输入信号,右侧是输出信号。
五、功能仿真
1. 仿真文件
每1ps个时间单位时钟信号反转一次,即时钟周期为2ps
module MultiCycleCPU_test();// module MultiCycleCPU(
// CLK,
// Opcode,ALU_in1,ALU_in2,ALU_result,STATE_out,PC_out,
// IF_clk,ID_clk,ALU_clk,MEM_clk,WB_clk
// );reg CLK;wire IF_clk,ID_clk,ALU_clk,MEM_clk,WB_clk;wire [5:0] Opcode;wire [31:0] ALU_in1;wire [31:0] ALU_in2;wire [31:0] ALU_result;wire [31:0] PC_out;MultiCycleCPU cpu32(.CLK(CLK),.Opcode(Opcode),.ALU_in1(ALU_in1),.ALU_in2(ALU_in2),.ALU_result(ALU_result),.PC_out(PC_out),.IF_clk(IF_clk),.ID_clk(ID_clk),.ALU_clk(ALU_clk),.MEM_clk(MEM_clk),.WB_clk(WB_clk));initialbeginCLK=0;endalways #0.001 CLK=~CLK;
endmodule
2. 存储的指令
memory[0]=32'b000000_00111_00010_00010_00000_100000;//add reg[2]=reg[7]+reg[2]memory[1]=32'b000000_00010_00111_00100_00000_100011;//subu reg[4]=reg[2]-reg[7]memory[2]=32'b000000_00000_00001_00010_00000_101011;//sltu reg[0]<reg[1]?reg[2]=1:reg[2]=0memory[3]=32'b001101_00011_00100_0010011111000001;//ori reg[4]=reg[3]|zeroext(0010011111000001)memory[4]=32'b101011_00101_00110_0000000000000111;//sw reg[6]=6 MEM[reg[5]+SignExt(imm16)<=reg[6]memory[5]=32'b100011_00101_00111_0000000000000111;//lw reg[7]<=MEM[reg[5]+SignExt(imm16)memory[6]=32'b000000_00111_00010_00011_00000_100000;//add reg[7]=6,,reg[2]=1,reg[3]=reg[7]+reg[2]memory[7]=32'b000100_00001_00010_0000000000000001;//beq reg[1]==reg[2] ? pc<=pc+4+SignExt(0000000000000001)*4 : pc<=pc+4//memory[8]beq跳转到memory[9]memory[9]=32'b000010_00000_00000_00000_00000_111111;//jump pc<=0000_00000_00000_00000_00000_111111_00
3. 测试
对照CLK、IF_clk、ID_clk、ALU_clk、MEM_clk、WB_clk所划分的周期可以很容易验证指令的执行情况。
六、模块代码
1. MultiCycleCPU
module MultiCycleCPU(
CLK,
Opcode,ALU_in1,ALU_in2,ALU_result,PC_out,
IF_clk,ID_clk,ALU_clk,MEM_clk,WB_clk);input CLK;output [5:0] Opcode;output [31:0] ALU_in1;output [31:0] ALU_in2;output [31:0] ALU_result;output [31:0] PC_out;//计算出的下一个pc值output IF_clk,ID_clk,ALU_clk,MEM_clk,WB_clk;//ControlUnit输出信号wire PCWre,Branch,Jump,RegDst,ALUSrc,MemorReg,MemWr,ExtOp;wire RegWr;wire [2:0] ALUctr;wire [2:0] STATE_out;//ALU输出信号wire Carryout,Zero,Overflow;wire [31:0] PC_in;//从指令中取出的相关数据wire [25:0] Imm26;wire [5:0] FUNC;wire [4:0] RS;wire [4:0] RT;wire [4:0] RD;wire [31:0] DataMem_out;//RegisterFile相关wire [31:0] data_to_registerfile;//wire [31:0] ALU_data1;wire [31:0] ALU_temp_data1;wire [31:0] ALU_temp_data2;//wire [31:0] ALU_data2;
// module PCctr(
// clk,PCWre,Branch, Jump, Zero, imm,pc_in,pc_out);
//imm取自指令后26位PCctr pcctr(.PCWre(PCWre),.Branch(Branch),.Jump(Jump),.Zero(Zero),.imm(Imm26),.pc_in(PC_in),.pc_out(PC_out));// module PC_in_out(
// clk,pc_in,
// pc_out );
//把当前pc值PC_out,送入PC_in,以便PCctr下一次计算PC_in_out pc_in_out(.clk(CLK),.pc_in(PC_out),.pc_out(PC_in)); // module InstructionMem(
// pc,IF_clk,
// ins_Opcode,ins_func,ins_rs,ins_rt,ins_rd,ins_imm );
//imm取自指令后26位InstructionMem IM(.pc(PC_out),.IF_clk(IF_clk),.ins_Opcode(Opcode),.ins_func(FUNC),.ins_rs(RS),.ins_rt(RT),.ins_rd(RD),.ins_imm(Imm26));// module ControlUnit(
// clk,Opcode,func,
// Branch,Jump,RegDst,ALUSrc,ALUctr,MemorReg,RegWr,MemWr,ExtOp,PCWre,
// IF_clk,ID_clk,ALU_clk,MEM_clk,WB_clk,
// state_out
// );ControlUnit controlunit(.clk(CLK),.Opcode(Opcode),.func(FUNC),.Branch(Branch),.Jump(Jump),.RegDst(RegDst),.ALUSrc(ALUSrc),.ALUctr(ALUctr),.MemorReg(MemorReg),.RegWr(RegWr),.MemWr(MemWr),.ExtOp(ExtOp),.PCWre(PCWre),.IF_clk(IF_clk),.ID_clk(ID_clk),.ALU_clk(ALU_clk),.MEM_clk(MEM_clk),.WB_clk(WB_clk),.state_out(STATE_out));// module RegisterFile(
// WB_clk,RegWr,Overflow,RegDst,Ra,Rb,Rc,busW,
// busA,busB ); RegisterFile registerfile(.WB_clk(WB_clk),.RegWr(RegWr),.Overflow(Overflow),.RegDst(RegDst),.Ra(RS),.Rb(RT),.Rc(RD),.busW(data_to_registerfile),.busA(ALU_in1),.busB(ALU_temp_data1)); // module Extender(
// ExtOp,ex_imm,
// ex_out
// ); Extender extender(.ExtOp(ExtOp),.ex_imm(Imm26),.ex_out(ALU_temp_data2));// module ALUSrc_select(
// ALUSrc,busB,imm36,
// src_out ); ALUSrc_select alusrc_select(.ALUSrc(ALUSrc),.busB(ALU_temp_data1),.imm36(ALU_temp_data2),.src_out(ALU_in2));// module ALU32(
// ALU_clk,ALUctr,in0,in1,
// carryout,overflow,zero,out );ALU32 alu32(.ALU_clk(ALU_clk),.ALUctr(ALUctr),.in0(ALU_in1),.in1(ALU_in2),.carryout(Carryout),.overflow(Overflow),.zero(Zero),.out(ALU_result));// module DataMem(
// MEM_clk,WrEn,Adr,DataIn,
// DataOut
// );DataMem datamem(.MEM_clk(MEM_clk),.WrEn(MemWr),.Adr(ALU_result),.DataIn(ALU_temp_data1),.DataOut(DataMem_out));// module Data_select(
// MemorReg,ALU_out,DataMem_out,
// Data_out
// );Data_select data_select(.MemorReg(MemorReg),.ALU_out(ALU_result),.DataMem_out(DataMem_out),.Data_out(data_to_registerfile));endmodule
2. PCctr
module PCctr(
PCWre,Branch, Jump, Zero, imm,pc_in,pc_out);//input clk;input PCWre;input Branch;input Jump;input Zero;input [25:0] imm;//imm取自指令的后26位input [31:0] pc_in;output reg [31:0] pc_out;initialbeginpc_out=0;end//clk上升沿触发always @(Jump or Branch or Zero or PCWre)if(Jump)pc_out={pc_in[31:28],imm[25:0],1'b0,1'b0};else if(Branch&&Zero)pc_out=pc_in+{{14{imm[15]}},imm[15:0],1'b0,1'b0};else if(!Jump&&PCWre)pc_out=pc_in+4;endmodule
3. PC_in_out
module PC_in_out(
clk,pc_in,
pc_out);input clk;input [31:0] pc_in;output reg [31:0] pc_out;always@(posedge clk)beginpc_out<=pc_in;end
endmodule
4. InstructionMem
module InstructionMem(
pc,IF_clk,
ins_Opcode,ins_func,ins_rs,ins_rt,ins_rd,ins_imm);input [31:0] pc;input IF_clk;output reg [5:0] ins_Opcode;output reg [5:0] ins_func;output reg [4:0] ins_rs;output reg [4:0] ins_rt;output reg [4:0] ins_rd;output reg [25:0] ins_imm;reg [31:0] memory[64:0];initialbeginmemory[0]=32'b000000_00111_00010_00010_00000_100000;//add reg[2]=reg[7]+reg[2]memory[1]=32'b000000_00010_00111_00100_00000_100011;//subu reg[4]=reg[2]-reg[7]memory[2]=32'b000000_00000_00001_00010_00000_101011;//sltu reg[0]<reg[1]?reg[2]=1:reg[2]=0memory[3]=32'b001101_00011_00100_0010011111000001;//ori reg[4]=reg[3]|zeroext(0010011111000001)memory[4]=32'b101011_00101_00110_0000000000000111;//sw reg[6]=6 MEM[reg[5]+SignExt(imm16)<=reg[6]memory[5]=32'b100011_00101_00111_0000000000000111;//lw reg[7]<=MEM[reg[5]+SignExt(imm16)memory[6]=32'b000000_00111_00010_00011_00000_100000;//add reg[7]=6,,reg[2]=1,reg[3]=reg[7]+reg[2]memory[7]=32'b000100_00001_00010_0000000000000001;//beq reg[1]==reg[2] ? pc<=pc+4+SignExt(0000000000000001)*4 : pc<=pc+4//memory[8]beq跳转到memory[9]memory[9]=32'b000010_00000_00000_00000_00000_111111;//jump pc<=0000_00000_00000_00000_00000_111111_00endalways @(posedge IF_clk)beginins_Opcode=memory[pc[31:2]][31:26];ins_func=memory[pc[31:2]][5:0];ins_rs=memory[pc[31:2]][25:21];ins_rt=memory[pc[31:2]][20:16];ins_rd=memory[pc[31:2]][15:11];ins_imm=memory[pc[31:2]][25:0];endendmodule
5. ControlUnit
module ControlUnit(
clk,Opcode,func,
Branch,Jump,RegDst,ALUSrc,ALUctr,MemorReg,RegWr,MemWr,ExtOp,PCWre,
IF_clk,ID_clk,ALU_clk,MEM_clk,WB_clk,
state_out);input clk;input [5:0] Opcode;input [5:0] func;output reg Branch;output reg Jump;output reg RegDst;output reg ALUSrc;output reg [2:0] ALUctr;output reg MemorReg;output reg RegWr;output reg MemWr;output reg ExtOp;output reg PCWre;output reg [2:0] state_out;output reg IF_clk;output reg ID_clk;output reg ALU_clk;output reg MEM_clk;output reg WB_clk;parameter [2:0] IF=3'b000,//IF stateID=3'b001,//ID stateEXE1=3'b110,//add,sub,subu,slt,sltu,ori,addiuEXE2=3'b101,//beqEXE3=3'b010,//sw lwMEM=3'b011,//MEM stateWB1=3'b111,//add,sub,subu,slt,sltu,ori,addiuWB2=3'b100;//lwparameter [5:0] R_type=6'b000000,ori=6'b001101,addiu=6'b001001,lw=6'b100011,sw=6'b101011,beq=6'b000100,jump=6'b000010;//状态寄存器 reg [2:0] state,next_state;initialbeginBranch=0;Jump=0;RegDst=0;ALUSrc=0;ALUctr=0;MemorReg=0;RegWr=0;MemWr=0;ExtOp=0;PCWre=0;state=3'b000;state_out=state;end//上升沿触发always@(posedge clk)beginstate<=next_state;state_out=state;endalways@(state)begincase(state)//IF阶段无条件跳转到ID阶段IF: next_state<=ID;//ID阶段ID:beginif(Opcode == jump)next_state<=IF;else if(Opcode==beq)next_state<=EXE2;else if(Opcode==lw||Opcode==sw)next_state<=EXE3;elsenext_state<=EXE1;endEXE1:next_state<=WB1;EXE2:next_state<=IF;EXE3:next_state<=MEM;MEM:beginif(Opcode==lw)next_state=WB2;elsenext_state=IF;endWB1:next_state<=IF;WB2:next_state<=IF;default:next_state=IF;endcaseendalways @(next_state)beginif(next_state==IF)IF_clk=1;elseIF_clk=0;if(next_state==ID)ID_clk=1;elseID_clk=0;if(next_state==EXE1||next_state==EXE2||next_state==EXE3)ALU_clk=1;elseALU_clk=0;if(next_state==MEM)MEM_clk=1;elseMEM_clk=0;if(next_state==WB1||next_state==WB2)WB_clk=1;elseWB_clk=0;endalways@(state)beginif(state==IF&&Opcode!=jump)PCWre<=1;elsePCWre<=0;if(Opcode==R_type)beginBranch<=0;Jump<=0;RegDst<=1;ALUSrc<=0;MemorReg<=0;RegWr<=1;MemWr<=0;ALUctr[2]<=(~func[2])&func[1];ALUctr[1]<=func[3]&(~func[2])&func[1];ALUctr[0]<=((~func[3])&(~func[2])&(~func[1])&(~func[0])) | ((~func[2])&func[1]&(~func[0]));endelsebeginif(Opcode==beq)Branch<=1;elseBranch<=0;if(Opcode==jump)Jump<=1;elseJump<=0;RegDst<=0;if(Opcode==ori||Opcode==addiu||Opcode==lw||Opcode==sw)ALUSrc<=1;elseALUSrc<=0;if(Opcode==lw)MemorReg<=1;elseMemorReg<=0;if(Opcode==ori||Opcode==addiu||Opcode==lw)RegWr<=1;elseRegWr<=0;if(Opcode==sw)MemWr<=1;elseMemWr<=0;if(Opcode==addiu||Opcode==lw||Opcode==sw)ExtOp<=1;elseExtOp<=0;ALUctr[2]<=~Opcode[5]&~Opcode[4]&~Opcode[3]&Opcode[2]&~Opcode[1]&~Opcode[0];ALUctr[1]<=~Opcode[5]&~Opcode[4]&Opcode[3]&Opcode[2]&~Opcode[1]&Opcode[0];ALUctr[0]<=0;endend endmodule
6. RegisterFile
module RegisterFile(
WB_clk,RegWr,Overflow,RegDst,Ra,Rb,Rc,busW,
busA,busB);input WB_clk;input RegWr;input Overflow;input RegDst;//Ra(Rs),Rb(Rt),Rc(Rd)input [4:0] Ra;input [4:0] Rb;input [4:0] Rc;input [31:0] busW;output reg [31:0] busA;output reg [31:0] busB;reg [31:0] RegMem [31:0];//32个32位宽寄存器//初始化寄存器中的值integer i;initial begin
// RegMem[0]<=5;
// RegMem[1]<=32'b11;
// RegMem[2]<=32'b10;for(i=0;i<32;i=i+1)RegMem[i]<=i;endalways @(Ra or Rb)beginbusA=RegMem[Ra];busB=RegMem[Rb];endalways@(posedge WB_clk or RegWr)begin//RegMem[2]<=2;if(RegWr&&!Overflow)beginif(RegDst)
// RegMem[2]=2;RegMem[Rc]<=busW;elseRegMem[Rb]<=busW;endendendmodule
7. Extender
module Extender(
ExtOp,ex_imm,
ex_out);input ExtOp;input [25:0] ex_imm;output [31:0] ex_out;assign ex_out=ExtOp?{ {16{ex_imm[15]}} ,ex_imm[15:0]}:{ 16'b0,ex_imm[15:0]};//符号扩展
// always @(ExtOp)
// begin
// if(ExtOp)
// ex_out={ {16{ex_imm[15]}} ,ex_imm[15:0]};
// else
// ex_out={ 16'b0,ex_imm[15:0]};
// end
endmodule
8. ALUSrc_select
module ALUSrc_select(
ALUSrc,busB,imm36,
src_out);input ALUSrc;input [31:0] busB;input [31:0] imm36;output [31:0] src_out;assign src_out=ALUSrc?imm36:busB;
endmodule
9. ALU32
module ALU32(
ALU_clk,ALUctr,in0,in1,
carryout,overflow,zero,out);input ALU_clk;input [31:0] in0,in1;input [2:0] ALUctr;//控制ALU进行何种操作output reg[31:0] out;output reg carryout,overflow,zero;always@(posedge ALU_clk)
begincase(ALUctr)//addu3'b000:begin{carryout,out}=in0+in1;zero=(out==0)?1:0;overflow=0;end//add3'b001:beginout=in0+in1;overflow=((in0[31]==in1[31])&&(~out[31]==in0[31]))?1:0;zero=(out==0)?1:0;carryout=0;end//or3'b010:beginout=in0|in1;zero=(out==0)?1:0;carryout=0;overflow=0;end//subu3'b100:begin{carryout,out}=in0-in1;zero=(out==0)?1:0;overflow=0;end//sub3'b101:beginout=in0-in1;overflow=((in0[31]==0&&in1[31]==1&&out[31]==1)||(in0[31]==1&&in1[31]==0&&out[31]==0))?1:0;zero=(in0==in1)?1:0;carryout=0;end//sltu3'b110:beginout=(in0<in1)?1:0;carryout=out;zero=(out==0)?1:0;overflow=0;end//slt3'b111:begin if(in0[31]==1&&in1[31]==0)out=1;else if(in0[31]==0&&in1[31]==1)out=0;else out=(in0<in1)?1:0;overflow=out; zero=(out==0)?1:0;carryout=0; end/*//and11'b00000100100:beginout=in0&in1;zero=(out==0)?1:0;carryout=0;overflow=0;end//xor11'b00000100110:beginout=in0^in1;zero=(out==0)?1:0;carryout=0;overflow=0;end//nor11'b00000100111:beginout=~(in0|in1);zero=(out==0)?1:0;carryout=0;overflow=0;end//shl11'b00000000100:begin{carryout,out}=in0<<in1;overflow=0;zero=(out==0)?1:0;end//shr11'b00000000110:beginout=in0>>in1;carryout=in0[in1-1];overflow=0;zero=(out==0)?1:0;end//sar11'b00000000111:beginout=($signed(in0))>>>in1;carryout=in0[in1-1];overflow=0;zero=(out==0)?1:0;end*/endcase
end
endmodule
10. DataMem
module DataMem(
MEM_clk,WrEn,Adr,DataIn,
DataOut);input MEM_clk;input WrEn;input [31:0] Adr;input [31:0] DataIn;output reg [31:0] DataOut;//32个32位宽寄存器reg [31:0] memory[0:31];integer i;initialbeginfor(i=0;i<32;i=i+1)memory[i]<=0;endalways@ (posedge MEM_clk)beginif(WrEn==0)DataOut=memory[Adr];elsememory[Adr]=DataIn;endendmodule
11. Data_select
module Data_select(
MemorReg,ALU_out,DataMem_out,
Data_out);input MemorReg;input [31:0] ALU_out;input [31:0] DataMem_out;output [31:0] Data_out;assign Data_out=MemorReg?DataMem_out:ALU_out;
endmodule
多周期CPU设计(verilog)相关推荐
- 31条指令单周期cpu设计(Verilog)-(十)上代码→顶层模块设计总结
说在前面 开发环境:Vivado 语言:Verilog cpu框架:Mips 控制器:组合逻辑 设计思路 按照预先设计好的数据通路图将各个模块连接起来 `timescale 1ns / 1ps mod ...
- 31条指令单周期cpu设计(Verilog)-(二)总体设计
目录 31条指令单周期cpu设计(Verilog)-(一)相关软件 31条指令单周期cpu设计(Verilog)-(二)总体设计 31条指令单周期cpu设计(Verilog)-(三)指令分析 ...
- 单周期CPU设计(Verilog)
2017/06/08: 当时单周期cpu写的比较仓促,没有深入的进行调试,我准备在放假的时候重构一下代码, 然后把博文改进一下,现在实在没有时间,很抱歉~ 不过多周期我有调试过的,所以有需要的可以移步 ...
- 31条指令单周期cpu设计(Verilog)-(四)数据输入输出关系表
说在前面 开发环境:Vivado 语言:Verilog cpu框架:Mips 控制器:组合逻辑 表格作用 这张表用于设计整体的数据通路图 (在第二篇中已经给出来了),而这张总图是用于设计Verilog ...
- 31条指令单周期cpu设计(Verilog)-(三)指令分析
说在前面 开发环境:Vivado 语言:Verilog cpu框架:Mips 控制器:组合逻辑 鸽鸽鸽... 指令分析流程 确定一条指令所需要的具体操作 分析该条指令涉及的部件 确定各个部件的输入输出 ...
- 31条指令单周期cpu设计(Verilog)-(一)相关软件
说在前面 开发环境:Vivado 语言:Verilog cpu框架:Mips 计算机组成原理课程终于结束了,由于以下均为课程学习过程中的内容,所以难免存在各种错误,各位大佬轻喷 相关软件 vivado ...
- 31条指令单周期cpu设计(Verilog)-(八)上代码→指令译码以及控制器
说在前面 开发环境:Vivado 语言:Verilog cpu框架:Mips 控制器:组合逻辑 指令译码器 我们需要根据一条32位的指令的结构确定是哪一条指令 可以根据操作码(op)以及功能码(fun ...
- 31条指令单周期cpu设计(Verilog)-(七)整体代码结构
说在前面 开发环境:Vivado 语言:Verilog cpu框架:Mips 控制器:组合逻辑 结构 sccpu:顶层模块 cpu_ins:指令译码器 cpu_opcode:控制器 其他均是基本模块( ...
- 31条指令单周期cpu设计(Verilog)-(六)指令操作时间表设计
说在前面 开发环境:Vivado 语言:Verilog cpu框架:Mips 控制器:组合逻辑 这张表格又是干啥的呢(+_+)? 废话少说,用来设计控制器的 (红色方框) 设计流程 1. 表头为3 ...
- 31条指令单周期cpu设计(Verilog)-(五)整体数据通路图设计
说在前面 开发环境:Vivado 语言:Verilog cpu框架:Mips 控制器:组合逻辑 这张图是用来干啥的? 我们在用verilog实现这个cpu的时候,一般是先把各个部件单独写一个modul ...
最新文章
- SAP UI5和Angularjs事件处理机制的实现比较
- [设计模式]中介者模式之Events消息传递实现
- Mybatis判断表是否存在
- PCB参数计算神器-Saturn PCB Design Toolkit下载及安装指南
- 1433 mssql 安全_mssqlsql2008安全配置又一给力教程
- SecureCRT连接Linux显示Mysql记录中文乱码
- Android中的神器-放大镜
- 杭州电信域名解析服务器,浙江电信的DNS是多少?
- autocad ios 虚线_教大家AutoCAD2020怎么画虚线的方法
- html中siblings方法,jQuery siblings()方法的用法
- hive计算周是一年的第几周
- 温度报警器 c语言,红外遥控温度报警器
- 【Java】所有做过的面试题
- 微信支付官方揭开刷脸支付神秘面纱
- 智行订票系统需求分析报告
- 游戏鼠标的dpi测试软件,教你自己测试鼠标的DPI
- 斗地主小游戏(JAVA实现)
- FFT(傅里叶快速变换算法)计算频率
- 量化分析师的Python日记【Q Quant兵器谱之偏微分方程3的具体金融学运用】
- 浅谈手机app的推广
热门文章
- win11任务管理器_win11系统怎么打开任务管理器
- android地图画线,绘制折线-在地图上绘制-开发指南-Android 轻量版地图SDK | 高德地图API...
- 使用计算机翻译软件,memoQ(计算机翻译工具)
- EasyExcel读写Excel
- Excel设置行高列宽单元格为正方形,行列比例
- 广告营销用户点击预测分析
- iapp获取桌面壁纸
- windows系统卸载VMware Workstation 并删除注册表残留信息
- 微信小程序登陆,后端接口实现 - springboot
- 记录个js调用浏览器打印功能的代码