单周期CPU设计

终于有点时间了,恰好多周期的设计也已经完成,其实只想写写多周期的,无奈单周期补上才好,哈哈哈~

—————+—————黄金分割线—————+—————

首先要理解什么叫单周期CPU(与后面多周期CPU对比)单周期CPU指的是一条指令的执行在一个时钟周期内完成,然后开始下一条指令的执行,即一条指令用一个时钟周期完成。

单周期CPU的功能:能够实现一些指令功能操作。需设计的指令与格式如下:

==>算术运算指令

(1)add rd , rs, rt  (说明:以助记符表示,是汇编指令;以代码表示,是机器指令


000000


rs(5位)


rt(5位)


rd(5位)


reserved

功能:rd←rs + rt。reserved为预留部分,即未用,一般填“0”。

(2)addi rt , rs ,immediate


000001


rs(5位)


rt(5位)


   immediate(16位)

功能:rt←rs + (sign-extend)immediate;immediate符号扩展再参加“加”运算。

(3)sub rd , rs , rt


000010


rs(5位)


rt(5位)


rd(5位)


reserved

完成功能:rd←rs - rt

==> 逻辑运算指令

(4)ori rt , rs ,immediate


010000


rs(5位)


rt(5位)


   immediate(16位)

功能:rt←rs | (zero-extend)immediate;immediate做“0”扩展再参加“或”运算。

(5)and rd , rs , rt


010001


rs(5位)


rt(5位)


rd(5位)


reserved

功能:rd←rs & rt;逻辑与运算。

(6)or rd , rs , rt


010010


rs(5位)


rt(5位)


rd(5位)


reserved

功能:rd←rs | rt;逻辑或运算。

==> 传送指令

(7)move  rd , rs


100000


rs(5位)


00000


rd(5位)


reserved

功能:rd←rs + $0 ;$0=$zero=0。

==> 存储器读/写指令

(8)sw rt ,immediate(rs) 写存储器


100110


rs(5位)


rt(5位)


    immediate(16位)

功能:memory[rs+ (sign-extend)immediate]←rt;immediate符号扩展再相加。

(9) lw  rt , immediate(rs)读存储器


100111


rs(5位)


rt(5位)


    immediate(16位)

功能:rt ← memory[rs + (sign-extend)immediate];immediate符号扩展再相加。

==> 分支指令

    (10)beq rs,rt,immediate


110000


rs(5位)


rt(5位)


immediate(位移量,16位)

功能:if(rs=rt) pc←pc +4 + (sign-extend)immediate <<2;

特别说明:immediate是从PC+4地址开始和转移到的指令之间指令条数。immediate符号扩展之后左移2位再相加。为什么要左移2位?由于跳转到的指令地址肯定是4的倍数(每条指令占4个字节),最低两位是“00”,因此将immediate放进指令码中的时候,是右移了2位的,也就是以上说的“指令之间指令条数”。

==>停机指令

(11)halt


111111


00000000000000000000000000(26位)

功能:停机;不改变PC的值,PC保持不变。

 设计原理

 

CPU在处理指令时,一般需要经过以下几个步骤:

(1) 取指令(IF):根据程序计数器PC中的指令地址,从存储器中取出一条指令,同时,PC根据指令字长度自动递增产生下一条指令所需要的指令地址,但遇到“地址转移”指令时,则控制器把“转移地址”送入PC,当然得到的“地址”需要做些变换才送入PC。

(2) 指令译码(ID):对取指令操作中得到的指令进行分析并译码,确定这条指令需要完成的操作,从而产生相应的操作控制信号,用于驱动执行状态中的各种操作。

(3) 指令执行(EXE):根据指令译码得到的操作控制信号,具体地执行指令动作,然后转移到结果写回状态。

(4) 存储器访问(MEM):所有需要访问存储器的操作都将在这个步骤中执行,该步骤给出存储器的数据地址,把数据写入到存储器中数据地址所指定的存储单元或者从存储器中得到数据地址单元中的数据。

(5) 结果写回(WB):指令执行的结果或者访问存储器中得到的数据写回相应的目的寄存器中。

单周期CPU,是在一个时钟周期内完成这五个阶段的处理。

MIPS32的指令的三种格式:

R类型:

31       26 25       21 20      16 15       11 10        6 5       0


op


rs


rt


rd


sa


func

6位         5位       5位       5位        5位        6位

I类型:

31        26 25         21 20        16 15                       0


op


rs


rt


immediate

6位         5位          5位                16位

J类型:

31        26 25                                                0


op


address

6位                            26位

其中,

op:为操作码;

rs:为第1个源操作数寄存器,寄存器地址(编号)是00000~11111,00~1F;

rt:为第2个源操作数寄存器,或目的操作数寄存器,寄存器地址(同上);

rd:为目的操作数寄存器,寄存器地址(同上);

sa:为位移量(shift amt),移位指令用于指定移多少位;

func:为功能码,在寄存器类型指令中(R类型)用来指定指令的功能;

immediate:为16位立即数,用作无符号的逻辑操作数、有符号的算术操作数、数据加载(Laod)/数据保存(Store)指令的数据地址字节偏移量和分支指令中相对程序计数器(PC)的有符号偏移量;

address:为地址。

 

图2是一个简单的基本上能够在单周期上完成所要求设计的指令功能的数据通路和必要的控制线路图。其中指令和数据各存储在不同存储器中,即有指令存储器和数据存储器。访问存储器时,先给出地址,然后由读/写信号控制(1-写,0-读。当然,也可以由时钟信号控制,但必须在图上标出)。对于寄存器组,读操作时,先给出地址,输出端就直接输出相应数据;而在写操作时,在 WE使能信号为1时,在时钟边沿触发写入。图中控制信号作用如表1所示,表2是ALU运算功能表。

表1 控制信号的作用


控制信号名


状态“0”


状态“1”


PCWre


PC不更改,相关指令:halt


PC更改,相关指令:除指令halt外


ALUSrcB


来自寄存器堆data2输出,相关指令:add、sub、or、and、move、beq


来自sign或zero扩展的立即数,相关指令:addi、ori、sw、lw


ALUM2Reg


来自ALU运算结果的输出,相关指令:add、addi、sub、ori、or、and、move


来自数据存储器(Data MEM)的输出,相关指令:lw


RegWre


无写寄存器组寄存器,相关指令:

sw、halt


寄存器组写使能,相关指令:add、addi、sub、ori、or、and、move、lw


InsMemRW


读指令存储器(Ins. Data),初始化为0


写指令存储器


DataMemRW


读数据存储器,相关指令:lw


写数据存储器,相关指令:sw


ExtSel


相关指令:ori,(zero-extend)immediate(0扩展


相关指令:addi、sw、lw、beq,

(sign-extend)immediate(符号扩展


PCSrc


PC←PC+4,相关指令:add、sub、ori、or、and、move、sw、lw、beq(zero=0)


PC←PC+4+(sign-extend)immediate,同时zero=1,相关指令:beq


RegOut


写寄存器组寄存器的地址,来自rt字段,相关指令:addi、ori、lw


写寄存器组寄存器的地址,来自rd字段,相关指令:add、sub、and、or、move


ALUOp[2..0]


ALU 8种运算功能选择(000-111),看功能表

相关部件及引脚说明:

InstructionMemory指令存储器

Iaddr,指令存储器地址输入端口

IDataIn,指令存储器数据输入端口(指令代码输入端口)

IDataOut,指令存储器数据输出端口(指令代码输出端口)

RW,指令存储器读写控制信号,为1写,为0读

DataMemory数据存储器

Daddr,数据存储器地址输入端口

DataIn,数据存储器数据输入端口

DataOut,数据存储器数据输出端口

RW,数据存储器读写控制信号,为1写,为0读

RegisterFile:(寄存器组)

Read Reg1,rs寄存器地址输入端口

Read Reg2,rt寄存器地址输入端口

Write Reg,将数据写入的寄存器端口,其地址来源rt或rd字段

Write Data,写入寄存器的数据输入端口

Read Data1,rs寄存器数据输出端口

Read Data2,rt寄存器数据输出端口

WE,写使能信号,为1时,在时钟上升沿写入

ALU

result,ALU运算结果

zero,运算结果标志,结果为0输出1,否则输出0

表2 ALU运算功能表


ALUOp[2..0]


功能


描述


000


A + B



001


A – B



010


B – A



011


A ∨ B



100


A ∧ B



101


/A ∧ B


A非与B


110


A ? B


异或


111


A ⊙ B


同或

需要说明的是根据要实现的指令功能要求画出以上数据通路图,和确定ALU的运算功能(当然,以上指令没有完全用到提供的ALU所有功能,但至少必须能实现以上指令功能操作)。从数据通路图上可以看出控制单元部分需要产生各种控制信号,当然,也有些信号必须要传送给控制单元。从指令功能要求和数据通路图的关系得出以上表1,这样,从表1可以看出各控制信号与相应指令之间的相互关系,根据这种关系就可以得出控制信号与指令之间的关系表(如下),再根据关系表可以写出各控制信号的逻辑表达式,这样控制单元部分就可实现了。

表3 控制信号与指令的关系表


控制信号


指令


z


PCWre


ALUSrcB


ALUM2Reg


RegWre


InsMemRW


DataMemRW


ExtSel


PCSrc


RegOut


ALUOp[2..0]


add


x


1


0


0


1


0


x


x


0


1


000


addi


x


1


1


0


1


0


x


1


0


0


000


sub


x


1


0


0


1


0


x


x


0


1


001


ori


x


1


1


0


1


0


x


0


0


0


011


and


x


1


0


0


1


0


x


x


0


1


100


or


x


1


0


0


1


0


x


x


0


1


011


move


x


1


0


0


1


0


x


x


0


1


000


sw


x


1


1


x


0


0


1


1


0


x


000


lw


x


1


1


1


1


0


0


1


0


0


000


beq


0


1


0


x


0


0


x


1


0


x


001


1


1


0


x


0


0


x


1


1


x


001


halt


x


0


x


x


x


0


x


x


x


x


xxx

 

分析与设计

 

根据实验原理中的单周期CPU数据通路和控制线路图,我们可以清楚的知道单周期CPU的设计应包括controlUnit,RegisterFile, ALU, DataMemory, instructionMemory, PC, signZeroExtend这几个模块,其中为了运行整个CPU还需要加入一个顶层模块(singleCycleCPU)来调用这七个模块,所以自然地,这七个模块为顶层模块的子模块。设计流程逻辑图如下:

1、控制单元(controlUnit.v)

根据数据通路图可以知道,控制单元的功能是接收一个6位的操作码(opCode)和一个标志符(zero)作为输入,输出PCWre、ALUSrcB等控制信号,各控制信号的作用见实验原理的控制信号作用表(表1),从而达到控制各指令的目的。其中模块内部实现则根据实验原理中控制信号与指令的关系表(表3)列出各信号的逻辑表达式从而实现各信号的输出。比如:

ALUOp的表达式为:ALUOp[2]=i_and

ALUOp[1]=i_ori | i_or

ALUOp[0]=i_sub | i_ori | i_or | i_beq

所以其实现为:assignALUOp[2] = (opCode == 6‘b010001)? 1 : 0;

assignALUOp[1] = (opCode == 6‘b010000 || opCode == 6‘b010010)? 1 : 0;

assign ALUOp[0] = (opCode == 6‘b000010 || opCode == 6‘b010000|| opCode == 6‘b010010 || opCode == 6‘b110000)? 1 : 0;

整个模块设计如下:

[plain] view plain copy

  1. </pre><pre name="code" class="plain">`timescale 1ns / 1ps
  2. module controlUnit(opCode, zero, PCWre, ALUSrcB, ALUM2Reg, RegWre, InsMemRW, DataMemRW, ExtSel, PCSrc, RegOut, ALUOp);
  3. input [5:0] opCode;
  4. input zero;
  5. output PCWre, ALUSrcB, ALUM2Reg, RegWre, InsMemRW, DataMemRW, ExtSel, PCSrc, RegOut;
  6. output[2:0] ALUOp;
  7. assign PCWre = (opCode == 6‘b111111)? 0 : 1;
  8. assign ALUSrcB = (opCode == 6‘b000001 || opCode == 6‘b010000 || opCode == 6‘b100110 || opCode == 6‘b100111)? 1 : 0;
  9. assign ALUM2Reg = (opCode == 6‘b100111)? 1 : 0;
  10. assign RegWre = (opCode == 6‘b100110 || opCode == 6‘b111111)? 0 : 1;
  11. assign InsMemRW = 0;
  12. assign DataMemRW = (opCode == 6‘b100111)? 0 : 1;
  13. assign ExtSel = (opCode == 6‘b010000)? 0 : 1;
  14. assign PCSrc = (opCode == 6‘b110000 && zero == 1)? 1 : 0;
  15. assign RegOut = (opCode == 6‘b000001 || opCode == 6‘b010000 || opCode == 6‘b100111)? 0 : 1;
  16. assign ALUOp[2] = (opCode == 6‘b010001)? 1 : 0;
  17. assign ALUOp[1] = (opCode == 6‘b010000 || opCode == 6‘b010010)? 1 : 0;
  18. assign ALUOp[0] = (opCode == 6‘b000010 || opCode == 6‘b010000 || opCode == 6‘b010010 || opCode == 6‘b110000)? 1 : 0;
  19. endmodule

2、算术运算单元(ALU.v)

模块ALU接收寄存器的数据和控制信号作为输入,将结果输出,具体设计如下:

[html] view plain copy

  1. `timescale 1ns / 1ps
  2. module ALU(ReadData1, ReadData2, inExt, ALUSrcB, ALUOp, zero, result);
  3. input [31:0] ReadData1, ReadData2, inExt;
  4. input ALUSrcB;
  5. input [2:0] ALUOp;
  6. output zero;
  7. output [31:0] result;
  8. reg zero;
  9. reg [31:0] result;
  10. wire [31:0] B;
  11. assign B = ALUSrcB? inExt : ReadData2;
  12. always @(ReadData1 or ReadData2 or inExt or ALUSrcB or ALUOp or B)
  13. begin
  14. case(ALUOp)
  15. // A + B
  16. 3‘b000: begin
  17. result = ReadData1 + B;
  18. zero = (result == 0)? 1 : 0;
  19. end
  20. // A - B
  21. 3‘b001: begin
  22. result = ReadData1 - B;
  23. zero = (result == 0)? 1 : 0;
  24. end
  25. // B - A
  26. 3‘b010: begin
  27. result = B - ReadData1;
  28. zero = (result == 0)? 1 : 0;
  29. end
  30. // A ∨ B
  31. 3‘b011: begin
  32. result = ReadData1 | B;
  33. zero = (result == 0)? 1 : 0;
  34. end
  35. // A ∧ B
  36. 3‘b100: begin
  37. result = ReadData1 & B;
  38. zero = (result == 0)? 1 : 0;
  39. end
  40. // /A ∧ B
  41. 3‘b101: begin
  42. result = (~ReadData1) & B;
  43. zero = (result == 0)? 1 : 0;
  44. end
  45. // A ⊕ B
  46. 3‘b110: begin
  47. result = ReadData1 ^ B;
  48. zero = (result == 0)? 1 : 0;
  49. end
  50. // A ⊙ B
  51. 3‘b111: begin
  52. result = ReadData1 ^~ B;
  53. zero = (result == 0)? 1 : 0;
  54. end
  55. endcase
  56. end
  57. endmodule

3、PC单元(PC.v)

PC单元以时钟信号clk、重置标志Reset、立即数以及PCWreck和PCSrc两个信号控制为输入,输出当前PC地址,具体设计如下:

[html] view plain copy

  1. `timescale 1ns / 1ps
  2. module PC(clk, Reset, PCWre, PCSrc, immediate, Address);
  3. input clk, Reset, PCWre, PCSrc;
  4. input [31:0] immediate;
  5. output [31:0] Address;
  6. reg [31:0] Address;
  7. /*initial begin
  8. Address = 0;
  9. end*/
  10. always @(posedge clk or negedge Reset)
  11. begin
  12. if (Reset == 0) begin
  13. Address = 0;
  14. end
  15. else if (PCWre) begin
  16. if (PCSrc) Address = Address + 4 + immediate*4;
  17. else Address = Address + 4;
  18. end
  19. end
  20. endmodule

4、 扩展单元(signZeroExtend.v)

扩展单元的设计比较简单,其功能就是将一个16位的立即数扩展到32位,具体模块设计如下:

[html] view plain copy

  1. `timescale 1ns / 1ps
  2. module signZeroExtend(immediate, ExtSel, out);
  3. input [15:0] immediate;
  4. input ExtSel;
  5. output [31:0] out;
  6. assign out[15:0] = immediate;
  7. assign out[31:16] = ExtSel? (immediate[15]? 16‘hffff : 16‘h0000) : 16‘h0000;
  8. endmodule

5、数据存储单元(DataMemory.v)

数据存储单元的功能是读取数据,根据数据通路图可以有如下模块设计:

[html] view plain copy

  1. `timescale 1ns / 1ps
  2. module dataMemory(DAddr, DataIn, DataMemRW, DataOut);
  3. input [31:0] DAddr, DataIn;
  4. input DataMemRW;
  5. output reg [31:0] DataOut;
  6. reg [31:0] memory[0:31];
  7. // read data
  8. always @(DataMemRW) begin
  9. if (DataMemRW == 0) assign DataOut = memory[DAddr];
  10. end
  11. // write data
  12. integer i;
  13. initial begin
  14. for (i = 0; i < 32; i = i+1) memory[i] <= 0;
  15. end
  16. always @(DataMemRW or DAddr or DataIn)
  17. begin
  18. if (DataMemRW) memory[DAddr] = DataIn;
  19. end
  20. endmodule

6、指令存储单元(instructionMemory.v)

根据当前的PC地址得到对应的op,rs,rt,rd以及immediate.

内部实现:

将需要测试的汇编指令程序转化为指令代码,当然,每个人都可以有自己的测试指令,能正确转化为指令代码就好。为了书写的简便,我们可以将32位的二进制指令代码转化为16进制。具体测试表设计如下:


地址


汇编程序


指令代码


op(6)


rs(5)


rt(5)


rd(5)/immediate (16)


16进制数代码


0x00000004


addi  $1,$0,8


000001


00000


00001


0000 0000 0000 1000


=


04010008


0x00000008


ori  $2,$0,12


010000


00000


00010


0000 0000 0000 1100


=


4002000C


0x0000000C


add  $3,$1,$2


000000


00001


00010


00011 00000000000


=


00221800


0x00000010


sub  $4,$2,$1


000010


00010


00001


00100 00000000000


=


08412000


0x00000014


and  $5,$1,$2


010001


00001


00010


00101 00000000000


=


44222800


0x00000018


or  $6,$1,$2


010010


00001


00010


00110 00000000000


=


48223000


0x0000001C


beq  $1,$2,4 (转030)


110000


00001


00010


0000 0000 0000 0100


=


C0220004


0x00000020


move  $7,$1


100000


00001


00000


00111 00000000000


=


80203800


0x00000024


sw  $1,1($7)


100110


00111


00001


0000 0000 0000 0001


=


98E10001


0x00000028


lw  $2,0($1)


100111


00001


00010


0000 0000 0000 0000


=


9C220000


0x0000002C


beq $2,$7,-5 (转01C)


110000


00010


00111


1111 1111 1111 1011


=


C047FFFB


0x00000030


halt


111111


00000


00000


0000000000000000


=


FC000000

其次,为了存储这些指令代码,可以申请一个32位的二进制数组来存储它们,最后根据PC地址得到对应的op,rs,rt,immediate等,具体模块设计如下:

[html] view plain copy

  1. `timescale 1ns / 1ps
  2. module instructionMemory(
  3. input [31:0] pc,
  4. input InsMemRW,
  5. output [5:0] op,
  6. output [4:0] rs, rt, rd,
  7. output [15:0] immediate);
  8. wire [31:0] mem[0:15];
  9. assign mem[0] = 32‘h00000000;
  10. // addi  $1,$0,8
  11. assign mem[1] = 32‘h04010008;
  12. // ori  $2,$0,12
  13. assign mem[2] = 32‘h4002000C;
  14. // add  $3,$1,$2
  15. assign mem[3] = 32‘h00221800;
  16. // sub  $4,$2,$1
  17. assign mem[4] = 32‘h08412000;
  18. // and  $5,$1,$2
  19. assign mem[5] = 32‘h44222800;
  20. // or  $6,$1,$2
  21. assign mem[6] = 32‘h48223000;
  22. // beq  $1,$2,4 (转030)
  23. assign mem[7] = 32‘hC0220004;
  24. // move  $7,$1
  25. assign mem[8] = 32‘h80203800;
  26. // sw  $1,1($7)
  27. assign mem[9] = 32‘h98E10001;
  28. // lw  $2,0($1)
  29. assign mem[10] = 32‘h9C220000;
  30. // beq $2,$7,-5 (转01C)
  31. assign mem[11] = 32‘hC047FFFB;
  32. // halt
  33. assign mem[12] = 32‘hFC000000;
  34. assign mem[13] = 32‘h00000000;
  35. assign mem[14] = 32‘h00000000;
  36. assign mem[15] = 32‘h00000000;
  37. // output
  38. assign op = mem[pc[5:2]][31:26];
  39. assign rs = mem[pc[5:2]][25:21];
  40. assign rt = mem[pc[5:2]][20:16];
  41. assign rd = mem[pc[5:2]][15:11];
  42. assign immediate = mem[pc[5:2]][15:0];
  43. endmodule

7、寄存器文件单元(registerFile.v)

寄存器文件单元的功能是接收instructionMemory中的rs,rt,rd作为输入,输出对应寄存器的数据,从而达到取寄存器里的数据的目的。需要注意的是,在其内部实现的过程中,为了防止0号寄存器写入数据需要在writeReg的时候多加入一个判断条件,即writeReg不等于0时写入数据。具体设计如下:

[html] view plain copy

  1. `timescale 1ns / 1ps
  2. module registerFile(clk, RegWre, RegOut, rs, rt, rd, ALUM2Reg, dataFromALU, dataFromRW, Data1, Data2);
  3. input clk, RegOut, RegWre, ALUM2Reg;
  4. input [4:0] rs, rt, rd;
  5. input [31:0] dataFromALU, dataFromRW;
  6. output [31:0] Data1, Data2;
  7. wire [4:0] writeReg;
  8. wire [31:0] writeData;
  9. assign writeReg = RegOut? rd : rt;
  10. assign writeData = ALUM2Reg? dataFromRW : dataFromALU;
  11. reg [31:0] register[0:31];
  12. integer i;
  13. initial begin
  14. for (i = 0; i < 32; i = i+1) register[i] <= 0;
  15. end
  16. // output
  17. assign Data1 = register[rs];
  18. assign Data2 = register[rt];
  19. // Write Reg
  20. always @(posedge clk or RegOut or RegWre or ALUM2Reg or writeReg or writeData) begin
  21. if (RegWre && writeReg) register[writeReg] = writeData;  // 防止数据写入0号寄存器
  22. end
  23. endmodule

8、顶层模块(singleStyleCPU)

顶层模块(singleStyleCPU)是整个CPU的控制模块,通过连接各个子模块来达到运行CPU的目的,整个模块设计可以如下:

[html] view plain copy

  1. `include "controlUnit.v"
  2. `include "dataMemory.v"
  3. `include "ALU.v"
  4. `include "instructionMemory.v"
  5. `include "registerFile.v"
  6. `include "signZeroExtend.v"
  7. `include "PC.v"
  8. `timescale 1ns / 1ps
  9. module SingleCycleCPU(
  10. input clk, Reset,
  11. output wire [5:0] opCode,
  12. output wire [31:0] Out1, Out2, curPC, Result);
  13. wire [2:0] ALUOp;
  14. wire [31:0] ExtOut, DMOut;
  15. wire [15:0] immediate;
  16. wire [4:0] rs, rt, rd;
  17. wire zero, PCWre, PCSrc, ALUSrcB, ALUM2Reg, RegWre, InsMemRW, DataMemRW, ExtSel, RegOut;
  18. // module ALU(ReadData1, ReadData2, inExt, ALUSrcB, ALUOp, zero, result);
  19. ALU alu(Out1, Out2, ExtOut, ALUSrcB, ALUOp, zero, Result);
  20. // module PC(clk, Reset, PCWre, PCSrc, immediate, Address);
  21. PC pc(clk, Reset, PCWre, PCSrc, ExtOut, curPC);
  22. // module controlUnit(opCode, zero, PCWre, ALUSrcB, ALUM2Reg, RegWre, InsMemRW, DataMemRW, ExtSel, PCSrc, RegOut, ALUOp);
  23. controlUnit control(opCode, zero, PCWre, ALUSrcB, ALUM2Reg, RegWre, InsMemRW, DataMemRW, ExtSel, PCSrc, RegOut, ALUOp);
  24. // module dataMemory(DAddr, DataIn, DataMemRW, DataOut);
  25. dataMemory datamemory(Result, Out2, DataMemRW, DMOut);
  26. /* module instructionMemory(
  27. input [31:0] pc,
  28. input InsMemRW,
  29. input [5:0] op,
  30. input [4:0] rs, rt, rd,
  31. output [15:0] immediate);*/
  32. instructionMemory ins(curPC, InsMemRW, opCode, rs, rt, rd, immediate);
  33. // module registerFile(clk, RegWre, RegOut, rs, rt, rd, ALUM2Reg, dataFromALU, dataFromRW, Data1, Data2);
  34. registerFile registerfile(clk, RegWre, RegOut, rs, rt, rd, ALUM2Reg, Result, DMOut, Out1, Out2);
  35. // module signZeroExtend(immediate, ExtSel, out);
  36. signZeroExtend ext(immediate, ExtSel, ExtOut);
  37. endmodule

[html] view plain copy

最后就是测试程序(testSCPU.v)

从顶层模块中可以看出整个CPU的输入只有时钟信号clk和重置信号Reset,所以测试程序代码比较简单。(说明:下面是在测试文件中额外加的,因为其他初始化数据ISE已经自动生成,点赞)

Reset = 1; //初始化PC地址,为0

forever #100 clk = ~clk;

一个简单的单周期就设计完成了,重点是要学会其中涉及到的模块化思想,这中模块化的分解思想应用极其广泛,所以,最好学会熟练使用。

表脸粘一下仿真结果好了:

单周期CPU卒,见多周期CPU,2333~

原文:http://blog.csdn.net/zhaokx3/article/details/51493842

时间: 2024-10-06 00:28:02

单周期CPU设计的相关文章

多周期CPU设计

------更新一下bug(测试代码有毒)------- 和单周期CPU的设计相同,都是为了实现一系列的指令功能,但需要指出的是何为多周期(注意与前面写道的单周期的区别,这也是设计的关键之处) 多周期CPU指的是将整个CPU的执行过程分成几个阶段,每个阶段用一个时钟去完成,然后开始下一条指令的执行,而每种指令执行时所用的时钟数不尽相同,这就是所谓的多周期CPU. 理解完多周期与单周期的区别后,开始我们的多周期CPU设计之路(可以随时对应单周期的设计,注意联系与区别). 需要设计的指令及格式如下:

P4 - Verilog单周期CPU

1 module mips( 2 input clk, 3 input reset 4 ); 5 6 wire [31:0] PC,nPC,PC_4; 7 wire [31:0] Instr; 8 wire [31:0] RD1,RD2,WD; 9 wire [31:0] ALU_B,ALUResult; 10 wire Zero; 11 wire [31:0] EXTResult,DMResult; 12 wire [4:0] WriteReg; 13 14 wire RegWrite,ALU

基于模型机的Micro cpu设计

第一章    模型机基本结构 由功能分析, 本次组成原理实验中设计的模型机包含下面这些部件:算术逻辑运算部件(ALU).程序计数器(PC).指令寄存器(IR).存储器(RAM).时序和微程序控制部件.模型机的数据通路为单总线结构,总线宽度为8位. 第二章    设计思想 1.基于状态机的模型机 如图1所示,整体模型机的设计采用了状态机的思想,将cpu的取指令.指令译码.指令执行所对应的操作拆分到各个状态中,并由此设计模型机的微操作. 图1 - 时钟控制信号状态机模型示意图 2.周期.节拍.脉冲制

记录:掌握单页网站设计的5大技巧

在设计师们的不懈探究之下,单页设计已经摘掉了混乱单调的帽子,构建起了一套相对比较完善的设计体系,保持简洁而漂亮的设计,重视内容,强调清晰明了的表达.从用户体验的角度上来看,单页设计确实有其优势也有缺陷,但是值得注意的是,用户的确是喜欢单页网站的浏览方式,这也是单页设计流行开来的基石. ·单页网站导航方式简单,用户不易迷路,只需上下滚动. ·单页网站内容更专注,信息传递更清晰,更有针对性. ·单页网站几乎可以在全平台设备上流畅浏览,滚动和滑动浏览替代了点击 而设计单页网站最大的挑战在于让用户保持滚

基于Extjs的web表单设计器 第二节——表单控件设计

这一节介绍表单设计器的常用控件的设计. 在前面两章节的附图中我已经给出了表单控件的两大分类:区域控件.常用控件.这里对每个分类以及分类所包含的控件的作用进行一一的介绍,因为它们很重要,是表单设计器的基本元素,更是核心组成部门. 一.区域控件,它主要包含三个类型的控件:卡片区域.表格区域.混合区域.这三个控件是我们的其他控件的容器或者叫包装器,相当于VS里面的各种Panel.它们很重要,每种区域控件的作用都不一样,能够包含的控件类型也不大一样,它们三个区域相互配合使用,可以为我们的表单提供强大的支

cpu设计--&gt;cpu指令设计与全程逻辑分析

CPU指令设计,除了命名之外,更重要的是分析出指令如何才能够实现.对于图 3 1的CPU结构,如果指令是预先放到irom里的,那么,指令执行时要一条一条地从irom取出来,放到ir指令寄存器中,提供给control进行分析执行.每一条指令如何转变成机器动作,CPU的设计者必须认真地进行分析和规划.这一过程叫指令全程动作分析,简称指令全程分析. 我们针对图 3-1的结构,可以尝试设计一些用符号表示的汇编指令,然后对这些汇编指令如何实现,进行细致地分析.汇编指令的二进制数表示就是机器指令.汇编指令和

网页表单文档设计及技术实现

在很多业务流程应用中,业务审批单的样式.内容多变,然而系统对业务表单数据并不敏感,因此,不使用对应的关系型数据表,而采用NoSQL技术来优化设计.因为NoSQL无需事先为要存储的数据建立字段,随时可以存储自定义的数据格式.按NoSQL的特性,可以灵活进行schema结构(列定义)的修改,理论上应该可以很好支持这些多样表单的持久化保存.基于上述原因,业务审批单采用网页表单文档设计. 网页表单设计 首先,我们看一看在HTML表单元素(对象)中使用自定义属性的示例: <input fieldid=&quo

计算机组成与设计(八)—— 单周期处理器

处理器的设计步骤 分析指令系统,得出对数据通路的需求 为数据通路选择合适的组件 连接组件,建立数据通路 分析每条指令的实现,以确定控制信号 集成控制信号,完成完整的数据通路 具体设计步骤 (一)分析指令系统 MIPS的所有指令是非常多的,我们只实现其简化版,包含如下6种: (二)需求分析 需求分析,需要存放指令地址的32位寄存器(PC),需要存放指令的存储器,可读,数据和指令均为32位(MEM[PC]).还需要一个寄存器堆,用来保存源操作数和目的操作数,一个ALU进行运算. (三)选择组件 所以

简单CPU设计实践

目录 开始前的话. 3 总体组成. 3 运算器. 3 补码... 3 算术单元... 4 逻辑单元... 5 算术逻辑单元... 6 移位器... 7 运算器综合... 8 溢出判断... 9 运算器设计的总结和补充... 11 寄存器组. 11 注意事项... 11 使能端... 12 构建寄存器组... 12 控制器. 13 程序计数器... 14 指令寄存器... 14 数据通路设计... 14 控制字... 15 指令译码器... 16 状态寄存器... 18 控制器综合... 18 C