做一个最简单的CPU -- 计算机组成原理(六)

在上一个章节中,我们已经了解了一个存储是如何制作出来的,利用这个存储我们就可以做一个最简单的CPU

指令

我们知道CPU负责执行计算机的程序,而程序其实是一个个的操作指令

比如可能是计算指令,cpu会指示ALU进行加减运算

也可能是存储指令,cpu进行内存数据的读写

我们这里给出一个指令表,给cpu支持的所有指令进行一个编号,假设指令都是8bit的数据

前4位为操作码,后4位为地址或者特定寄存器

32023bd42d3c460c8c8fa438ca10d91f.png

我们就根据一个程序的执行来组合一个CPU

cpu组合

首先我们需要一个内存,直接使用用上一个章节的RAM

26c93640cdf54861b0270909bd7c18f4.png

然后我们需要四个寄存器,用来临时存储运算过程中的数据

62f14ca886974ae484dee380c9a3ac44.png

我们还需要两个寄存器来完成CPU

1.  一个寄存器来追踪程序运行到哪里了,我们叫它“指令地址寄存器(Instruction Address Register)”,  用来存储当前的指令地址

2. 另一个寄存器来存储当前的指令,就叫“指令寄存器(Instrctuion Register)”

8d6cb76e5d8341f5864dfedd85e359c3.png

当程序开始的时候所有存储的数据都是0000, 这里接给出了所有需要的存储的内容

e54a74809fe046a196833e310c84fe83.png

我们使用上面假设的指令表,在RAM里面放了一个程序,我们跟着这个程序画出CPU的其他部分

 

CPU运行

取指令阶段(Fetch Phase)

cpu运行的第一个阶段叫取指令阶段,  首先指令地址寄存器链接到RAM, 由于指令地址寄存器数据是0, 就从RAM中读取地址为0的数据进入指令寄存器

 

4e16f87d190049a4b8707568eb8116cc.png

 

解码阶段(Decode Phase)

现在指令拿到了,需要知道是什么指令,才能运行它,这就是阶段阶段

可以看到第一个指令是 0010 1110

前四位 0010 就是LOAD_A 指令

a0e220969f504254ae426e6e0158b6c6.png

意思就是把 后四位的地址的值放置到寄存器A内, 后四位 1110转成10进制是14,也就是RAM地址14的数据, 我们可以看到RAM地址14的数据是 0000 0011, 也就是把0000 0011 放入寄存器A,这个数据十进制是3,也就是寄存器A此时保存的数据为3

这里就需要一个“控制单元” 来识别这个LOAD_A的指令, 将它转化成对应的操作

77d74d1c34f4418195c979b5d8162d81.png

我们用一个简单的逻辑门来判断指令是不是 0010(LOAD_A), 如果这个输出为1的话代表执行LOAD_A的操作, 将这个“控制单元”放入整体的cpu中进行特定的链接就是执行的操作

执行阶段(Execute Phase)

经过控制电路后,我们需要读取RAM地址14的数据到寄存器A,所以需要打开RAM的允许读取线以及寄存器A的允许写入线, 并且将寄存器A和RAM的数据线进行连接

7056e177641040688e785615eee2fdb1.png

这样就完成了一个CPU的指令循环,完成指令后,就关闭所有的线路,将所有的允许写入和读取都关闭,即完成了存储

0de05664552448a0bf0e9d014c1af38f.png

最后将指令地址寄存器+1,执行阶段就此结束

LOAD_A 只是其中一种指令,控制单元需要识别各种执行,将其转化成各种指令操作,我们可以再进行一层的抽象,将控制单元抽象成一个块,这样就简洁一些

368308f224974d79ac39601f1f493dcf.png

 

循环

由于指令地址+1, 我们进入了下一个循环, 重新进行读取阶段

将RAM地址1的数据读到指令寄存器中

9125c87a2fb343e581d58e81b241f5e9.png

可以看到 0001 1111, 前4位对应操作为LOAD_B,后四位代表的地址为15

994cd75b913243fa904913d471fa8928.png

即将RAM地址15的数据 0000 1110 读到寄存器B, 也就是寄存器B此时保存的数据是十进制的14

a35c71ff8f6a4b0c80441bb3672d7f12.png

此时指令地址寄存器再次+1, 完成第二个循环

第三个循环后,将RAM地址2读入地址寄存器,可以看到具体指令为 1000 0100

084c26a3dff94d2ba0fb15637a899976.png

代表加法指令,后面跟的就是不RAM地址,而是两个寄存器地址,01代表寄存器B,00代表寄存器A, 意思是将寄存器B的数据加到寄存器A, 保存在寄存器A的意思。

