国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

微程序控制型簡單CPU模型Verilog HDL實現

2019-11-08 19:39:04
字體:
來源:轉載
供稿:網友

一、設計目標

 掌握微程序控制器的基本原理 設計可以實現實現基本的指令運算指令、數據傳輸指令、輸入輸出指令、轉移指令;并且具有中斷和原碼一位乘法功能 使用Verilog HDL 在Max Plus2上實現CPU模型的仿真

注:我是在MaxPlus2上實現的,由于MaxPlus2太古老了,推薦大家使用Quartus。

二、指令設計

1、指令格式

單字節指令:

操作碼 OP  4位

目的寄存器 Rd  2位

源寄存器 Rs  2位

雙字節指令:

 

操作碼 OP  4位

目的寄存器 Rd  2位

源寄存器 Rs 2位

立即數字段  8位

 

2、指令集

本CPU模型有13條指令,其中0-9為單字節指令,10-13為雙字節指令。

使用Verilog實現的時候,會在內存之中預先設置好執行的指令,然后模擬仿真,觀察結果。

序號

指令助記符

功能

操作碼

舉例

機器碼

0

IN Rd

輸入

IN←Rd

0000

IN R2

0000 10 00

1

OUT Rs

輸出

OUT←Rs

0001

OUT R1

0001 00 01

2

MOV Rd, Rs

寄存器傳輸

Rd←Rs

0010

MOV R1,R2

0010 10 01

3

ADD Rd, Rs

加運算

Rd←Rs+Rd

并設置Cy,Zero標志

0011

ADD R3,R0

0011 11 00

4

AND Rd, Rs

與運算

Rd←Rs & Rd

并設置Zero標志

0100

AND R1,R0

0100 01 00

5

MUL

原碼一位乘法運算

 {HIGH,LOW}←RD*RS

0101

MUL RD RS

0101 01 10

6

STI

開中斷

0110

STI

0110xxxx

7

CLI

關中斷

0111

CLI

0111xxxx

8

IRET

中斷返回

1000

IRET

1000xxxx

9

HLT

停機

1001

HLT

1001xxxx

10

LDI

Rd←立即數

1010

LDI R1 59

101001xx

01011001

11

LAD

讀內存Rd←MEM

1011

LAD R1

10110100

12

STA

寫內存MEM←Rs

1100

STA R2

11001000

13

JMP target

無條件轉移

PC←地址

1101

JMP 59

110101xx

01011001

14

JC target

條件轉移,有進位時轉移

如果 FC= =1’b1,

 PC←立即數,程序實現轉移。

否則 不修改PC,程序順序執行。

1110

JC 50

11100000

01010000

 

三、CPU結構

結構圖

說明

這些控制信號,會在以下程序中體現。

ALU運算器:

當ALU_B為1時,ALU輸出,否則處于高阻態

S1、S0控制ALU的運算種類

FC進位標志寄存器: 

當做加法指令時,進位保存在FC中

用于條件跳轉指令的判斷條件。

 

 

 

MAR地址寄存器、A、B運算暫存器:

輸出沒有三態控制,即只要輸入到寄存器,輸出就有值了。

 

 

 

程序計數器PC:

當LDPC為1時,在時鐘上升沿,接收數據。

當INC_PC為1時,在時鐘上升沿,實現PC+1。

當PC_B為1時,輸出數據。否則高阻態。

 

內存:

/CE=1 /WE=x,不操作。 

/CE=0 /WE=0 寫內存;/CE=0 /WE=1 讀內存。

讀內存,由內存到MDR,再由MDR到總線。

 

寄存器IR:   

    

 

寄存器R3~R0:

以R0為例:當R_B為1時,R輸出(根據指令判斷),

否則處于高阻態。

當LDR0為1時,在時鐘上升沿,接收數據。     

 

四、 時序

分為兩個節拍

T1:在T1上升沿,微程序控制器工作,設置微指令各字段的值。根據各字段的值,設置微控制信號;各微控制信號,控制各寄存器傳輸到總線BUS。

T2:在T2的上升沿,當LDXXX的信號有效時,將數據從總線輸入到寄存器中

五、微程序控制器

1、微指令格式

運算器

2位

向總線輸出

3位

從總線輸入

3位

下地址

6位

S1 S0

XXX_B

LDXXX

uMA

2、字段說明

XXX_B為1時,XXX部件輸出到總線上。

