设计一个简易的处理器(3)--SEQ CPU的实现(1): 将指令组织成阶段

本文介绍SEQCPU的设计原理及Y86指令集的处理流程,详细阐述了SEQCPU的各组成部分与时序电路,并对Y86指令的执行阶段进行了分析。

本文是介绍SEQCPU(Sequential CPU)的实现的第一篇,着重介绍如何将Y86的指令组织成阶段.

 

 

Y86/SEQ CPU

————

"设计一个简易的处理器"的第一篇中,我介绍了一个简易的指令集系统Y86,这里的SEQ CPU使用的就是Y86指令集.

指令集详见(http://blog.youkuaiyun.com/dennis_fan/article/details/8226311).

需要指出的是, CPU是一个数字电路,由组合电路和时序电路组成.我们知道,组合电路没有状态,而时序电路是有状态的.特别的是,程序员的可见状态在硬件实现上就是一个一个的时序电路来完成的.

 

SEQ CPU的状态(时序电路):

  •  程序计数器(Program counter register, PC)
  • 条件码寄存器(Conditon code register, CC)
  • 寄存器文件(Register File)
  • 存储器(Memory)

这些时序电路随着时钟上升而更新.

 

SEQ CPU的组合电路:

  • 算术逻辑单元(ALU)
  • 控制逻辑(Control logic)
  • 读存储器(Memory reads):读指令寄存器,读寄存器文件,读数据寄存器.

 

 

指令处理阶段

————

为了降低实现的复杂性,采用统一的框架,这样可以共用一些部件.我们将Y86的指令处理组织成如下几个阶段:

  • 取指(Fetch):从指令寄存器读取指令.
  • 译码(Decode):读取程序寄存器.
  • 执行(Execute): ALU计算结果(分为两种一种是计算值(用于更新程序寄存器),一种是计算存储器引用的有效地址).
  • 访存(Memory):读写存储器.
  • 写回(Write Back):写回寄存器文件.
  • 更新PC(PC update):PC设置成下一条指令的地址.

先大家只需要了解一下一条指令执行的要经历的阶段,后面会分析Y86的具体指令的执行过程.

需要注意的两点:

1.在统一框架下,每条指令都会经历以上所有阶段.

2.SEQ/SEQ+,各个阶段是顺序进行的,但一个阶段内的内容基本上(有例外,稍后再说)是并行执行的.

 

 

Y86指令的执行

————

Y86的指令及其编码可以参看我以前的blog.

下面是各种指令处理的各个阶段,大家可以一扫而过,看我的分析结果,再对照着图就很容易理解.

 


看到上面的指令处理的各个阶段是不是天花乱坠啊.其实一点不复杂,因为使用的是统一的框架.总结起来就如下几点:

(1).首先要看指令到底要干啥,它的操作数是啥,明确数据流的方向.

      比如opl, rrmovl, irmovl, cmovXX都不涉及到存储器,都是将Execute阶段中的执行结果valE给某个程序寄存器.(数据流方向: valE->程序寄存器).

      比如mrmovl, popl的数据流方向是:存储器->程序寄存器.以为这肯定要从存储器中取出valM,再给这个程序寄存器.

     比如rmmovl的数据流方向是:程序寄存器->存储器,肯定会写入存储器.

(2).写入程序寄存器的数据有两种来源,一种是valE(opl,rrmovl, irmovl, pushl,  popl, call, ret,cmovXX),一种是valM(mrmovl, popl).

(3). pushl, popl, call, ret都涉及了""(存储器),都会更新%esp(%esp+/-4:在执行阶段计算出来valE).valE写回%esp.

(4). opl在执行阶段会设置CC, cmovXX, jXX在执行阶段会有一个判断逻辑.

(5).只有rmmovl, pushlcall需要写回存储器.

(6).统一处理的原则:excute阶段,valA尽量不参与运算,使用valB参与运算;memory阶段,都是valA参与运算(为了使得pushlrmmovl统一处理).

(7).总结     

阶段名

信号

注释

Fetch

icode:ifun

rA, rB

valC

valP

Read instruction byte

Read register byte

Read constant D or V

Compute next PC

Decode

valA

valB

Read operand A

Read operand B

Execute

valE

Cond code

Perform ALU operation

Set/Test Condition code register

Memory

valM

Memery read/write

Write back

dstE

dstM

Write back ALU result
Write back memory result

PC update

PC

Update PC

 

 

疑点

————

1. rrmovlexecute阶段本不需要运算,为什么要执行"valE = 0+valA"?

   :使用的是统一的框架,每条指令都必须通过每个阶段.这样做还有一个好处,减少信号传递的数量.写回都是通过valEvalM,而不需要valA.

 

2.为什么是mrmovl D(rB), rA而不是 mrmovl D(rA), rB?

   :统一处理 mrmvolrmmovl.这样保证了"execute阶段, valA尽量不参与运算,使用valB参与运算".

 

3. popl rAWrite back阶段需要写两个寄存器.这两个写应该是有次序的啊?

   :是的.为了保证"popl%esp"的语义同IA32一致,"R[%esp]<-valE"必须在"R[rA]<-valM"之前,这意味着按照只能在上升沿update的规则,就需要2cycles来执行(违反了原则)

 

4. pushl rA怎么没有问题?

    :由于在SEQ CPU.因为读取的值在某根信号线(指的是valA信号)上存在着.即便是"pushl %esp", %esp的值已经在valA信号线上了,只需要将valA的值写回存储器即可.

 

 

reference:

1. 深入理解计算机系统(原书第2版)

 

(版权所有,转载时请注明作者和出处-dennis_fan)

`define NOP 5&#39;b00000 `define HALT 5&#39;b00001 `define LOAD 5&#39;b00010 `define STORE 5&#39;b00011 `define LDIH 5&#39;b10000 `define ADD 5&#39;b01000 `define ADDI 5&#39;b01001 `define ADDC 5&#39;b10001 `define SUB 5&#39;b01011 `define SUBI 5&#39;b10011 `define SUBC 5&#39;b10111 `define CMP 5&#39;b01100 // control `define JUMP 5&#39;b11000 `define JMPR 5&#39;b11001 `define BZ 5&#39;b11010 `define BNZ 5&#39;b11011 `define BN 5&#39;b11100 `define BNN 5&#39;b11101 `define BC 5&#39;b11110 `define BNC 5&#39;b11111 // logic / shift `define AND 5&#39;b01101 `define OR 5&#39;b01111 `define XOR 5&#39;b01110 `define SLL 5&#39;b00100 `define SRL 5&#39;b00110 `define SLA 5&#39;b00101 `define SRA 5&#39;b00111 // general register `define gr0 3&#39;b000 `define gr1 3&#39;b001 `define gr2 3&#39;b010 `define gr3 3&#39;b011 `define gr4 3&#39;b100 `define gr5 3&#39;b101 `define gr6 3&#39;b110 `define gr7 3&#39;b111 // FSM `define idle 1&#39;b0 `define exec 1&#39;b1 /******* the whole module CPU is made of Instuction_Mem module, PCPU module and Data_Mem module ********/ module CPU( input wire clk, clock, enable, reset, start, input wire[3:0] select_y, output [7:0] select_segment, output [3:0] select_bit ); wire[15:0] d_datain; wire[15:0] i_datain; wire[7:0] d_addr; wire[7:0] i_addr; wire[15:0] d_dataout; wire d_we; wire[15:0] y; reg [20:0] count = 21&#39;b0; Instruction_Mem instruction(clock,reset,i_addr,i_datain); PCPU pcpu(clock, enable, reset, start, d_datain, i_datain, select_y, i_addr, d_addr, d_dataout, d_we, y); Data_memory data(clock, reset, d_addr, d_dataout, d_we, d_datain); Board_eval eval(clk, y, select_segment, select_bit); endmodule /************************ Instruction memeory module *****************************/ module Instruction_Mem ( input wire clock, reset, input wire[7:0] i_addr, output [15:0] i_datain ); reg[15:0] i_data[255:0]; // 8 bits pc address to get instructions reg[15:0] temp; always@(negedge clock) begin if(!reset) begin i_data[0] <= {`LOAD, `gr1, 1&#39;b0, `gr0, 4&#39;b0000}; i_data[1] <= {`LOAD, `gr2, 1&#39;b0, `gr0, 4&#39;b0001}; i_data[2] <= {`ADD, `gr3, 1&#39;b0, `gr1, 1&#39;b0, `gr2}; i_data[3] <= {`SUB, `gr3, 1&#39;b0, `gr1, 1&#39;b0, `gr2}; i_data[4] <= {`CMP, `gr3, 1&#39;b0, `gr2, 1&#39;b0, `gr1}; i_data[5] <= {`ADDC, `gr3, 1&#39;b0, `gr1, 1&#39;b0, `gr2}; i_data[6] <= {`SUBC, `gr3, 1&#39;b0, `gr1, 1&#39;b0, `gr2}; i_data[7] <= {`SLL, `gr2, 1&#39;b0, `gr3, 1&#39;b0, 3&#39;b001}; i_data[8] <= {`SRL, `gr3, 1&#39;b0, `gr1, 1&#39;b0, 3&#39;b001}; i_data[9] <= {`SLA, `gr4, 1&#39;b0, `gr1, 1&#39;b0, 3&#39;b001}; i_data[10] <= {`SRA, `gr5, 1&#39;b0, `gr1, 1&#39;b0, 3&#39;b001}; i_data[11] <= {`STORE, `gr3, 1&#39;b0, `gr0, 4&#39;b0010}; i_data[12] <= {`HALT, 11&#39;b000_0000_0000}; end else begin temp = i_data[i_addr[7:0]]; end end assign i_datain = temp; endmodule /**************************** PCPU module ***************************/ module PCPU( input wire clock, enable, reset, start, input wire [15:0] d_datain, // output from Data_Mem module input wire [15:0] i_datain, // output from Instruction_Mem module input wire [3:0] select_y, // for the board evaluation output [7:0] i_addr, output [7:0] d_addr, output [15:0] d_dataout, output d_we, output [15:0] y ); reg [15:0] gr [7:0]; reg nf, zf, cf; reg state, next_state; reg dw; reg [7:0] pc; reg[15:0] y_forboard; reg [15:0] id_ir; reg [15:0] wb_ir; reg [15:0] ex_ir; reg [15:0] mem_ir; reg [15:0] smdr = 0; reg [15:0] smdr1 = 0; reg signed [15:0] reg_C1; //有符号 reg signed [15:0] reg_A; reg signed [15:0] reg_B; reg signed [15:0] reg_C; reg signed [15:0] ALUo; //************* CPU control *************// always @(posedge clock) begin if (!reset) state <= `idle; else state <= next_state; end always @(*) begin case (state) `idle : if ((enable == 1&#39;b1) && (start == 1&#39;b1)) next_state <= `exec; else next_state <= `idle; `exec : if ((enable == 1&#39;b0) || (wb_ir[15:11] == `HALT)) next_state <= `idle; else next_state <= `exec; endcase end assign i_addr = pc; // 准备下一条指令的地址 //************* IF *************// always @(posedge clock or negedge reset) begin if (!reset) begin id_ir <= 16&#39;b0; pc <= 8&#39;b0; end else if (state ==`exec) // Stall happens in IF stage, always compare id_ir with i_datain to decide pc and id_ir begin // 当即将被执行的指令要用到之前load写入的值时, stall two stages , id and ex. /* 指令中后第二、三个操作数均为寄存器时,需要判断LOAD的第一个操作数是否与这些指令的后两个寄存器有冲突 为一部分算数运算指令和逻辑运算指令 */ if((i_datain[15:11] == `ADD ||i_datain[15:11] == `ADDC ||i_datain[15:11] == `SUB ||i_datain[15:11] == `SUBC ||i_datain[15:11] == `CMP ||i_datain[15:11] == `AND ||i_datain[15:11] == `OR ||i_datain[15:11] == `XOR) &&( (id_ir[15:11] == `LOAD && (id_ir[10:8] == i_datain[6:4] || id_ir[10:8] == i_datain[2:0])) ||(ex_ir[15:11] == `LOAD && (ex_ir[10:8] == i_datain[6:4] || ex_ir[10:8] == i_datain[2:0])) ) ) // end if begin id_ir <= 16&#39;bx; pc <= pc; // hold pc end /* 指令中第二个操作数为寄存器变量并参与运算时,需要判断LOAD的第一个操作数是否与这些指令的第二个操作数的寄存器有冲突 为移位指令和STORE指令 */ else if (( i_datain[15:11] == `SLL ||i_datain[15:11] == `SRL ||i_datain[15:11] == `SLA ||i_datain[15:11] == `SRA ||i_datain[15:11] == `STORE) &&((id_ir[15:11] == `LOAD &&(id_ir[10:8] == i_datain[6:4])) ||(ex_ir[15:11] == `LOAD &&(ex_ir[10:8] == i_datain[6:4])) ) ) begin id_ir <= 16&#39;bx; pc <= pc; // hold pc end /* 跳转指令系列,id和ex阶段都需要stall,mem阶段跳转 */ else if(id_ir[15:14] == 2&#39;b11 || ex_ir[15:14] == 2&#39;b11) begin id_ir <= 16&#39;bx; pc <= pc; // hold pc end /* mem阶段跳转 */ else begin // BZ & BNZ if(((mem_ir[15:11] == `BZ) && (zf == 1&#39;b1)) || ((mem_ir[15:11] == `BNZ) && (zf == 1&#39;b0))) begin id_ir <= 16&#39;bx; pc <= reg_C[7:0]; end // BN & BNN else if(((mem_ir[15:11] == `BN) && (nf == 1&#39;b1)) || ((mem_ir[15:11] == `BNN) && (nf == 1&#39;b0))) begin id_ir <= 16&#39;bx; pc <= reg_C[7:0]; end // BC & BNC else if(((mem_ir[15:11] == `BC) && (cf == 1&#39;b1)) || ((mem_ir[15:11] == `BNC) && (cf == 1&#39;b0))) begin id_ir <= 16&#39;bx; pc <= reg_C[7:0]; end // JUMP else if((mem_ir[15:11] == `JUMP) || (mem_ir[15:11] == `JMPR)) begin id_ir <= 16&#39;bx; pc <= reg_C[7:0]; end // 非跳转指令且没有检测到冲突 else begin id_ir <= i_datain; pc <= pc + 1; end end // end else end // else reset end // end always //************* ID *************// always @(posedge clock or negedge reset) begin if (!reset) begin ex_ir <= 16&#39;b0; reg_A <= 16&#39;b0; reg_B <= 16&#39;b0; smdr <= 16&#39;b0; end else if (state == `exec) //Data forwarding happens in ID stage, always check id_ir to decide reg_A/B begin ex_ir <= id_ir; // ********************reg_A 赋值******************* // /* 其他无冲突的情况 */ // reg_A <= r1: 要用到 r1 参与运算的指令,即除 "JUMP" 外的控制指令和一些运算指令,将寄存器r1中的值赋给reg_A if ((id_ir[15:14] == 2&#39;b11 && id_ir[15:11] != `JUMP) || (id_ir[15:11] == `LDIH) || (id_ir[15:11] == `ADDI) || (id_ir[15:11] == `SUBI)) reg_A <= gr[id_ir[10:8]]; else if (id_ir[15:11] == `LOAD) reg_A <= gr[id_ir[6:4]]; // case for data forwarding, 当前指令第2个操作数用到之前指令1个操作数的结果 else if(id_ir[6:4] == ex_ir[10:8]) reg_A <= ALUo; else if(id_ir[6:4] == wb_ir[10:8]) reg_A <= reg_C1; else if(id_ir[6:4] == mem_ir[10:8]) reg_A <= reg_C; //reg_A <= r2: 如果运算中不用到 r1,要用到 r2, 则将 gr[r2] else reg_A <= gr[id_ir[6:4]]; //************************* reg_B赋值************************// if (id_ir[15:11] == `STORE) begin reg_B <= {12&#39;b0000_0000_0000, id_ir[3:0]}; //value3 smdr <= gr[id_ir[10:8]]; // r1 end // case for data forwarding, 当前指令3个操作数用到之前指令1个操作数的结果 else if(id_ir[2:0] == ex_ir[10:8]) reg_B <= ALUo; else if(id_ir[2:0] == wb_ir[10:8]) reg_B <= reg_C1; else if(id_ir[2:0] == mem_ir[10:8]) reg_B <= reg_C; /* 其他无冲突的情况 */ else if ((id_ir[15:11] == `ADD) || (id_ir[15:11] == `ADDC) || (id_ir[15:11] == `SUB) || (id_ir[15:11] == `SUBC) || (id_ir[15:11] == `CMP) || (id_ir[15:11] == `AND) || (id_ir[15:11] == `OR) || (id_ir[15:11] == `XOR)) reg_B <= gr[id_ir[2:0]]; end end //************* ALUo *************// always @ (*) begin // {val2, val3} if (ex_ir[15:11] == `JUMP) ALUo <= {8&#39;b0, ex_ir[7:0]}; // 跳转指令 r1 + {val2, val3} else if (ex_ir[15:14] == 2&#39;b11) ALUo <= reg_A + {8&#39;b0, ex_ir[7:0]}; //算数运算,逻辑运算,计算结果到ALUo, 并计算cf标志位 else begin case(ex_ir[15:11]) `LOAD: ALUo <= reg_A + {12&#39;b0000_0000_0000, ex_ir[3:0]}; `STORE: ALUo <= reg_A + reg_B; `LDIH: {cf, ALUo} <= reg_A + { ex_ir[7:0], 8&#39;b0 }; `ADD: {cf, ALUo} <= reg_A + reg_B; `ADDI:{cf, ALUo} <= reg_A + { 8&#39;b0, ex_ir[7:0] }; `ADDC: {cf, ALUo} <= reg_A + reg_B + cf; `SUB: {cf, ALUo} <= {{1&#39;b0, reg_A} - reg_B}; `SUBI: {cf, ALUo} <= {1&#39;b0, reg_A }- { 8&#39;b0, ex_ir[7:0] }; `SUBC:{cf, ALUo} <= {{1&#39;b0, reg_A} - reg_B - cf}; `CMP: {cf, ALUo} <= {{1&#39;b0, reg_A} - reg_B}; `AND: {cf, ALUo} <= {1&#39;b0, reg_A & reg_B}; `OR: {cf, ALUo} <= {1&#39;b0, reg_A | reg_B}; `XOR: {cf, ALUo} <= {1&#39;b0, reg_A ^ reg_B}; `SLL: {cf, ALUo} <= {reg_A[4&#39;b1111 - ex_ir[3:0]], reg_A << ex_ir[3:0]}; `SRL: {cf, ALUo} <= {reg_A[ex_ir[3:0] - 4&#39;b0001], reg_A >> ex_ir[3:0]}; `SLA: {cf, ALUo} <= {reg_A[ex_ir[3:0] - 4&#39;b0001], reg_A <<< ex_ir[3:0]}; `SRA: {cf, ALUo} <= {reg_A[4&#39;b1111 - ex_ir[3:0]], reg_A >>> ex_ir[3:0]}; default: begin end endcase end end //************* EX *************// always @(posedge clock or negedge reset) begin if (!reset) begin mem_ir <= 16&#39;b0; reg_C <= 16&#39;b0; dw <= 0; nf <= 0; zf <= 0; smdr1 <= 16&#39;b0; end else if (state == `exec) begin mem_ir <= ex_ir; reg_C <= ALUo; if (ex_ir[15:11] == `STORE) begin dw <= 1&#39;b1; smdr1 <= smdr; end // 设置标志位zf, nf, 算数和逻辑运算 else if(ex_ir[15:14] != 2&#39;b11 && ex_ir[15:11] != `LOAD) begin zf <= (ALUo == 0)? 1:0; nf <= (ALUo[15] == 1&#39;b1)? 1:0; dw <= 1&#39;b0; end else dw <= 1&#39;b0; end end // PCPU module 的输出 assign d_dataout = smdr1; assign d_we = dw; assign d_addr = reg_C[7:0]; //************* MEM *************// always @(posedge clock or negedge reset) begin if (!reset) begin wb_ir <= 16&#39;b0; reg_C1 <= 16&#39;b0; end else if (state == `exec) begin wb_ir <= mem_ir; if (mem_ir[15:11] == `LOAD) reg_C1 <= d_datain; else if(mem_ir[15:14] != 2&#39;b11) reg_C1 <= reg_C; end end //************* WB *************// always @(posedge clock or negedge reset) begin if (!reset) begin gr[0] <= 16&#39;b0; gr[1] <= 16&#39;b0; gr[2] <= 16&#39;b0; gr[3] <= 16&#39;b0; gr[4] <= 16&#39;b0; gr[5] <= 16&#39;b0; gr[6] <= 16&#39;b0; gr[7] <= 16&#39;b0; end else if (state == `exec) begin // 回写到 r1 if ((wb_ir[15:14] != 2&#39;b11) &&(wb_ir[15:11] != `STORE) &&(wb_ir[15:11] != `CMP) ) gr[wb_ir[10:8]] <= reg_C1; end end // 板极验证 assign y = y_forboard; // 板极验证需要的输出 always @(select_y) begin case(select_y) 4&#39;b0000: y_forboard <= {8&#39;B0,pc}; 4&#39;b0001: y_forboard <= id_ir; 4&#39;b0010: y_forboard <= reg_A; 4&#39;b0011: y_forboard <= reg_B; 4&#39;b0100: y_forboard <= smdr; 4&#39;b0101: y_forboard <= ALUo; 4&#39;b0110: y_forboard <= {15&#39;b0, cf}; 4&#39;b0111: y_forboard <= {15&#39;b0, nf}; 4&#39;b1000: y_forboard <= reg_C; 4&#39;b1001: y_forboard <= reg_C1; 4&#39;b1010: y_forboard <= gr[0]; 4&#39;b1011: y_forboard <= gr[1]; 4&#39;b1100: y_forboard <= gr[2]; 4&#39;b1101: y_forboard<= gr[3]; 4&#39;b1110: y_forboard <= gr[4]; 4&#39;b1111: y_forboard <= gr[5]; endcase end endmodule /**************************** Data memory module ******************************/ module Data_memory ( input wire clock, reset, input wire [7:0] d_addr, input wire [15:0] d_dataout, input wire d_we, output [15:0] d_datain ); reg[15:0] temp; reg[15:0] d_data[255:0]; always@(negedge clock) begin if(!reset) begin d_data[0] <= 16&#39;hFc00; d_data[1] <= 16&#39;h00AB; end else if(d_we) begin d_data[d_addr] <= d_dataout; end else begin temp = d_data[d_addr]; end end assign d_datain = temp; endmodule /**************************** Board evaluation module ******************************/ module Board_eval ( input wire clock, input wire [15:0] y, output reg [7:0] select_segment, output reg [3:0] select_bit ); parameter SEG_NUM0 = 8&#39;b00000011, SEG_NUM1 = 8&#39;b10011111, SEG_NUM2 = 8&#39;b00100101, SEG_NUM3 = 8&#39;b00001101, SEG_NUM4 = 8&#39;b10011001, SEG_NUM5 = 8&#39;b01001001, SEG_NUM6 = 8&#39;b01000001, SEG_NUM7 = 8&#39;b00011111, SEG_NUM8 = 8&#39;b00000001, SEG_NUM9 = 8&#39;b00001001, SEG_A = 8&#39;b00010001, SEG_B = 8&#39;b11000001, SEG_C = 8&#39;b01100011, SEG_D = 8&#39;b10000101, SEG_E = 8&#39;b01100001, SEG_F = 8&#39;b01110001; // 位选 parameter BIT_3 = 4&#39;b0111, BIT_2 = 4&#39;b1011, BIT_1 = 4&#39;b1101, BIT_0 = 4&#39;b1110; reg [20:0] count = 0; always @ (posedge clock) begin count <= count + 1&#39;b1; end always @ (posedge clock) begin case(count[19:18]) 2&#39;b00: begin select_bit <= BIT_3; case(y[15:12]) 4&#39;b0000: select_segment <= SEG_NUM0; 4&#39;b0001: select_segment <= SEG_NUM1; 4&#39;b0010: select_segment <= SEG_NUM2; 4&#39;b0011: select_segment <= SEG_NUM3; 4&#39;b0100: select_segment <= SEG_NUM4; 4&#39;b0101: select_segment <= SEG_NUM5; 4&#39;b0110: select_segment <= SEG_NUM6; 4&#39;b0111: select_segment <= SEG_NUM7; 4&#39;b1000: select_segment <= SEG_NUM8; 4&#39;b1001: select_segment <= SEG_NUM9; 4&#39;b1010: select_segment <= SEG_A; 4&#39;b1011: select_segment <= SEG_B; 4&#39;b1100: select_segment <= SEG_C; 4&#39;b1101: select_segment <= SEG_D; 4&#39;b1110: select_segment <= SEG_E; 4&#39;b1111: select_segment <= SEG_F; endcase end 2&#39;b01: begin select_bit <= BIT_2; case(y[11:8]) 4&#39;b0000: select_segment <= SEG_NUM0; 4&#39;b0001: select_segment <= SEG_NUM1; 4&#39;b0010: select_segment <= SEG_NUM2; 4&#39;b0011: select_segment <= SEG_NUM3; 4&#39;b0100: select_segment <= SEG_NUM4; 4&#39;b0101: select_segment <= SEG_NUM5; 4&#39;b0110: select_segment <= SEG_NUM6; 4&#39;b0111: select_segment <= SEG_NUM7; 4&#39;b1000: select_segment <= SEG_NUM8; 4&#39;b1001: select_segment <= SEG_NUM9; 4&#39;b1010: select_segment <= SEG_A; 4&#39;b1011: select_segment <= SEG_B; 4&#39;b1100: select_segment <= SEG_C; 4&#39;b1101: select_segment <= SEG_D; 4&#39;b1110: select_segment <= SEG_E; 4&#39;b1111: select_segment <= SEG_F; endcase end 2&#39;b10: begin select_bit <= BIT_1; case(y[7:4]) 4&#39;b0000: select_segment <= SEG_NUM0; 4&#39;b0001: select_segment <= SEG_NUM1; 4&#39;b0010: select_segment <= SEG_NUM2; 4&#39;b0011: select_segment <= SEG_NUM3; 4&#39;b0100: select_segment <= SEG_NUM4; 4&#39;b0101: select_segment <= SEG_NUM5; 4&#39;b0110: select_segment <= SEG_NUM6; 4&#39;b0111: select_segment <= SEG_NUM7; 4&#39;b1000: select_segment <= SEG_NUM8; 4&#39;b1001: select_segment <= SEG_NUM9; 4&#39;b1010: select_segment <= SEG_A; 4&#39;b1011: select_segment <= SEG_B; 4&#39;b1100: select_segment <= SEG_C; 4&#39;b1101: select_segment <= SEG_D; 4&#39;b1110: select_segment <= SEG_E; 4&#39;b1111: select_segment <= SEG_F; endcase end 2&#39;b11: begin select_bit <= BIT_0; case(y[3:0]) 4&#39;b0000: select_segment <= SEG_NUM0; 4&#39;b0001: select_segment <= SEG_NUM1; 4&#39;b0010: select_segment <= SEG_NUM2; 4&#39;b0011: select_segment <= SEG_NUM3; 4&#39;b0100: select_segment <= SEG_NUM4; 4&#39;b0101: select_segment <= SEG_NUM5; 4&#39;b0110: select_segment <= SEG_NUM6; 4&#39;b0111: select_segment <= SEG_NUM7; 4&#39;b1000: select_segment <= SEG_NUM8; 4&#39;b1001: select_segment <= SEG_NUM9; 4&#39;b1010: select_segment <= SEG_A; 4&#39;b1011: select_segment <= SEG_B; 4&#39;b1100: select_segment <= SEG_C; 4&#39;b1101: select_segment <= SEG_D; 4&#39;b1110: select_segment <= SEG_E; 4&#39;b1111: select_segment <= SEG_F; endcase end endcase end endmodule 2).test `timescale 1ns / 1ps //////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 21:22:32 12/29/2014 // Design Name: CPU // Module Name: C:/Users/liang/Desktop/embed/CPU/CPU/CPUTest.v // Project Name: CPU // Target Device: // Tool versions: // Description: // // Verilog Test Fixture created by ISE for module: CPU // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // //////////////////////////////////////////////////////////////////////////////// module CPU_test; // Inputs reg clock; reg enable; reg reset; reg [3:0] select_y; reg start; // Outputs wire [15:0] y; // Instantiate the Unit Under Test (UUT) CPU cpu ( .clock(clock), .enable(enable), .reset(reset), .start(start), .select_y(select_y) ); initial begin // Initialize Inputs clock = 0; enable = 0; reset = 0; select_y = 0; start = 0; // Wait 100 ns for global reset to finish #100; forever begin #5 clock <= ~clock; end // Add stimulus here end initial begin // Wait 100 ns for global reset to finish #100; $display("pc: id_ir : ex_ir :reg_A: reg_B: reg_C: cf: nf: zf: regC1: gr1: gr2: gr3: gr4: gr5:"); $monitor("%h: %b: %b: %h: %h: %h: %h: %h: %h: %h: %h: %h: %h: %h: %h", cpu.pcpu.pc, cpu.pcpu.id_ir, cpu.pcpu.ex_ir, cpu.pcpu.reg_A, cpu.pcpu.reg_B, cpu.pcpu.reg_C, cpu.pcpu.cf, cpu.pcpu.nf, cpu.pcpu.zf, cpu.pcpu.reg_C1, cpu.pcpu.gr[1], cpu.pcpu.gr[2], cpu.pcpu.gr[3], cpu.pcpu.gr[4], cpu.pcpu.gr[5]); enable <= 1; start <= 0; select_y <= 0; #10 reset <= 0; #10 reset <= 1; #10 enable <= 1; #10 start <=1; #10 start <= 0; end endmodule
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值