为了执行加法操作,需要使用到上一章的ALU进行加法操作

 33c89b2cb710433db5c086ce0850cf7e.png

控制单元需要将加法操作给到ALU,并将寄存器A/B的数据输入到ALU,此时计算结果不能直接存储到寄存器A,否则就会不断进行加法操作, 控制单元需要用自己的寄存器保存计算结果,关闭ALU之后,再将数据写到寄存器A

这里进行加法操作3+14 =17, 也就是寄存器A此时保存数据为17,也即是 0001 0001, 最后指令地址寄存器+1, 循环完成

此时开始最后一个循环,RAM地址为3的数据读入0100 1101,根据前4位得到指令

15b3c6b128d14a718b259dddfbe896f8.png

意思是把寄存器A的数据保存到,后四位的RAM地址 1101(十进制15)中

460acc9a76464d46b2309b491aebb7ed.png

指令地址寄存器再+1,读入RAM地址4的数据为 0000 0000, 程序停止

可以看到我们用4个执行,计算了一个3+14=17,并将结果存储到RAM地址15

可以看到CPU就是在不断循环进行  读取,解码,执行的操作, 那是什么来管理cpu的节奏呢?

答案是时钟

0f048fcdd1fa40a1925cb1e7889df700.png

时钟以一个精确的间隔触发电信号,而控制单元根据电信号触发不同的操作,来让cpu不断运行

cpu完成一次 取指令->解码->执行的循环叫做时钟速度

 

这样一个最简单的CPU就完成了

 

 

上一章:

寄存器和内存 - 计算机组成原理(五)

 

