1、通用计算机与单片机在硬件结构上的比较通用计算机与单片机在硬件结构上的比较 微型计算机系统 单片机系统微型计算机的组成框图(由多个IC芯片组装在一个主电路板上)数据RAMCPU并行I/O程序ROM定时/计数器串型端口中断控制器扩展I/O端口系统总线(DB、AB、CB)所有基本单元都组装在一个IC芯片上MCS-51单片机MCS-51 MCS-51 单片机内部方框图单片机内部方框图 时钟电路时钟电路4KROM程序存储器程序存储器256BRAM数据存储器数据存储器2X16位位定时定时/计数器计数器CPU处理器处理器64KB总线总线扩展控制器扩展控制器可编程可编程I/O端口端口P0-3可编程可编程串行口
2、串行口MCS-51单片机外型图(单片机外型图(DIP-40封装)封装) MCS-51单片机的逻辑符号图单片机的逻辑符号图VCCRSTXTAL1 P0口XTAL2/EA/PSENALE P1口P3口RXDTXD/INT0/INT1 P2口T0T1/WR/RDGND87C51EPROM型AT89C51ATMELFLASH型MCS-51MCS-51单片机的外形和逻辑符号单片机的外形和逻辑符号cpuABDB地址地址译码器译码器ROMRAMclockresetreadwrite1 1)振荡周期)振荡周期 指为单片机提供定时信号的振荡源的周期,若为内部产生方式时,为石指为单片机提供定时信号的振荡源的周期,
3、若为内部产生方式时,为石英晶体的振荡周期。英晶体的振荡周期。2 2)时钟周期)时钟周期 也称为状态周期,用也称为状态周期,用S表示。时钟周期是计算机中最基本的时间单位,在表示。时钟周期是计算机中最基本的时间单位,在一个时钟周期内,一个时钟周期内,CPUCPU完成一个最基本的动作。完成一个最基本的动作。MCS51单片机中一个时钟周期单片机中一个时钟周期为振荡周期的为振荡周期的2 2倍。倍。3 3)机器周期)机器周期 完成一个基本操作(例如,取指令、存储器读、存储器写等)所需要的完成一个基本操作(例如,取指令、存储器读、存储器写等)所需要的时间称为机器周期。时间称为机器周期。MCS51的一个机器周
4、期含有的一个机器周期含有6 6个时钟周期。个时钟周期。4 4)指令周期)指令周期 完成一条指令所需要的时间称为指令周期。完成一条指令所需要的时间称为指令周期。MCS5l的指令周期含的指令周期含1 14 4个机器周期不等,其中多数为单周期指令,还有个机器周期不等,其中多数为单周期指令,还有2 2周期和周期和4 4周期指令。周期指令。4 4周期指令只周期指令只有乘、除两条指令。有乘、除两条指令。P1P2S1振荡周期时钟周期机器周期机器周期指令周期指令周期XTAL2(OSC)S2S3S4S5S6S1S2S4S5S3S6P1P1P1P1P1P1P1P1P1P1P1P2P2P2P2P2P2P2P2P2P
5、2P2若MCS-51单片机外接晶振为12MHz时,则单片机的四个周期的具体值为:振荡周期1/12MHz1/12s0.0833s时钟周期1/6s0.167s机器周期1s指令周期14s单片机指令功能一览表单片机指令功能一览表 指令指令机器码机器码功能说明功能说明数据传送类指令数据传送类指令 操作码操作码 + 【操作数操作数】MOV A,RnE8EF 寄存器送累加器寄存器送累加器MOV A,dirE5 dir直接字节送累加器直接字节送累加器MOV A,#data74 data 立即数送累加器立即数送累加器NOP00空操作空操作MOV dir,#data75 dir data立即数送直接字节立即数送直
6、接字节MOVX A,DPTR E0外部外部RAM(16位地址位地址)读操作读操作 MOV A,#55NOPMOVX A,DPTR745500E00000000100100011ROM122333000000000100100011RAMA?DPTR0010data7.0enaclkrstaccum7.0accuminst2Parameter.Value.Type.data7.0accum7.0alu_enaopcode2.0clkalu_out7.0zeroaluinst3in7.0data_enadata7.0datactlinst4fetchpc_addr12.0ir_addr12.0ad
7、dr12.0adrinst5Parameter.Value.Type.clkzeroenaopcode2.0inc_pcload_accload_pcrdwrload_irdatactl_enahaltmachineinst6fetchrstclkenamachinectlinst7ir_addr12.0loadclkrstpc_addr12.0counterinst11clkresetfetchalu_enaclk_geninstParameter.Value.Type.VCCclkINPUTVCCresetINPUTVCCdata7.0BIDIRaddr12.0OUTPUTrdOUTPUT
8、wrOUTPUThaltOUTPUTdata7.0enaclkrstopc2.0iraddr12.0registerinst15data7.0enaclkrstaccum7.0accuminst2Parameter.Value.Type.data7.0accum7.0alu_enaopcode2.0alu_out7.0zeroaluclkresetfetchalu_enaclk_geninstParameter.Value.Type.VCCclkINPUTVCCresetINPUTdata7.0enaclkrstopc2.0iraddr12.0registerinst15cpuABDB地址地址
9、译码器译码器ROMRAMclockresetreadwriteD15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0高8位低8位地址码指令码 alu_ena累加器A指令寄存器IR算逻单元ALU数据控制地址选择程序计数器PC控制状态机时钟信号ABDBhaltrdwrclkrstload_accinc_pcload_pcload_irfetchdatactl_ena累加器A指令寄存器IR算逻单元ALU数据控制地址选择程序计数器PC控制状态机时钟信号ABDBhaltrdwrclkrstload_accfetchinc_pcload_pcload_i
10、ralu_enadatactl_enahaltload_irrdinc_pcalu_enafetchclk01234567halt指令指令累加器指令寄存器算逻单元数据控制地址选择程序计数器控制状态机时钟信号ABDBrdload_accfetchinc_pcload_iralu_enadataload_irrdinc_pcalu_enafetchclk01234567LDA 1000B000EE0110001001RAMEEload_accaddress000000011000B00000000001ROM0000020002累加器指令寄存器算逻单元数据控制地址选择程序计数器控制状态机时钟信号A
11、BDBrdload_accfetchinc_pcload_iralu_enadataload_irrdinc_pcalu_enafetchclk01234567ADD 10015001EE1110001001RAM11load_accaddress000200031001500100020003ROM00040004累加器指令寄存器算逻单元数据控制地址选择程序计数器控制状态机时钟信号ABDBrdload_accfetchinc_pcload_iralu_enadataload_irrdinc_pcalu_enafetchclk01234567STO 1001D001EE0110001001RA
12、MFFwraddress000400051001D00100040005ROM00060006Idle S1 S2 S3 S4 S5 S6 S7 S8 S1 S2 S3 S4 S5 S6 S7 S8 S1 S2 S3 S4 S5 S6 S7 S8 idle always (posedge clk) if(reset) begin fetch=0; alu_ena=0; state=idle; end else begin case (state) default:state=idle; endcase endcase (state) S1: begin fetch=1; state=S2; e
13、nd 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 data7.0enaclkrstopc_iraddr15.0registerinst1resetclkload_iropcode2:0ir_addr12:0resetclkload_acca
14、lu_out7:0data7.0enaclkrstaccum7.0accuminst2data7.0enaclkrstaccum7.0accuminst2 in7.0data_enadata7.0datactlinst4data7:0alu_out7:0datactl_enafetchpc_addr12.0ir_addr12.0addr12.0adrinst5ir_addr12.0loadclkrstpc_addr12.0counterinst1000001010011100101110111 3b100: begin if(opcode=JMP) begin inc_pc,load_acc,
15、load_pc,rd=4b0010; wr,load_ir,datactl_ena,halt=4b0000; end else if(opcode=ADD|opcode=ANDD|opcode=XORR|opcode=LDA) begin inc_pc,load_acc,load_pc,rd=4b0001; wr,load_ir,datactl_ena,halt=4b0000; end else if(opcode=STO) begin inc_pc,load_acc,load_pc,rd=4b0000; wr,load_ir,datactl_ena,halt=4b0010; end else
16、 begin inc_pc,load_acc,load_pc,rd=4b0000; wr,load_ir,datactl_ena,halt=4b0000; end state=3b101; end 3b101: begin /operation if(opcode=ADD|opcode=ANDD|opcode=XORR|opcode=LDA) begin inc_pc,load_acc,load_pc,rd=4b0101; wr,load_ir,datactl_ena,halt=4b0000; end else if(opcode=SKZ & zero=1) begin inc_pc,load
17、_acc,load_pc,rd=4b1000; wr,load_ir,datactl_ena,halt=4b0000; end else if(opcode=JMP) begin inc_pc,load_acc,load_pc,rd=4b1010; wr,load_ir,datactl_ena,halt=4b0000; end else if(opcode=STO) begin inc_pc,load_acc,load_pc,rd=4b0000; wr,load_ir,datactl_ena,halt=4b1010; end else begin inc_pc,load_acc,load_pc
18、,rd=4b0000; wr,load_ir,datactl_ena,halt=4b0000; end state=3b110; end 3b110:/idle begin if(opcode=STO) begin inc_pc,load_acc,load_pc,rd=4b0000; wr,load_ir,datactl_ena,halt=4b0010; end else if(opcode=ADD|opcode=ANDD|opcode=XORR|opcode=LDA) begin inc_pc,load_acc,load_pc,rd=4b0001; wr,load_ir,datactl_en
19、a,halt=4b0000; end else begin inc_pc,load_acc,load_pc,rd=4b0000; wr,load_ir,datactl_ena,halt=4b0000; end state=3b111; end 3b111: begin if(opcode=SKZ & zero=1) begin inc_pc,load_acc,load_pc,rd=4b1000; wr,load_ir,datactl_ena,halt=4b0000; end else begin inc_pc,load_acc,load_pc,rd=4b0000; wr,load_ir,dat
20、actl_ena,halt=4b0000; end state=3b000; end default: begin inc_pc,load_acc,load_pc,rd=4b0000; wr,load_ir,datactl_ena,halt=4b0000; state=3b000; end endcase end endtask /-end of task ctl_cycle- endmodulecpuABDB地址地址译码器译码器ROMRAMclockresetreadwriteaddr12.0rom_selram_seladdr_decodeinst8module addr_decode(a
21、ddr,rom_sel,ram_sel); output rom_sel,ram_sel; input 12:0addr; reg rom_sel,ram_sel; always (addr) casex(addr) 13b1_1xxx_xxxx_xxxx:rom_sel,ram_sel=2b01; 13b0_xxxx_xxxx_xxxx:rom_sel,ram_sel=2b10; 13b1_0 xxx_xxxx_xxxx:rom_sel,ram_sel=2b10; default:rom_sel,ram_sel=2b00; endcaseendmodulemodule addr_decode
22、(addr,rom_sel,ram_sel); output rom_sel,ram_sel; input 12:0addr; reg rom_sel,ram_sel; always (addr) casex(addr) 13b1_1xxx_xxxx_xxxx:rom_sel,ram_sel=2b01; 13b0_xxxx_xxxx_xxxx:rom_sel,ram_sel=2b10; 13b1_0 xxx_xxxx_xxxx:rom_sel,ram_sel=2b10; default:rom_sel,ram_sel=2b00; endcaseendmoduleaddr9.0enareadwr
23、itedata7.0raminst9module rom(data,addr,read,ena); output 7:0data; input 12:0addr; input ena,read; reg 7:0mem13h1fff:0; assign data=(read&ena)?memaddr:8hzz;endmoduleaddr12.0readenadata7.0rominst10D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0高8位低8位地址码指令码17.5 RISC_CPU 17.5 RISC_CPU 寻址方式和指令系统寻址方
24、式和指令系统LDA 010FH8EH00H77H56HEDHFFHFFH00H 010FH 010EH 010DH010CH56H地址码指令码17.5 RISC_CPU 17.5 RISC_CPU 寻址方式和指令系统寻址方式和指令系统17.5 RISC_CPU 17.5 RISC_CPU 寻址方式和指令系统寻址方式和指令系统17.5 RISC_CPU 17.5 RISC_CPU 寻址方式和指令系统寻址方式和指令系统累加器指令寄存器算逻单元数据控制地址选择程序计数器控制状态机时钟信号ABDBrdload_accfetchinc_pcload_iralu_enadataload_irrdinc_p
25、calu_enafetchclk01234567LDA 1000B000EE0110001001RAMEEload_accaddress000000011000B00000000001ROM0000020002累加器指令寄存器算逻单元数据控制地址选择程序计数器控制状态机时钟信号ABDBrdload_accfetchinc_pcload_iralu_enadataload_irrdinc_pcalu_enafetchclk01234567ADD 10015001EE1110001001RAM11load_accaddress000200031001500100020003ROM00040004累
26、加器指令寄存器算逻单元数据控制地址选择程序计数器控制状态机时钟信号ABDBrdload_accfetchinc_pcload_iralu_enadataload_irrdinc_pcalu_enafetchclk01234567STO 1001D001EE0110001001RAMFFwraddress000400051001D00100040005ROM0006000600111_00000 /00 BEGIN: JMP TEST_JMP0011_1100 000_00000 /02 HLT0000_0000000_00000 /04 HLT0000_0000101_11000 /06 JM
27、P_OK: LDA DATA_10000_0000001_00000 /08 SKZ0000_0000000_00000 /0A HLT0000_0000101_11000 /0C LDA DATA_20000_0001001_00000 /0E SKZ0000_0000111_00000 /10 JMP SKZ_OK0001_0100000_00000 /12 HLT0000_0000110_11000 /14 SKZ_OK: STO TEMP0000_0010101_11000 /16 LDA DTAT_10000_0000110_11000 /18 STO TEMP0000_001010
28、1_11000 /1A LDA TEMP0000_0010001_00000 /1C SKZ0000_0000000_00000 /1E HLT0000_0000100_11000 /20 XORR DTAT_20000_0001001_00000 /22 SKZ0000_0000000_00000 /24 HLT0000_0000111_00000 /26 JMP XORR_OK0010_0100100_11000 /28 XORR_OK: XORR DATA_20000_0001001_00000 /2A SKZ0000_0000000_00000 /2C HLT0000_0000 000
29、_00000 /2E EDN: HLT0000_0000111_00000 /30 JMP BEGIN0000_00003C111_00000 /3C TST_JMP: JMP JMP_OK0000_0110000_00000 /3E HLT00 00000000 /1800 DATA_1 11111111 /1801 DATA_2 10101010 /1802 TEMP 17.6 RISC_CPU 17.6 RISC_CPU 模块的调试模块的调试cpuABDB地址地址译码器译码器ROMRAMclockresetreadwritedata7.0enaclkrstaccum7.0accumins
30、t2Parameter.Value.Type.data7.0accum7.0alu_enaopcode2.0clkalu_out7.0zeroaluinst3in7.0data_enadata7.0datactlinst4fetchpc_addr12.0ir_addr12.0addr12.0adrinst5Parameter.Value.Type.clkzeroenaopcode2.0inc_pcload_accload_pcrdwrload_irdatactl_enahaltmachineinst6fetchrstclkenamachinectlinst7ir_addr12.0loadclk
31、rstpc_addr12.0counterinst11clkresetfetchalu_enaclk_geninstParameter.Value.Type.VCCclkINPUTVCCresetINPUTVCCdata7.0BIDIRaddr12.0OUTPUTrdOUTPUTwrOUTPUThaltOUTPUTdata7.0enaclkrstopc2.0iraddr12.0registerinst15include clk_gen.vinclude register.vinclude accum.vinclude adr.vinclude alu.vinclude machine.vinc
32、lude machinectl.vinclude counter.vinclude datactl.vtimescale 1ns/1nsmodule cpu(clk,reset,halt,rd,wr,addr,data,opcode,fetch,ir_addr,pc_addr); input clk,reset; output rd,wr,halt; output 12:0addr; output 2:0opcode; output fetch; output 12:0ir_addr,pc_addr; inout 7:0data; wire clk,reset,halt; wire 7:0da
33、ta; wire 12:0addr; wire rd,wr, wire fetch,alu_ena; wire 2:0opcode; wire 12:0ir_addr,pc_addr; wire 7:0alu_out,accum; wire zero,inc_pc,load_acc,load_pc,load_ir,data_ena,contrl_ena;endmodulemodule cpu(clk,reset,halt,rd,wr,addr,data,opcode,fetch,ir_addr,pc_addr); clk_gen m_clkgen(.clk(clk),.reset(reset)
34、,.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
35、(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); d
36、atactl 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); endmoduleinclude cpu.vinclude ram.vinclude rom.vinclude addr_decode.v
37、timescale 1ns/1nsdefine PERIOD 100module topcpu; reg reset_req,clock; integer test; reg (3*8):0mnemonic; reg 12:0PC_addr,IR_addr; wire 7:0data; wire 12:0addr; wire rd,wr,halt,ram_sel,rom_sel; wire 2:0opcode; wire fetch; wire 12:0ir_addr,pc_addr;.endmodulemodule topcpu; reg reset_req,clock;. cpu t_cp
38、u(.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(addr9: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_ad
39、dr_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.endmodulemodule topcpu;.task display_debug_message; begin $display(n*); $display(*test1; to load the 1st diagnostic program. *); end
40、 endtask task test1; begin 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; end endtask.endmodulemodule topcpu;task sys_reset; begin reset_req=0; #(PERIOD*0.7
41、) 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) begin #60
42、 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); end end endcase endendmodulemodule 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) 3b000 :mnemonic=HLT; 3b001 :mnemonic=SKZ; 3b010 :mnemonic=ADD; 3b011 :mnemonic=AND; 3b100 :mnemonic=XOR; 3b101 :mnemonic=LDA; 3b110 :mnemonic=STO; 3b111 :mnemonic=JMP; endcase endmodule