LDXXX為1時,當T2上升沿到來時,將總線上的數據輸入到XXX部件。

 LDXXX字段

 

 

 

 

 0        

 0        

 0        

 NOP

 0

 0

 1

 LDA

 0

 1 

 0

 LDB

 0

 1

 1

 LDR

 1

 0

 0

 LDOUT    

 1

 0

 1

 LDMAR

 1

 1

 0

 LDIR

 1

 1

 1

 LDPC

 

 XXX_B字段

 

 

 

 0        

 0        

 0        

  NOP       

 0

 0

 1

  ALU_B  

 0

 1

 0

  R_B

 0

 1

 1

  PC_B

 1

 0

 0

  STI

 1

 0

 1

  CLI

 1

 1

 0

  MEM_B 

 1

 1

 1

  IN_B

 C字段

 

 

 

 

 

 0        

 0         

 0       

  NOP       

 0

 0

 1

 P<1>

 0

 1

 0

 P<2>

 0

 1

 1

 P<3>

 1

 0

 0

 P<4>

 1

 0

 1

 P<5>

 1

 1

 0

 保留

 1

 1

 1

 保留

3、微程序流程圖

注:以下是全部指令的流程圖,本文只實現簡單的ADD指令和LDI指令,作為實例。

六、Verilog HDL實現源碼

    主要是通過Verilog 模擬微程序控制器,將各個控制信號作為變量,在不同的時序 對 控制信號進行 賦值、判斷,模擬微程序的流程。    