`define NOP 5'b00000 `define HALT 5'b00001 `define LOAD 5'b00010 `define STORE 5'b00011 `define LDIH 5'b10000 `define ADD 5'b01000 `define ADDI 5'b01001 `define ADDC 5'b10001 `define SUB 5'b01011 `define SUBI 5'b10011 `define SUBC 5'b10111 `define CMP 5'b01100 // control `define JUMP 5'b11000 `define JMPR 5'b11001 `define BZ 5'b11010 `define BNZ 5'b11011 `define BN 5'b11100 `define BNN 5'b11101 `define BC 5'b11110 `define BNC 5'b11111 // logic / shift `define AND 5'b01101 `define OR 5'b01111 `define XOR 5'b01110 `define SLL 5'b00100 `define SRL 5'b00110 `define SLA 5'b00101 `define SRA 5'b00111 // general register `define gr0 3'b000 `define gr1 3'b001 `define gr2 3'b010 `define gr3 3'b011 `define gr4 3'b100 `define gr5 3'b101 `define gr6 3'b110 `define gr7 3'b111 // FSM `define idle 1'b0 `define exec 1'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'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'b0, `gr0, 4'b0000}; i_data[1] <= {`LOAD, `gr2, 1'b0, `gr0, 4'b0001}; i_data[2] <= {`ADD, `gr3, 1'b0, `gr1, 1'b0, `gr2}; i_data[3] <= {`SUB, `gr3, 1'b0, `gr1, 1'b0, `gr2}; i_data[4] <= {`CMP, `gr3, 1'b0, `gr2, 1'b0, `gr1}; i_data[5] <= {`ADDC, `gr3, 1'b0, `gr1, 1'b0, `gr2}; i_data[6] <= {`SUBC, `gr3, 1'b0, `gr1, 1'b0, `gr2}; i_data[7] <= {`SLL, `gr2, 1'b0, `gr3, 1'b0, 3'b001}; i_data[8] <= {`SRL, `gr3, 1'b0, `gr1, 1'b0, 3'b001}; i_data[9] <= {`SLA, `gr4, 1'b0, `gr1, 1'b0, 3'b001}; i_data[10] <= {`SRA, `gr5, 1'b0, `gr1, 1'b0, 3'b001}; i_data[11] <= {`STORE, `gr3, 1'b0, `gr0, 4'b0010}; i_data[12] <= {`HALT, 11'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'b1) && (start == 1'b1)) next_state <= `exec; else next_state <= `idle; `exec : if ((enable == 1'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'b0; pc <= 8'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'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'bx; pc <= pc; // hold pc end /* 跳转指令系列,id和ex阶段都需要stall,mem阶段跳转 */ else if(id_ir[15:14] == 2'b11 || ex_ir[15:14] == 2'b11) begin id_ir <= 16'bx; pc <= pc; // hold pc end /* mem阶段跳转 */ else begin // BZ & BNZ if(((mem_ir[15:11] == `BZ) && (zf == 1'b1)) || ((mem_ir[15:11] == `BNZ) && (zf == 1'b0))) begin id_ir <= 16'bx; pc <= reg_C[7:0]; end // BN & BNN else if(((mem_ir[15:11] == `BN) && (nf == 1'b1)) || ((mem_ir[15:11] == `BNN) && (nf == 1'b0))) begin id_ir <= 16'bx; pc <= reg_C[7:0]; end // BC & BNC else if(((mem_ir[15:11] == `BC) && (cf == 1'b1)) || ((mem_ir[15:11] == `BNC) && (cf == 1'b0))) begin id_ir <= 16'bx; pc <= reg_C[7:0]; end // JUMP else if((mem_ir[15:11] == `JUMP) || (mem_ir[15:11] == `JMPR)) begin id_ir <= 16'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'b0; reg_A <= 16'b0; reg_B <= 16'b0; smdr <= 16'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'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'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'b0, ex_ir[7:0]}; // 跳转指令 r1 + {val2, val3} else if (ex_ir[15:14] == 2'b11) ALUo <= reg_A + {8'b0, ex_ir[7:0]}; //算数运算,逻辑运算,计算结果到ALUo, 并计算cf标志位 else begin case(ex_ir[15:11]) `LOAD: ALUo <= reg_A + {12'b0000_0000_0000, ex_ir[3:0]}; `STORE: ALUo <= reg_A + reg_B; `LDIH: {cf, ALUo} <= reg_A + { ex_ir[7:0], 8'b0 }; `ADD: {cf, ALUo} <= reg_A + reg_B; `ADDI:{cf, ALUo} <= reg_A + { 8'b0, ex_ir[7:0] }; `ADDC: {cf, ALUo} <= reg_A + reg_B + cf; `SUB: {cf, ALUo} <= {{1'b0, reg_A} - reg_B}; `SUBI: {cf, ALUo} <= {1'b0, reg_A }- { 8'b0, ex_ir[7:0] }; `SUBC:{cf, ALUo} <= {{1'b0, reg_A} - reg_B - cf}; `CMP: {cf, ALUo} <= {{1'b0, reg_A} - reg_B}; `AND: {cf, ALUo} <= {1'b0, reg_A & reg_B}; `OR: {cf, ALUo} <= {1'b0, reg_A | reg_B}; `XOR: {cf, ALUo} <= {1'b0, reg_A ^ reg_B}; `SLL: {cf, ALUo} <= {reg_A[4'b1111 - ex_ir[3:0]], reg_A << ex_ir[3:0]}; `SRL: {cf, ALUo} <= {reg_A[ex_ir[3:0] - 4'b0001], reg_A >> ex_ir[3:0]}; `SLA: {cf, ALUo} <= {reg_A[ex_ir[3:0] - 4'b0001], reg_A <<< ex_ir[3:0]}; `SRA: {cf, ALUo} <= {reg_A[4'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'b0; reg_C <= 16'b0; dw <= 0; nf <= 0; zf <= 0; smdr1 <= 16'b0; end else if (state == `exec) begin mem_ir <= ex_ir; reg_C <= ALUo; if (ex_ir[15:11] == `STORE) begin dw <= 1'b1; smdr1 <= smdr; end // 设置标志位zf, nf, 算数和逻辑运算 else if(ex_ir[15:14] != 2'b11 && ex_ir[15:11] != `LOAD) begin zf <= (ALUo == 0)? 1:0; nf <= (ALUo[15] == 1'b1)? 1:0; dw <= 1'b0; end else dw <= 1'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'b0; reg_C1 <= 16'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'b11) reg_C1 <= reg_C; end end //************* WB *************// always @(posedge clock or negedge reset) begin if (!reset) begin gr[0] <= 16'b0; gr[1] <= 16'b0; gr[2] <= 16'b0; gr[3] <= 16'b0; gr[4] <= 16'b0; gr[5] <= 16'b0; gr[6] <= 16'b0; gr[7] <= 16'b0; end else if (state == `exec) begin // 回写到 r1 if ((wb_ir[15:14] != 2'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'b0000: y_forboard <= {8'B0,pc}; 4'b0001: y_forboard <= id_ir; 4'b0010: y_forboard <= reg_A; 4'b0011: y_forboard <= reg_B; 4'b0100: y_forboard <= smdr; 4'b0101: y_forboard <= ALUo; 4'b0110: y_forboard <= {15'b0, cf}; 4'b0111: y_forboard <= {15'b0, nf}; 4'b1000: y_forboard <= reg_C; 4'b1001: y_forboard <= reg_C1; 4'b1010: y_forboard <= gr[0]; 4'b1011: y_forboard <= gr[1]; 4'b1100: y_forboard <= gr[2]; 4'b1101: y_forboard<= gr[3]; 4'b1110: y_forboard <= gr[4]; 4'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'hFc00; d_data[1] <= 16'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'b00000011, SEG_NUM1 = 8'b10011111, SEG_NUM2 = 8'b00100101, SEG_NUM3 = 8'b00001101, SEG_NUM4 = 8'b10011001, SEG_NUM5 = 8'b01001001, SEG_NUM6 = 8'b01000001, SEG_NUM7 = 8'b00011111, SEG_NUM8 = 8'b00000001, SEG_NUM9 = 8'b00001001, SEG_A = 8'b00010001, SEG_B = 8'b11000001, SEG_C = 8'b01100011, SEG_D = 8'b10000101, SEG_E = 8'b01100001, SEG_F = 8'b01110001; // 位选 parameter BIT_3 = 4'b0111, BIT_2 = 4'b1011, BIT_1 = 4'b1101, BIT_0 = 4'b1110; reg [20:0] count = 0; always @ (posedge clock) begin count <= count + 1'b1; end always @ (posedge clock) begin case(count[19:18]) 2'b00: begin select_bit <= BIT_3; case(y[15:12]) 4'b0000: select_segment <= SEG_NUM0; 4'b0001: select_segment <= SEG_NUM1; 4'b0010: select_segment <= SEG_NUM2; 4'b0011: select_segment <= SEG_NUM3; 4'b0100: select_segment <= SEG_NUM4; 4'b0101: select_segment <= SEG_NUM5; 4'b0110: select_segment <= SEG_NUM6; 4'b0111: select_segment <= SEG_NUM7; 4'b1000: select_segment <= SEG_NUM8; 4'b1001: select_segment <= SEG_NUM9; 4'b1010: select_segment <= SEG_A; 4'b1011: select_segment <= SEG_B; 4'b1100: select_segment <= SEG_C; 4'b1101: select_segment <= SEG_D; 4'b1110: select_segment <= SEG_E; 4'b1111: select_segment <= SEG_F; endcase end 2'b01: begin select_bit <= BIT_2; case(y[11:8]) 4'b0000: select_segment <= SEG_NUM0; 4'b0001: select_segment <= SEG_NUM1; 4'b0010: select_segment <= SEG_NUM2; 4'b0011: select_segment <= SEG_NUM3; 4'b0100: select_segment <= SEG_NUM4; 4'b0101: select_segment <= SEG_NUM5; 4'b0110: select_segment <= SEG_NUM6; 4'b0111: select_segment <= SEG_NUM7; 4'b1000: select_segment <= SEG_NUM8; 4'b1001: select_segment <= SEG_NUM9; 4'b1010: select_segment <= SEG_A; 4'b1011: select_segment <= SEG_B; 4'b1100: select_segment <= SEG_C; 4'b1101: select_segment <= SEG_D; 4'b1110: select_segment <= SEG_E; 4'b1111: select_segment <= SEG_F; endcase end 2'b10: begin select_bit <= BIT_1; case(y[7:4]) 4'b0000: select_segment <= SEG_NUM0; 4'b0001: select_segment <= SEG_NUM1; 4'b0010: select_segment <= SEG_NUM2; 4'b0011: select_segment <= SEG_NUM3; 4'b0100: select_segment <= SEG_NUM4; 4'b0101: select_segment <= SEG_NUM5; 4'b0110: select_segment <= SEG_NUM6; 4'b0111: select_segment <= SEG_NUM7; 4'b1000: select_segment <= SEG_NUM8; 4'b1001: select_segment <= SEG_NUM9; 4'b1010: select_segment <= SEG_A; 4'b1011: select_segment <= SEG_B; 4'b1100: select_segment <= SEG_C; 4'b1101: select_segment <= SEG_D; 4'b1110: select_segment <= SEG_E; 4'b1111: select_segment <= SEG_F; endcase end 2'b11: begin select_bit <= BIT_0; case(y[3:0]) 4'b0000: select_segment <= SEG_NUM0; 4'b0001: select_segment <= SEG_NUM1; 4'b0010: select_segment <= SEG_NUM2; 4'b0011: select_segment <= SEG_NUM3; 4'b0100: select_segment <= SEG_NUM4; 4'b0101: select_segment <= SEG_NUM5; 4'b0110: select_segment <= SEG_NUM6; 4'b0111: select_segment <= SEG_NUM7; 4'b1000: select_segment <= SEG_NUM8; 4'b1001: select_segment <= SEG_NUM9; 4'b1010: select_segment <= SEG_A; 4'b1011: select_segment <= SEG_B; 4'b1100: select_segment <= SEG_C; 4'b1101: select_segment <= SEG_D; 4'b1110: select_segment <= SEG_E; 4'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
发出的红包

打赏作者

Jacen.L

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值