精简指令集(RISC)CPU的构造原理和设计方法
CPU:中央处理单元,是计算机的核心部件 计算机进行信息处理分两个步骤: 将数据和程序(指令序列)输入到计算机的存储器中 从第一条指令的地址起开始执行程序,得到所需结果,结束运行。 CPU的作用:协调并控制计算机的各部件,使之有条不紊的执行程序
CPU的基本功能: 取指令-地址与控制信号 分析指令-即指令译码,操作和操作控制信号 执行指令-操作控制信号作用于各部件 CPU的基本功能概括: 能对指令进行译码并执行规定的动作 可以进行算术和逻辑运算 能与存储器和外设交换数据 提供系统所需的控制
CPU的内部结构: 算术逻辑运算单元(ALU) 累加器 程序计数器 指令寄存器和译码器 时序和控制部件 RISC即精简指令集计算机: Reduced Instruction Set Computer 时序控制信号由硬件而不是微程序控制
MICRO COMPUTER SYSTEM cpu AB DB 地址 译码器 ROM RAM clock read reset write
指令 指令数目:8条 地址空间:213=8K 指令码 地址码 高8位 低8位 D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 高8位 低8位 指令数目:8条 地址空间:213=8K
指令集 助记符 操作码 功能 HLT 3'b000 暂停 SKZ 3‘b001 累加器为零转移ADD 3’b010 加 助记符 操作码 功能 HLT 3'b000 暂停 SKZ 3‘b001 累加器为零转移ADD 3’b010 加 ANDD 3‘b011 与 XORR 3‘b100 或 LDA 3‘b101 取数 STO 3‘b110 存数 JMP 3‘b111 转移
CPU的基本功能: 取指令-地址与控制信号 分析指令-即指令译码,操作和操作控制信号 执行指令-操作控制信号作用于各部件 CPU的基本功能概括: 能对指令进行译码并执行规定的动作 可以进行算术和逻辑运算 能与存储器和外设交换数据 提供系统所需的控制
CPU的内部结构: 算术逻辑运算单元(ALU) 累加器 程序计数器 指令寄存器和译码器 时序和控制部件
CPU的结构功能图 AB DB clk rst fetch 时钟信号 数据控制 指令寄存器 IR 地址选择 datactl_ena alu_ena load_ir 程序计数器 PC 算逻单元 ALU load_pc inc_pc 累加器 A load_acc 控制状态机 halt rd wr
AB DB clk fetch 时钟信号 数据控制 指令寄存器 IR 地址选择 rst 程序计数器 PC 算逻单元 ALU alu_ena inc_pc 累加器 A datactl_ena load_ir load_pc load_acc 控制状态机 halt rd wr clk 1 2 3 4 5 6 7 fetch alu_ena halt指令 inc_pc rd load_ir halt
累加器 指令寄存器 算逻单元 数据控制 地址选择 程序计数器 控制状态机 时钟信号 AB DB rd load_acc fetch inc_pc load_ir alu_ena clk 1 2 3 4 5 6 7 fetch LDA 1000 alu_ena B0 00 0000 0001 ROM 0002 inc_pc rd load_ir data B0 00 EE load_acc EE 01 1000 1001 RAM address 0000 0001 0002 1000
累加器 指令寄存器 算逻单元 数据控制 地址选择 程序计数器 控制状态机 时钟信号 AB DB rd load_acc fetch inc_pc load_ir alu_ena clk 1 2 3 4 5 6 7 fetch ADD 1001 alu_ena 50 01 0002 0003 ROM 0004 inc_pc rd load_ir data 50 01 11 load_acc EE 11 1000 1001 RAM address 0002 0003 0004 1001
累加器 指令寄存器 算逻单元 数据控制 地址选择 程序计数器 控制状态机 时钟信号 AB DB rd load_acc fetch inc_pc load_ir alu_ena clk 1 2 3 4 5 6 7 fetch STO 1001 alu_ena D0 01 0004 0005 ROM 0006 inc_pc rd load_ir data D0 01 FF wr EE 01 1000 1001 RAM address 0004 0005 0006 1001
17.3.1 时钟发生器 fetch是控制信号,clk的8分频信号 alu_ena用于控制算术逻辑运算单元 clk是时钟信号 reset是复位信号
17.3.1 时钟发生器 状态转移图 Idle idle S1 S2 S3 S4 S5 S6 S7 S8 S1 S2 S3 S4 S5 S6
17.3.1 时钟发生器 //-------clk_gen.v-------- `timescale 1ns/1ns module clk_gen(clk,reset,fetch,alu_ena); input clk, reset; output fetch, alu_ena; wire clk, reset; reg fetch, alu_ena; reg [7:0]state; parameter S1=8'b00000001, S2=8'b00000010, S3=8'b00000100, S4=8'b00001000, S5=8'b00010000, S6=8'b00100000, S7=8'b01000000, S8=8'b10000000, idle=8'b00000000;
always @(posedge clk) if(reset) begin fetch<=0; alu_ena<=0; state<=idle; end else case (state) … default:state<=idle; endcase case (state) S1: begin fetch<=1; state<=S2; end S2: state<=S3; S3: state<=S4; S4: state<=S5; S5: begin state<=S6; fetch=0; end S6: begin state<=S7; alu_ena<=1; end S7: begin alu_ena<=0; state<=S8; end S8: state<=S1; idle: state<=S1; default:state<=idle; endcase
17.3.2 指令寄存器 opcode[2:0] load_ir ir_addr[12:0] clk reset
`timescale 1ns/1ns module register(opc_iraddr,data,ena,clk,rst); output [15:0]opc_iraddr; input [7:0]data; input ena,clk,rst; reg [15:0]opc_iraddr; reg state; always @(posedge clk) begin if (rst) opc_iraddr<=16'b0000_0000_0000_0000; state<=1'b0; end else if (ena) casex(state) 1'b0:begin opc_iraddr[15:8]<=data; state<=1; end 1'b1:begin opc_iraddr[7:0]<=data; state<=0; default:begin opc_iraddr[15:0]<=16'bx; state<=1'bx; endcase else state<=1'b0; endmodule
17.3.3 累加器 alu_out[7:0] load_acc clk reset
module accum(accum,data,ena,clk,rst); output [7:0]accum; input [7:0]data; input ena,clk,rst; reg [7:0]accum; always @(posedge clk) begin if(rst) accum<=8'b0000_0000; else if(ena) accum<=data; end endmodule
17.3.4 算术逻辑运算器 助记符 操作码 功能 HLT 3'b000 暂停 SKZ 3‘b001 累加器为零转移ADD 3’b010 加 助记符 操作码 功能 HLT 3'b000 暂停 SKZ 3‘b001 累加器为零转移ADD 3’b010 加 ANDD 3‘b011 与 XORR 3‘b100 或 LDA 3‘b101 取数 STO 3‘b110 存数 JMP 3‘b111 转移
`timescale 1ns/1ns module alu(alu_out,zero,data,accum,alu_ena,opcode,clk); output [7:0]alu_out; output zero; input [7:0]data,accum; input [2:0]opcode; input alu_ena,clk; reg [7:0]alu_out; parameter HLT=3'b000, SKZ=3'b001, ADD=3'b010, ANDD=3'b011, XORR=3'b100, LDA=3'b101, STO=3'b110, JMP=3'b111; assign zero=!accum; always @(posedge clk) if(alu_ena) begin casex(opcode) HLT:alu_out<=accum; SKZ:alu_out<=accum; ADD:alu_out<=data+accum; ANDD:alu_out<=data&accum; XORR:alu_out<=data^accum; LDA:alu_out<=data; STO:alu_out<=accum; JMP:alu_out<=accum; default:alu_out<=8'bxxxx_xxxx; endcase end endmodule
17.3.5 数据控制器 alu_out[7:0] data[7:0] datactl_ena
module datactl(data,in,data_ena); output [7:0]data; input [7:0]in; input data_ena; assign data=(data_ena)?in:8'bz; endmodule
17.3.6 地址多路器
module adr(addr,fetch,pc_addr,ir_addr); input fetch; input [12:0]pc_addr,ir_addr; output [12:0]addr; assign addr=fetch? pc_addr:ir_addr; endmodule
17.3.7 程序计数器
module counter(pc_addr,ir_addr,load,clk,rst); input load,clk,rst; input [12:0]ir_addr; output [12:0]pc_addr; reg [12:0]pc_addr; always @(posedge clk or posedge rst) if(rst) pc_addr<=13'b0_0000_0000_0000; else if(load) pc_addr<=ir_addr; pc_addr<=pc_addr+1; endmodule
17.3.8 状态控制器
17.3.8 状态控制器 状态控制器两部分: 状态机(machine) 状态控制器machinectl rst有效,ena=0, 状态机停止工作。 `timescale 1ns/1ns module machinectl(ena,fetch,rst,clk); input fetch,rst,clk; output ena; reg ena; always @(posedge clk) begin if(rst) ena<=0; else if(fetch) ena<=1; end endmodule
17.3.8 状态控制器 状态机是CPU的核心部件,用于产生控制信号: 启动、停止某些部件 CPU执行读指令来读写接口、存储器 000 001 010 011 100 101 110 111 状态机是CPU的核心部件,用于产生控制信号: 启动、停止某些部件 CPU执行读指令来读写接口、存储器 状态变量state的值,是指令周期已经过的时钟数
指令周期中8个时钟完成的操作 第0个时钟:rd和load_ir为高电平,ROM中高八位指令代码-->指令寄存器 第1个时钟:rd和load_ir为高电平,inc_pc加1,故PC+1,ROM中低八位指令代码-->指令寄存器 第2个时钟:空操作 第3个时钟:PC+1,指向下一条指令;若HLT指令,halt=1;其它指令控制线输出为0
指令周期中8个时钟完成的操作 第4个时钟:若AND ADD XOR LDA,读相应地址数据; 若JMP, 目的地址-->PC; 若STO, 输出累加器数据。 第5个时钟:若AND ADD XOR , 进行相应运算; 若LDA, 数据-->运算器-->累加器;若JMP,锁存目的地址;若STO,数据到地址处。 第6个时钟:空操作 第7个时钟:若SKZ指令, PC+1跳过一条指令;否则PC无变化
`timescale 1ns/1ns module machine(inc_pc,load_acc,load_pc,rd,wr,load_ir,datactl_ena,halt,clk,zero,ena,opcode); output inc_pc,load_acc,load_pc,rd,wr,load_ir; output datactl_ena,halt; input clk,zero,ena; input [2:0]opcode; reg inc_pc,load_acc,load_pc,rd,wr,load_ir; reg datactl_ena,halt; reg [2:0]state; parameter HLT =3'B000, SKZ =3'b001, ADD =3'b010, ANDD=3'b011, XORR=3'b100, LDA =3'b101, STO =3'b110, JMP =3'b111;
always @(negedge clk) begin if(!ena) state<=3'b000; {inc_pc,load_acc,load_pc,rd}<=4'b0000; {wr,load_ir,datactl_ena,halt}<=4'b0000; end else ctl_cycle;
3'b010: begin //-------begin of task ctl_cycle------- task ctl_cycle; casex(state) 3'b000: begin {inc_pc,load_acc,load_pc,rd}<=4'b0001; {wr,load_ir,datactl_ena,halt}<=4'b0100; state<=3'b001; end 3'b001: begin {inc_pc,load_acc,load_pc,rd}<=4'b1001; state<=3'b010; 3'b010: begin {inc_pc,load_acc,load_pc,rd}<=4'b0000; {wr,load_ir,datactl_ena,halt}<=4'b0000; state<=3'b011;
3'b011: begin if(opcode==HLT) {inc_pc,load_acc,load_pc,rd}<=4'b1000; {wr,load_ir,datactl_ena,halt}<=4'b0001; state<=3'b100; end else {wr,load_ir,datactl_ena,halt}<=4'b0000;
3'b100: begin if(opcode==JMP) begin {inc_pc,load_acc,load_pc,rd}<=4'b0010; {wr,load_ir,datactl_ena,halt}<=4'b0000; end else if(opcode==ADD||opcode==ANDD||opcode==XORR||opcode==LDA) {inc_pc,load_acc,load_pc,rd}<=4'b0001; else if(opcode==STO) {inc_pc,load_acc,load_pc,rd}<=4'b0000; {wr,load_ir,datactl_ena,halt}<=4'b0010; end else state<=3'b101; end
3'b101: begin //operation if(opcode==ADD||opcode==ANDD||opcode==XORR||opcode==LDA) begin {inc_pc,load_acc,load_pc,rd}<=4'b0101; {wr,load_ir,datactl_ena,halt}<=4'b0000; end else if(opcode==SKZ && zero==1) {inc_pc,load_acc,load_pc,rd}<=4'b1000; {wr,load_ir,datactl_ena,halt}<=4'b0000; end else if(opcode==JMP) {inc_pc,load_acc,load_pc,rd}<=4'b1010; else if(opcode==STO) {inc_pc,load_acc,load_pc,rd}<=4'b0000; {wr,load_ir,datactl_ena,halt}<=4'b1010; end else state<=3'b110; end
3'b110://idle begin if(opcode==STO) {inc_pc,load_acc,load_pc,rd}<=4'b0000; {wr,load_ir,datactl_ena,halt}<=4'b0010; end else if(opcode==ADD||opcode==ANDD||opcode==XORR||opcode==LDA) {inc_pc,load_acc,load_pc,rd}<=4'b0001; {wr,load_ir,datactl_ena,halt}<=4'b0000; else state<=3'b111;
3'b111: begin if(opcode==SKZ && zero==1) begin {inc_pc,load_acc,load_pc,rd}<=4'b1000; {wr,load_ir,datactl_ena,halt}<=4'b0000; end else {inc_pc,load_acc,load_pc,rd}<=4'b0000; state<=3'b000; end default: begin {wr,load_ir,datactl_ena,halt}<=4'b0000; state<=3'b000; end endcase endtask //-----------end of task ctl_cycle-------------- endmodule
MICRO COMPUTER SYSTEM cpu AB DB 地址 译码器 ROM RAM clock read reset write
17.3.9 外围模块(地址译码器)
module addr_decode(addr,rom_sel,ram_sel); output rom_sel,ram_sel; input [12:0]addr; reg rom_sel,ram_sel; always @(addr) casex(addr) 13'b1_1xxx_xxxx_xxxx:{rom_sel,ram_sel}<=2'b01; 13'b0_xxxx_xxxx_xxxx:{rom_sel,ram_sel}<=2'b10; 13'b1_0xxx_xxxx_xxxx:{rom_sel,ram_sel}<=2'b10; default:{rom_sel,ram_sel}<=2'b00; endcase endmodule
17.3.9 外围模块(RAM) module addr_decode(addr,rom_sel,ram_sel); output rom_sel,ram_sel; input [12:0]addr; reg rom_sel,ram_sel; always @(addr) casex(addr) 13'b1_1xxx_xxxx_xxxx:{rom_sel,ram_sel}<=2'b01; 13'b0_xxxx_xxxx_xxxx:{rom_sel,ram_sel}<=2'b10; 13'b1_0xxx_xxxx_xxxx:{rom_sel,ram_sel}<=2'b10; default:{rom_sel,ram_sel}<=2'b00; endcase endmodule
17.3.9 外围模块(ROM) module rom(data,addr,read,ena); output [7:0]data; input [12:0]addr; input ena,read; reg [7:0]mem[13'h1fff:0]; assign data=(read&&ena)?mem[addr]:8'hzz; endmodule
17.4 RISC_CPU操作和时序 主要操作: 系统的复位和启动操作 总线读操作 总线写操作
17.4.1 系统的复位和启动操作 复位状态reset=1: CPU内部寄存器全为零 数据总线为高阻状态 地址总线为0000H 所有控制信号为无效状态 启动状态reset=0: fetch上升沿启动CPU开始工作 从ROM的000处读指令并执行
17.4.2 总线读操作 复位状态reset=1: CPU内部寄存器全为零 数据总线为高阻状态 地址总线为0000H 所有控制信号为无效状态 fetch上升沿启动CPU开始工作 从ROM的000处读指令并执行
17.5 RISC_CPU 寻址方式和指令系统 指令数目:8条 地址空间:213=8K 指令码 地址码 高8位 低8位 D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 高8位 低8位 指令数目:8条 地址空间:213=8K
17.5 RISC_CPU 寻址方式和指令系统 直接寻址方式 数据放在存储器中,寻址单元的地址由指令直接给出。 指令码 地址码 LDA 010FH 56H 010CH 8EH 010DH 00H 010EH 77H 010FH 56H EDH 指令码 地址码 FFH FFH 00H 1 1 1 1 1 1 1
17.5 RISC_CPU 寻址方式和指令系统 HLT: 停机操作 该操作空一个指令周期,即8个时钟 SKZ: 为零跳过下一条语句 累加器结果为零,跳过下一语句; 累加器结果不为零,顺序执行。 ADD: 相加 累加器的值+地址所知的存储器中的数据,结果送回累加器。
17.5 RISC_CPU 寻址方式和指令系统 ANDD: 相与 累加器的值&地址所知的存储器中的数据,结果送回累加器。 XORR: 相异或 累加器的值^地址所知的存储器中的数据,结果送回累加器。 LDA: 读数据 地址所知的存储器中的数据送累加器。
17.5 RISC_CPU 寻址方式和指令系统 STO: 写数据 累加器中的数据送地址所指的存储器中 JMP: 无条件跳转语句 该操作跳转至指令给出的目的地址,继续执行。
累加器 指令寄存器 算逻单元 数据控制 地址选择 程序计数器 控制状态机 时钟信号 AB DB rd load_acc fetch inc_pc load_ir alu_ena clk 1 2 3 4 5 6 7 fetch LDA 1000 alu_ena B0 00 0000 0001 ROM 0002 inc_pc rd load_ir data B0 00 EE load_acc EE 01 1000 1001 RAM address 0000 0001 0002 1000
累加器 指令寄存器 算逻单元 数据控制 地址选择 程序计数器 控制状态机 时钟信号 AB DB rd load_acc fetch inc_pc load_ir alu_ena clk 1 2 3 4 5 6 7 fetch ADD 1001 alu_ena 50 01 0002 0003 ROM 0004 inc_pc rd load_ir data 50 01 11 load_acc EE 11 1000 1001 RAM address 0002 0003 0004 1001
累加器 指令寄存器 算逻单元 数据控制 地址选择 程序计数器 控制状态机 时钟信号 AB DB rd load_acc fetch inc_pc load_ir alu_ena clk 1 2 3 4 5 6 7 fetch STO 1001 alu_ena D0 01 0004 0005 ROM 0006 inc_pc rd load_ir data D0 01 FF wr EE 01 1000 1001 RAM address 0004 0005 0006 1001
ROM @00 111_00000 //00 BEGIN: JMP TEST_JMP 0011_1100 000_00000 //02 HLT 0000_0000 000_00000 //04 HLT 101_11000 //06 JMP_OK: LDA DATA_1 001_00000 //08 SKZ 000_00000 //0A HLT 101_11000 //0C LDA DATA_2 0000_0001 001_00000 //0E SKZ 111_00000 //10 JMP SKZ_OK 0001_0100 000_00000 //12 HLT 110_11000 //14 SKZ_OK: STO TEMP 0000_0010 101_11000 //16 LDA DTAT_1 110_11000 //18 STO TEMP 101_11000 //1A LDA TEMP 001_00000 //1C SKZ 0000_0000 000_00000 //1E HLT 100_11000 //20 XORR DTAT_2 0000_0001 001_00000 //22 SKZ 000_00000 //24 HLT 111_00000 //26 JMP XORR_OK 0010_0100 100_11000 //28 XORR_OK: XORR DATA_2 001_00000 //2A SKZ 000_00000 //2C HLT 000_00000 //2E EDN: HLT 111_00000 //30 JMP BEGIN @3C 111_00000 //3C TST_JMP: JMP JMP_OK 0000_0110 000_00000 //3E HLT
RAM @00 00000000 //1800 DATA_1 11111111 //1801 DATA_2 10101010 //1802 TEMP
17.6 RISC_CPU 模块的调试 cpu AB DB 地址 译码器 ROM RAM clock read reset write
`include "clk_gen.v" `include "register.v" `include "accum.v" `include "adr.v" `include "alu.v" `include "machine.v" `include "machinectl.v" `include "counter.v" `include "datactl.v" `timescale 1ns/1ns module cpu(clk,reset,halt,rd,wr,addr,data,opcode,fetch,ir_addr,pc_addr); input clk,reset; output rd,wr,halt; output [12:0]addr; output [2:0]opcode; output fetch; output [12:0]ir_addr,pc_addr; inout [7:0]data; wire clk,reset,halt; wire [7:0]data; wire [12:0]addr; wire rd,wr, wire fetch,alu_ena; wire [2:0]opcode; wire [12:0]ir_addr,pc_addr; wire [7:0]alu_out,accum; wire zero,inc_pc,load_acc,load_pc,load_ir,data_ena,contrl_ena; endmodule
module cpu(clk,reset,halt,rd,wr,addr,data,opcode,fetch,ir_addr,pc_addr); clk_gen m_clkgen(.clk(clk),.reset(reset),.fetch(fetch),.alu_ena(alu_ena)); register m_register(.data(data),.ena(load_ir),.rst(reset),.clk(clk),.opc_iraddr({opcode,ir_addr})); accum m_accum(.data(alu_out),.ena(load_acc),.clk(clk),.rst(reset),.accum(accum)); alu m_alu(.data(data),.accum(accum),.clk(clk),.alu_ena(alu_ena),.opcode(opcode),.alu_out(alu_out),.zero(zero)); machinectl m_machinectl(.clk(clk),.rst(reset),.fetch(fetch),.ena(contrl_ena)); machine m_machine(.inc_pc(inc_pc),.load_acc(load_acc),.load_pc(load_pc),.rd(rd),.wr(wr),.load_ir(load_ir), .clk(clk),.datactl_ena(data_ena),.halt(halt),.zero(zero),.ena(contrl_ena),.opcode(opcode)); datactl m_datactl(.in(alu_out),.data_ena(data_ena),.data(data)); adr m_adr(.fetch(fetch),.ir_addr(ir_addr),.pc_addr(pc_addr),.addr(addr)); counter m_counter(.clk(inc_pc),.rst(reset),.ir_addr(ir_addr),.load(load_pc),.pc_addr(pc_addr)); endmodule
`include "cpu.v" `include "ram.v" `include "rom.v" `include "addr_decode.v" `timescale 1ns/1ns `define PERIOD 100 module topcpu; reg reset_req,clock; integer test; reg [(3*8):0]mnemonic; reg [12:0]PC_addr,IR_addr; wire [7:0]data; wire [12:0]addr; wire rd,wr,halt,ram_sel,rom_sel; wire [2:0]opcode; wire fetch; wire [12:0]ir_addr,pc_addr; …….. endmodule
module topcpu; reg reset_req,clock; ……. cpu t_cpu(.clk(clock),.reset(reset_req),.halt(halt),.rd(rd),.wr(wr),.addr(addr),.data(data), .opcode(opcode),.fetch(fetch),.ir_addr(ir_addr),.pc_addr(pc_addr)); ram t_ram(.addr(addr[9:0]),.read(rd),.write(wr),.ena(ram_sel),.data(data)); rom t_rom(.addr(addr),.read(rd),.ena(rom_sel),.data(data)); addr_decode t_addr_decode(.addr(addr),.ram_sel(ram_sel),.rom_sel(rom_sel)); initial begin clock=1; $timeformat(-9,1,"ns",12); display_debug_message; sys_reset; test1; $stop; $finish; end …….. endmodule
module topcpu; …….. task display_debug_message; begin $display("\n********************************************************"); $display("*\"test1;\" to load the 1st diagnostic program. *"); end endtask task test1; test=0; disable MONITOR; $readmemb("test1.pro",t_rom.mem); $display("rom loaded successfully!"); $readmemb("test1.dat",t_ram.mem); $display("ram loaded successfully!"); #1 test=1; #14800; sys_reset; ………. endmodule
module topcpu; task sys_reset; begin reset_req=0; #(`PERIOD*0.7) reset_req=1; #(1.5*`PERIOD) reset_req=0; end endtask always@(test) begin:MONITOR case(test) 1:begin $display("\n***RUNNING CPUtest1-The Basic CPU Diagonostic Program***"); $display("\n TIME PC INSTR ADDR DATA"); $display("------------- ------- -------- ----------- ----------"); while(test==1) @(t_cpu.pc_addr) if((t_cpu.pc_addr%2==1)&&(t_cpu.fetch==1)) #60 PC_addr<=t_cpu.pc_addr-1; IR_addr<=t_cpu.m_adr.ir_addr; #340 $strobe("%t %h %s %h %h",$time,PC_addr,mnemonic,IR_addr,data); endcase endmodule
module topcpu; ……. always@(posedge halt) begin #500 $display("\n*****************************************"); $display("** A HALT INSTRUCTION WAS PROCESSD!!**"); $display("*****************************************"); end always #(`PERIOD/2) clock=~clock; always @(t_cpu.opcode) case(t_cpu.opcode) 3'b000 :mnemonic="HLT"; 3'b001 :mnemonic="SKZ"; 3'b010 :mnemonic="ADD"; 3'b011 :mnemonic="AND"; 3'b100 :mnemonic="XOR"; 3'b101 :mnemonic="LDA"; 3'b110 :mnemonic="STO"; 3'b111 :mnemonic="JMP"; endcase endmodule