module CPU(clk,reset,interrupt,T1,T2,PC,MAR,IR,uMA,A,B,ALU,R0,R1,R2,R3,LDR,LDIR,BUS,FC);	input clk,reset,interrupt;	output T1,T2,PC,MAR,IR,uMA,A,B,ALU,R0,R1,R2,R3,LDR,LDIR,BUS,FC;	reg[7:0] MEM0,MEM1,MEM2,MEM3,MEM4; //內存中的普通程序	reg[7:0] R0,R1,R2,R3,ALU,A,B,PC,BUS,MAR,IR;	reg[1:0] S;  // 2位ALU控制字段	reg[2:0] LDXXX,XXX_B; // 三個控制字段	reg[5:0] uMA; // 6位微地址字段	//T1時刻直接XXX_B、設置LDXXX控制信號, T2時刻根據LDXXX信號 從BUS傳數據	reg LDA,LDB,LDR,LDPC,LDOUT,LDMAR,LDIR,INC_PC,FC; // 微控制信號	reg T1;	wire T2;	//產生時序T1 T2;初始內存中的機器指令	always @(posedge clk)	begin		if(reset)			begin				T1 <= 1'b0;				//內存初始賦值(輸入機器指令)MEM			    MEM0 <= 8'b10100000; //立即數傳值->R0				MEM1 <= 8'b10000000;				MEM2 <= 8'b10100100; //立即數傳值->R1				MEM3 <= 8'b10000000;				MEM4 <= 8'b00110001; //R0+R1 ->R0			end		else			//設置時序			T1 <= ~T1;	end	//設置時序	assign T2=~T1;		//T1 設置微代碼各字段	always @(posedge T1)	begin		if(reset)			uMA <= 6'b000000;		else			begin				case(uMA)						6'h00:							begin								S <= 2'b00;								XXX_B <= 3'b101;								LDXXX <= 3'b000;								INC_PC <= 1'b0;								uMA <= 6'h01;							end						6'h01:							begin								S <= 2'b00;								XXX_B <= 3'b000;								LDXXX <= 3'b000;								INC_PC <= 1'b0;								uMA <= 6'h02;							end						6'h02:							begin								S <= 2'b00;								XXX_B <= 3'b011;								LDXXX <= 3'b101;								INC_PC <= 1'b1;								uMA <= 6'h03;							end						6'h03:							begin								S <= 2'b00;								XXX_B <= 3'b110;								LDXXX <= 3'b110;								INC_PC <= 1'b0;								uMA <= 6'h04;							end						6'h04:							begin								S <= 2'b00;								XXX_B <= 3'b000;								LDXXX <= 3'b000;								INC_PC <= 1'b0;								case({IR[7],IR[6],IR[5],IR[4]})									4'b0011:										uMA <= 6'h08; //ADD									4'b1010:										uMA <= 6'h16; //LDI								endcase							end						6'h08: //RD->A							begin								S <= 2'b00;								XXX_B <= 3'b010;								LDXXX <= 3'b001;								INC_PC <= 1'b0;								uMA <= 6'h09;							end						6'h09://RS->B							begin								S <= 2'b00;								XXX_B <= 3'b010;								LDXXX <= 3'b010;								INC_PC <= 1'b0;								uMA <= 6'h0A;							end						6'h0A:  //A+B->RD							begin								S <= 2'b01;								XXX_B <= 3'b001;								LDXXX <= 3'b011;								INC_PC <= 1'b0;								uMA <= 6'h01;							end							6'h16:  //LDI							begin								S <= 2'b00;								XXX_B <= 3'b011;								LDXXX <= 3'b101;								INC_PC <= 1'b1;								uMA <= 6'h17;							end						6'h17:  							begin								S <= 2'b00;								XXX_B <= 3'b110;								LDXXX <= 3'b011;								INC_PC <= 1'b0;								uMA <= 6'h01;							end				endcase			end	end		//設置每字段的控制信號	always @(S or LDXXX or XXX_B)	begin			//ALU運算控制		case(S)				2'b00:					begin						ALU <= ALU;					end				2'b01:					begin						{FC,ALU} <= A + B;					end			endcase		// A字段控制 LDXX		case(LDXXX)				3'b000:					begin						{LDA,LDB,LDR,LDOUT,LDMAR,LDIR,LDPC} <= 7'b0000000;					end				3'b001:					begin						{LDA,LDB,LDR,LDOUT,LDMAR,LDIR,LDPC} <= 7'b1000000;					end				3'b010:					begin						{LDA,LDB,LDR,LDOUT,LDMAR,LDIR,LDPC} <= 7'b0100000;					end				3'b011:					begin						{LDA,LDB,LDR,LDOUT,LDMAR,LDIR,LDPC} <= 7'b0010000;					end				3'b100:					begin						{LDA,LDB,LDR,LDOUT,LDMAR,LDIR,LDPC} <= 7'b0001000;					end				3'b101:					begin						{LDA,LDB,LDR,LDOUT,LDMAR,LDIR,LDPC} <= 7'b0000100;					end				3'b110:					begin						{LDA,LDB,LDR,LDOUT,LDMAR,LDIR,LDPC} <= 7'b0000010;					end				3'b111:					begin						{LDA,LDB,LDR,LDOUT,LDMAR,LDIR,LDPC} <= 7'b0000001;					end		endcase		// B字段控制 XX_B		case(XXX_B)				3'b000:					begin						BUS <= BUS;					end				3'b001:					begin						BUS <= ALU;					end				3'b010:					begin						case({IR[1],IR[0]})							2'b00:								BUS <= R0;							2'b01:								BUS <= R1;							2'b10:								BUS <= R2;							2'b11:								BUS <= R3;						endcase					end				3'b011:					begin						BUS <= PC;					end				3'b100:					begin						STI <= 1'b1;						CLI <= 1'b0;					end				3'b101:					begin						STI <= 1'b0;						CLI <= 1'b1;					end				3'b110:				begin					case(MAR)						8'h00:							BUS <= MEM0;						8'h01:							BUS <= MEM1;						8'h02:							BUS <= MEM2;						8'h03:							BUS <= MEM3;						8'h04:							BUS <= MEM4;					endcase				end				3'b111:					BUS <= IN;		endcase		endendmodul

七、仿真

內存指令:
                                MEM0 <= 8'b10100000; //立即數傳值->R0				MEM1 <= 8'b10000000;				MEM2 <= 8'b10100100; //立即數傳值->R1				MEM3 <= 8'b10000000;				MEM4 <= 8'b00110001; //R0+R1 ->R0

八、結語

 本文只實現了簡單的功能加法、立即數傳值指令,介紹如何使用Verilog 模擬微程序控制器,進而實現一個簡單CPU的功能。實現微程序流程圖中的所有指令的源代碼,在我的GitHub 之中,歡迎大家參考。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 离岛区| 西充县| 视频| 盐山县| 高平市| 泽库县| 酒泉市| 灵台县| 年辖:市辖区| 伊宁县| 公安县| 正宁县| 汉中市| 旬阳县| 浪卡子县| 清原| 益阳市| 吉林省| 安吉县| 阿勒泰市| 廉江市| 古田县| 威远县| 大关县| 孝昌县| 玉溪市| 海伦市| 随州市| 武山县| 崇仁县| 财经| 定州市| 江山市| 苍溪县| 江安县| 柘荣县| 镇康县| 砀山县| 灵川县| 阜新市| 福泉市|