計(jì)算機(jī)組成實(shí)驗(yàn)報(bào)告

          指導(dǎo)教師姓名:戴老師

          學(xué)生姓名:wyz_wx@163.com

          實(shí)驗(yàn)日期:星期六上午

          目錄

          第一部分 運(yùn)用TDM-CM++實(shí)驗(yàn)臺(tái)的實(shí)驗(yàn)

          實(shí)驗(yàn)三:微控制器實(shí)驗(yàn)

          第二部分 Verilog-HDL進(jìn)行計(jì)算機(jī)設(shè)計(jì)的實(shí)驗(yàn)

          實(shí)驗(yàn)一:帶進(jìn)位的四位加法器

          實(shí)驗(yàn)二:時(shí)鐘發(fā)生器

          實(shí)驗(yàn)三:指令寄存器

          實(shí)驗(yàn)五:數(shù)據(jù)控制器

          實(shí)驗(yàn)九:狀態(tài)控制器

          附一CPU設(shè)計(jì)

          附二:實(shí)驗(yàn)波形圖

          第一部分 運(yùn)用TDM-CM++實(shí)驗(yàn)臺(tái)的實(shí)驗(yàn)

          實(shí)驗(yàn)三:微控制器實(shí)驗(yàn)

          (與《實(shí)驗(yàn)五:基本微型機(jī)設(shè)計(jì)與實(shí)現(xiàn)》一起分析)

          [實(shí)驗(yàn)?zāi)康?/span>]

          1 掌握時(shí)序產(chǎn)生器的組成原理。
          2 掌握微程序控制器的組成原理。
          3 掌握微程序的編制,寫入,觀察微程序的運(yùn)行。

          [實(shí)驗(yàn)設(shè)備]

          TDN-CM++計(jì)算機(jī)組成原理教學(xué)實(shí)驗(yàn)系統(tǒng)一臺(tái)。

          [實(shí)驗(yàn)原理]

          1. 時(shí)序控制電路

          時(shí)序控制電路采用一片CPLD芯片,電路框圖如圖。產(chǎn)生4個(gè)等間隔的時(shí)序信號(hào)TS1TS4

          φ:時(shí)鐘脈沖輸入端,接到方波發(fā)生器的輸出(H23)。WI調(diào)頻率,W2調(diào)脈寬。
          START鍵是實(shí)驗(yàn)板上一個(gè)微動(dòng)開關(guān)START的按鍵信號(hào)。
          STEP(單步開關(guān)):STEP開關(guān)為0時(shí)(EXEC),一旦按下啟動(dòng)鍵,時(shí)序信號(hào)TS1TS4將周而復(fù)始地發(fā)送出去。
          STOP:撥動(dòng)開關(guān)。STOP停機(jī);RUN運(yùn)行。
          CLR:撥動(dòng)開關(guān)。時(shí)序清零。
          TS1~TS4等間隔的時(shí)序信號(hào)輸出。
          2 微指令格式

          微指令字長共24位,其中UA5UA06位的后續(xù)微地址,ABC為三個(gè)譯碼字段,分別由三個(gè)控制位譯碼出多位。

          24

          23

          22

          21

          20

          19

          18

          17

          16

          15 14 13

          12 11 10

          9 8 7

          6

          5

          4

          3

          2

          1

          S3

          S2

          S1

          S0

          M

          Cn

          WE

          A9

          A8

          A

          B

          C

          μA5

          μA4

          μA3

          μA2

          μA1

          μA0

          3 微程序控制電路

          微程序控制電路組成:控制存儲(chǔ)器、微命令寄存器、微地址寄存器。

          編程開關(guān) : PROM(編程):根據(jù)微地址和微指令格式將微指令二進(jìn)制代碼寫入到控制存儲(chǔ)器中;READ(校驗(yàn)):可以對寫入控制存儲(chǔ)器中的二進(jìn)制代碼進(jìn)行驗(yàn)證;RUN(運(yùn)行):只要給出微程序的入口微地址,則可根據(jù)微程序流程圖自動(dòng)執(zhí)行微程序。

          [實(shí)驗(yàn)步驟以及結(jié)果]

          1 連接實(shí)驗(yàn)線路,接通電源。
          2 運(yùn)行實(shí)驗(yàn)臺(tái)系統(tǒng)程序NCMP53,按F7
          3 把時(shí)序電路中“STOP”開關(guān)置“RUN”、“STEP”開關(guān)置“EXEC”,按START,用PC模擬字波器觀察φ,TS1~TS4波形,畫出波形圖,測出周期和脈沖寬度。
          4 聯(lián)機(jī)裝載微程序(把編程開關(guān)撥到PROM狀態(tài))(按F4,輸入文件名EXI.TXT)檢查微程序是否正確(按F3,輸入起始地址,對照37頁微程序代碼。)運(yùn)行實(shí)驗(yàn)臺(tái)系統(tǒng)程序NCMP53,按F7
          5 SWITCH單元μMA5~μAO接線接到微控制器單元的SE6~SE1MA5~MA0全置“1”。單步運(yùn)行微程序。通過改變開關(guān)狀態(tài),把所有微程序全部執(zhí)行。(注意:微地址“1”要變“0”)

          [解釋數(shù)據(jù)通路]

          結(jié)合實(shí)驗(yàn)五,對照微程序流程圖和基本微型機(jī)的硬件組成解釋數(shù)據(jù)通路:

          SWA

          SWB

          控制臺(tái)命令

          0

          0

          讀內(nèi)存

          0

          1

          寫內(nèi)存

          1

          1

          啟動(dòng)程序

          默認(rèn)SWA=1SWB=1,處于啟動(dòng)程序狀態(tài)。經(jīng)過控制臺(tái)指令地址從00-》01,啟動(dòng)控制臺(tái)。

          第二部分 用Verilog-HDL進(jìn)行計(jì)算機(jī)設(shè)計(jì)的實(shí)驗(yàn)

          [實(shí)驗(yàn)?zāi)康腯

          1 了解工作原理。
          2 學(xué)會(huì)編寫模塊程序
          3 學(xué)會(huì)編寫測試的模塊程序。

          [實(shí)驗(yàn)設(shè)備]

          1 常用微機(jī)一臺(tái);
          2 Model Sim SEPLUS5.6 軟件一套。

          [實(shí)驗(yàn)步驟]

          1 編寫模塊程序;
          2 編寫測試程序;
          3 編輯編譯這兩個(gè)模塊程序;
          4 運(yùn)行模擬、觀察波形、驗(yàn)證設(shè)計(jì)的正確性。

          [實(shí)驗(yàn)內(nèi)容]

          實(shí)驗(yàn)一 帶進(jìn)位四位加法器

          實(shí)驗(yàn)二 時(shí)鐘發(fā)生器

          實(shí)驗(yàn)五 數(shù)據(jù)控制器

          實(shí)驗(yàn)九 狀態(tài)控制器

          附:實(shí)驗(yàn)十:CPU

          實(shí)驗(yàn)一:帶進(jìn)位的四位加法器

          [實(shí)驗(yàn)原理]

          4位輸入信號(hào):add_a[4],add_b[4]

          輸入進(jìn)位:carry

          時(shí)鐘信號(hào):clk

          4位輸出信號(hào):sum[4]

          進(jìn)位信號(hào):flow

          [實(shí)驗(yàn)步驟以及結(jié)果]

          1. 模塊程序add4.v

          module add4(add_a,add_b,sum,flow,clk,carry);

          output [3:0] sum; //聲明輸出信號(hào)sum

          output flow; //聲明輸出高位進(jìn)位float

          input [3:0] add_a,add_b; //聲明兩個(gè)4位二進(jìn)制的輸入信號(hào)add_aadd_b

          input carry; //聲明輸入信號(hào)低位進(jìn)位信號(hào)carry

          input clk; //聲明時(shí)鐘信號(hào)CLK

          reg [3:0] sum; //定義了一個(gè)4位的名為SUM的寄存器

          reg flow; //定義了一個(gè)1位的名為FLOW的寄存器

          always@(negedge clk) //CLK下降沿時(shí),執(zhí)行下列語句

          begin

          sum<=add_a+add_b+carry;//sum<=add_a+add_b+carry;

          end

          always@(posedge clk) //CLK上升沿時(shí),執(zhí)行下列語句

          begin

          flow<=(add_a[3]&add_b[3])|((add_a[3]|add_b[3])&sum[3]<1);

          end //計(jì)算FLOW的數(shù)值

          endmodule

          2.測試程序add4_test.tst

          module add4_test;

          reg [3:0] add_a,add_b;

          reg carry;

          reg clk;

          wire [3:0] sum;

          wire flow;

          add4 add4(add_a,add_b,sum,flow,clk,carry);

          initial begin

          carry=0;

          clk=1;

          add_a=4'b1011;

          add_b=4'b0101;

          end

          always #1 clk=~clk; //產(chǎn)生時(shí)鐘信號(hào)

          always #5 carry=~carry; //間隔5,低位進(jìn)位信號(hào)改變數(shù)值

          always@(posedge clk)

          begin

          add_a<=add_b+1;

          add_b<=add_a+1; //改變add_aadd_b

          end

          endmodule

          3.仿真波形,見附件圖;

          實(shí)驗(yàn)二:時(shí)鐘發(fā)生器

          [實(shí)驗(yàn)原理]

          時(shí)鐘發(fā)生器clkgen利用外來時(shí)鐘信號(hào)材料clk1,fetch,aluclk,送往CPU的其他部見。其中fetch是外部時(shí)鐘,利用fetch的上升沿來觸發(fā)CPU控制器開始執(zhí)行一條指令,同時(shí)fetch信號(hào)還將控制地址多路器輸出指令地址和數(shù)據(jù)地址;clk1信號(hào)用作指令寄存器、累加器、狀態(tài)控制器的時(shí)鐘信號(hào);alu_clk則用于觸發(fā)算術(shù)邏輯運(yùn)算單元。

          時(shí)鐘信號(hào):clk

          中間信號(hào):clk2=~clk2(clk1↑);clk4=~clk4(clk2↓)

          輸出信號(hào):clk1=~clk;

          fetch=~fetch(clk4↑);

          alu_clk=clk2&clk4&!fetch

          [實(shí)驗(yàn)步驟以及結(jié)果]

          1. 模塊程序clkgen.v

          module clkgen(clk,clk1,fetch,alu_clk);

          output clk1,fetch,alu_clk; //聲明輸出變量clk1,fetch,alu_clk

          input clk; //聲明時(shí)鐘信號(hào)clk

          reg clk2,clk4,fetch; //定義3個(gè)1位寄存器名為clk2,clk4,fetch

          initial //初始化

          begin

          clk2=0;

          clk4=1;

          fetch=0;

          end

          assign clk1=~clk; //邏輯功能定義

          assign alu_clk=clk2&clk4&!fetch;

          always@(posedge clk1) //每當(dāng)clk1的信號(hào)出現(xiàn)上升沿時(shí),下列語句被不斷重復(fù)執(zhí)行

          begin

          clk2<=~clk2;

          end

          always@(negedge clk2)

          begin

          clk4<=~clk4;

          end

          always@(posedge clk4)

          begin

          fetch<=~fetch;

          end

          endmodule

          2. 測試程序clkgen_test.v

          module clkgen_test;

          reg clk;reg clk2;reg clk4;

          clkgen clkgen(clk,clk1,fetch,alu_clk);

          initial

          begin

          clk=1;

          end

          always #1 clk=~clk; //信號(hào)反相,#1表示延遲1個(gè)時(shí)間單位。

          endmodule

          3.仿真波形,見附錄二。

          實(shí)驗(yàn)六:數(shù)據(jù)控制器

          [實(shí)驗(yàn)原理]

          數(shù)據(jù)控制器的作用是控制累加器數(shù)據(jù)輸出,由于數(shù)據(jù)總線是各種操作時(shí)傳送數(shù)據(jù)的公共通道,不同的情況下傳送不同的內(nèi)容。累加器的數(shù)據(jù)只有在需要往RAM區(qū)或端口寫時(shí)才允許輸出,否則應(yīng)呈現(xiàn)高阻態(tài),以允許其他部件使用數(shù)據(jù)總線。數(shù)據(jù)控制其何時(shí)輸出累加器的數(shù)據(jù)則由狀態(tài)控制器輸出的控制信號(hào)DAYA_ENA決定。

          [實(shí)驗(yàn)步驟以及結(jié)果]

          1模塊程序datactl.v

          module datactl(data,in,data_ena);

          output[7:0] data;

          input[7:0] in;

          input data_ena; //聲明輸入輸出

          assign data=(data_ena)?in:8'bzzz_zzzz;//當(dāng)data_ena為真,則允許輸出,否則

          //呈現(xiàn)高阻態(tài)

          endmodule

          2.測試程序datactl_test.v

          module datactl_test;

          wire [7:0] data;

          reg [7:0] in;

          reg data_ena;

          datactl datactl(data,in,data_ena);

          initial begin

          data_ena=0;

          in<=8'b0101_0101;

          end

          always #1 data_ena=~data_ena; //間隔2nsdata_ena改變

          always #1 in=in+1; //間隔1nsin的值在原來的基礎(chǔ)上增1

          endmodule

          3.仿真波形,見附錄二。

          實(shí)驗(yàn)九:狀態(tài)控制器

          [實(shí)驗(yàn)原理]

          狀態(tài)控制器有兩部分組成:(1)狀態(tài)機(jī);(2)狀態(tài)控制器。

          狀態(tài)控制器接受復(fù)位信號(hào)RST,當(dāng)RST有效時(shí)通過信號(hào)ENA使其為0,輸入到狀態(tài)機(jī)中停止?fàn)顟B(tài)機(jī)的工作。

          狀態(tài)機(jī)時(shí)CPU的控制核心,用于產(chǎn)生一系列的狀態(tài)信號(hào),啟動(dòng)或停止某些部件。CPU何時(shí)進(jìn)行讀指令讀寫I/O端口,RAM區(qū)等操作,都是由狀態(tài)機(jī)來控制的。狀態(tài)機(jī)的當(dāng)前狀態(tài),由變量STATE記錄,STATE的值就是當(dāng)前這個(gè)指令周期中經(jīng)過的時(shí)鐘數(shù)。

          指令周期由8個(gè)時(shí)鐘周期組成,每個(gè)時(shí)鐘周期都要完成固定的操作。

          第0個(gè)時(shí)鐘,因?yàn)镃PU狀態(tài)控制器的輸出RD和LOAD_IR為高電平,其余均為低電平。指令寄存器寄存由ROM送來的高8位指令代碼。

          第1個(gè)時(shí)鐘,與上一時(shí)鐘相比只是INC_PC從0變?yōu)?,故PC增1,ROM送來低8位指令代碼,指令寄存器寄存該8位代碼。

          第2個(gè)時(shí)鐘,空操作。

          第3個(gè)時(shí)鐘,PC增1,指向下一條指令。若操作符為HLT,則輸出信號(hào)HLT為高;如果操作符不為HLT,除了PC增1外,其他各控制線輸出為零。

          第4個(gè)時(shí)鐘,若操作符號(hào)為ANDD,ADD,XORR或LDA,讀相應(yīng)地址的數(shù)據(jù);若為JMP,將目的地址送給程序計(jì)數(shù)器;若為STO,輸出累加器數(shù)據(jù)。

          第5個(gè)時(shí)鐘,若操作符為ANDD,ADD,XORR,算術(shù)運(yùn)算器就進(jìn)行相應(yīng)的運(yùn)算;若為LDA,就把數(shù)據(jù)通過算術(shù)運(yùn)算器送給累加器;若為SKZ,線判斷累加器的值是否為0,如果為,PC增1,否則保持原值;若為JMP,鎖存目的地址;若為STO,將數(shù)據(jù)寫入地址處。

          第6個(gè)時(shí)鐘,空操作。

          第7個(gè)時(shí)鐘,若操作符為SKZ且累加器值為0,則PC值再增加1,跳過一條指令,否則PC無變化。

          [實(shí)驗(yàn)步驟以及結(jié)果]

          1模塊程序machinectl.v

          module machinectl(ena,fetch,rst);

          output ena;

          input fetch,rst; //聲明輸入和輸出

          reg ena; //定義ena的寄存器

          always @(posedge fetch or posedge rst)//當(dāng)fetch或者rst信號(hào)出現(xiàn)上升沿時(shí),

          begin //根據(jù)rst的值確定ena的值

          if(rst)

          ena<=0;

          else

          ena<=1;

          end

          endmodule

          machine.v

          module machine(inc_pc,load_acc,load_pc,rd,wr,load_ir,datactl_ena,

          halt,clk1,zero,ena,opcode);

          output inc_pc,load_acc,load_pc,rd,wr,load_ir;

          output datactl_ena,halt;

          input clk1,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 //parameter來定義標(biāo)識(shí)符形式的常量

          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 clk1)

          begin

          if(!ena) //如果接收到復(fù)位信號(hào)RST,進(jìn)行復(fù)位操作

          begin

          state<=3'b000;

          {inc_pc,load_acc,load_pc,rd}<=4'b0000;

          {wr,load_ir,datactl_ena,halt}<=4'b0000;

          end

          else

          ctl_cycle; //執(zhí)行任務(wù)ctl_cycle

          end

          //------------task ctl_cycle------------任務(wù)開始---------

          task ctl_cycle;

          begin

          casex(state) //case語句

          0: //rdload_ir均為高電平,其余為低電平。指令寄存器寄

          Begin //存由ROM送來的高8位指令代碼

          {inc_pc,load_acc,load_pc,rd}<=4'b0001;

          {wr,load_ir,datactl_ena,halt}<=4'b0100;

          state<=1;

          end

          1: //INC_PC0變?yōu)?/span>1,故PC1ROM送來低8位指令代碼,

          Begin //指令寄存器寄存該8位代碼

          {inc_pc,load_acc,load_pc,rd}<=4'b1001;

          {wr,load_ir,datactl_ena,halt}<=4'b0100;

          state<=2;

          end

          2: //空操作

          Begin

          {inc_pc,load_acc,load_pc,rd}<=4'b0000;

          {wr,load_ir,datactl_ena,halt}<=4'b0000;

          state<=3;

          end

          3: //PC1,指向下一條指令

          begin

          if(opcode==HLT) //若操作符為HLT,則輸出信號(hào)HLT為高

          begin

          {inc_pc,load_acc,load_pc,rd}<=4'b1000;

          {wr,load_ir,datactl_ena,halt}<=4'b0001;

          end

          else //否則其他各控制線輸出為零。

          begin

          {inc_pc,load_acc,load_pc,rd}<=4'b1000;

          {wr,load_ir,datactl_ena,halt}<=4'b0000;

          end

          state<=4;

          end

          4:

          begin

          if(opcode==JMP) //若為JMP,將目的地址送給程序計(jì)數(shù)器

          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)

          begin //若操作符號(hào)為ANDD,ADD,XORRLDA,讀相應(yīng)地址的數(shù)據(jù)

          {inc_pc,load_acc,load_pc,rd}<=4'b0001;

          {wr,load_ir,datactl_ena,halt}<=4'b0000;

          end

          else

          if(opcode==STO) //若為STO,輸出累加器數(shù)據(jù)

          begin {inc_pc,load_acc,load_pc,rd}<=4'b0000;

          {wr,load_ir,datactl_ena,halt}<=4'b0010;

          end

          else

          begin //其他則為空操作

          {inc_pc,load_acc,load_pc,rd} <=4'b0000;

          {wr,load_ir,datactl_ena,halt}<=4'b0000;

          end

          state<=5;

          end

          5:

          begin

          if(opcode==ADD||opcode==ANDD||opcode==XORR||opcode==LDA)

          begin //若操作符為ANDD,ADD,XORR,算術(shù)運(yùn)算器就進(jìn)行相應(yīng)的運(yùn)算

          {inc_pc,load_acc,load_pc,rd} <=4'b0101;

          {wr,load_ir,datactl_ena,halt}<=4'b0000;

          end

          else

          if (opcode==SKZ&&zero==1) //若為SKZ,線判斷累加器的值是否為0,如果為,

          begin // PC1,否則保持原值

          {inc_pc,load_acc,load_pc,rd} <=4'b1000;

          {wr,load_ir,datactl_ena,halt}<=4'b0000;

          end

          else

          if(opcode==JMP) //若為JMP,鎖存目的地址

          begin

          {inc_pc,load_acc,load_pc,rd} <=4'b1010;

          {wr,load_ir,datactl_ena,halt}<=4'b0000;

          end

          else

          if(opcode==STO) //若為STO,將數(shù)據(jù)寫入地址處

          begin

          {inc_pc,load_acc,load_pc,rd} <=4'b0000;

          {wr,load_ir,datactl_ena,halt}<=4'b1010;

          end

          else

          begin //其他則為空操作

          {inc_pc,load_acc,load_pc,rd} <=4'b0000;

          {wr,load_ir,datactl_ena,halt}<=4'b0000;

          end

          state<=6;

          end

          6:

          begin

          if(opcode==STO) //若為STO,將數(shù)據(jù)寫入地址處

          begin

          {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)

          begin //若操作符號(hào)為ANDD,ADD,XORRLDA,讀相應(yīng)地址的數(shù)據(jù)

          {inc_pc,load_acc,load_pc,rd} <=4'b0001;

          {wr,load_ir,datactl_ena,halt}<=4'b0000;

          end

          else //其余為空操作

          begin

          {inc_pc,load_acc,load_pc,rd} <=4'b0000;

          {wr,load_ir,datactl_ena,halt}<=4'b0000;

          end

          state<=7;

          end

          7:

          begin

          if(opcode==SKZ&&zero==1) //若操作符為SKZ且累加器值為0

          begin //PC值再增加1,跳過一條指令,否則PC無變化

          {inc_pc,load_acc,load_pc,rd} <=4'b1000;

          {wr,load_ir,datactl_ena,halt}<=4'b0000;

          end

          else

          begin

          {inc_pc,load_acc,load_pc,rd} <=4'b0000;

          {wr,load_ir,datactl_ena,halt}<=4'b0000;

          end

          state<=0;

          end

          default: //缺省為空操作

          begin

          {inc_pc,load_acc,load_pc,rd} <=4'b0000;

          {wr,load_ir,datactl_ena,halt}<=4'b0000;

          state<=0;

          end

          endcase

          end

          endtask

          //-------------end of task ctl_cycle-----任務(wù)結(jié)束-----------------

          endmodule

          control.v

          module control(clk1, zero, fetch, rst, opcode, inc_pc, load_acc, load_pc, rd, wr, load_ir, halt, datactl_ena);

          output inc_pc,load_acc,load_pc,rd,wr,load_ir;

          output datactl_ena,halt;

          input clk1,zero,fetch,rst;

          input [2:0] opcode; //聲明輸入和輸出

          wire ena; //定義wire類型的ena

          machinectl machinectl(.fetch(fetch),.rst(rst),.ena(ena));

          machine machine(.clk1(clk1),.zero(zero),.opcode(opcode), .ena(ena),.inc_pc(inc_pc),.load_acc(load_acc),.load_pc(load_pc),

          .rd(rd),.wr(wr),.load_ir(load_ir),.halt(halt),.datactl_ena(datactl_ena)); //machinectlmachine連接起來

          //machinectl.vmachine.v均為上層文件

          endmodule

          2.測試程序control_test.tst

          module control_test;

          wire inc_pc ,load_acc ,load_pc, rd, wr ,load_ir ,datactl_ena, halt;

          wire clk1,fetch,alu_clock;

          reg zero, rst;

          reg [2:0] opcode;

          reg clk;

          clkgen clkgen(clk,clk1,fetch,alu_clk);

          //用一個(gè)CLKGEN部件來產(chǎn)生clk1,fetch序列

          control control(clk1, zero, fetch, rst, opcode, inc_pc, load_acc, load_pc, rd, wr, load_ir, halt, datactl_ena);

          initial begin

          rst=0;

          clk=1;

          zero=0;

          opcode=3'b000;

          end

          always #1 clk=~clk; //產(chǎn)生時(shí)鐘信號(hào),1個(gè)時(shí)鐘周期為2nm

          always #160 zero=~zero;

          always #16 opcode<=opcode+1;//經(jīng)過8個(gè)時(shí)鐘信號(hào)周期,opcode改變一次

          endmodule

          3.仿真波形,見附錄二;

          附錄一:

          實(shí)驗(yàn)十:CPU

          源代碼

          包含:

          accum.v累加器

          adr.v地址多路器

          alu.v算術(shù)運(yùn)算器

          clkgen.v 時(shí)鐘發(fā)生器

          control.v 狀態(tài)控制器

          machine.v

          machinectl.v

          counter.v程序計(jì)數(shù)器

          datactl.v數(shù)據(jù)控制器

          register.v指令寄存器

          sig.v //生成信號(hào)CLK

          addr_decode.v

          ram.v

          rom.v //外部器件

          cpu.v //CPU集成

          risc.v //CPU+外部器件

          rscsys_ex1.v //測試仿真文件

          test1.dat

          test1.pro

          test2.dat

          test2.pro

          test3.dat

          test3.pro

          cpu.v

          module cpu(rst,clk,rd,wr,halt,addr,data);

          input rst;

          input clk;

          output rd;

          output wr;

          output halt;

          output [12:0] addr;

          output [7:0] data;

          wire clk1 fetch alu_clk;

          wire [15:0] opc_iraddr;

          wire [7:0] accum_data;

          wire [7:0] alu_out;

          wire zeroinc_pc load_acc load_pcload_ir datactl_ena;

          wire [12:0] pc_addr;

          wire [7:0] data_altera;

          register register26p(.opc_iraddr(opc_iraddr), .data(data_altera), .ena(load_ir), .clk1(clk1), .rst(rst));

          clkgen clkgen27p(.clk(clk), .clk1(clk1), .fetch(fetch), .alu_clk(alu_clk));

          accum accum1p(.accum(accum_data), .data(alu_out), .ena(load_acc), .clk1(clk1), .rst(rst));

          datactl datactl24p(.data(data_altera), .in(alu_out),.data_ena(datactl_ena));

          adr adr22p(.addr(addr), .fetch(fetch), .ir_addr(opc_iraddr[12:0]), .pc_addr(pc_addr));

          counter counter11p( .pc_addr(pc_addr), .ir_addr(opc_iraddr[12:0]), .load(load_pc), .clock(inc_pc), .rst(rst));

          alu alu15p(.alu_out(alu_out), .zero(zero), .data(data_altera), .accum(accum_data), .alu_clk(alu_clk), .opcode(opc_iraddr[15:13]));

          control control12p(.clk1(clk1), .zero(zero), .fetch(fetch), .rst(rst), .opcode(opc_iraddr[15:13]),.inc_pc(inc_pc), .load_acc(load_acc), .load_pc(load_pc), .rd(rd), .wr(wr), .load_ir(load_ir), .halt(halt), .datactl_ena(datactl_ena));

          assign data = data_altera;

          endmodule

          sig.v

          module sig(clk);

          output clk;

          reg clock;

          initial

          begin

          clock=0;

          end

          assign clk=clock;

          always #1 clock=~clock;

          endmodule

          Risc.v

          module risc(rst);

          reg rst;

          wire clk, read, write, halt;

          wire [7:0] data;

          wire [12:0] addr;

          wire ramsel, romsel;

          sig sys_sig5p(.clk(clk));

          cpu sys_rsc4p(.rst(rst),.clk(clk),.rd(read),.wr(write),.halt(halt),.addr(addr[12:0]),.data(data[7:0]));

          ram sys_ram3p(.data(data[7:0]),.addr(addr[9:0]), .ena(ramsel), .read(read), .write(write));

          rom sys_rom1p(.addr(addr[12:0]),.ena(romsel), .read(read), .data(data[7:0]));

          addr_decode sys_addr_decode2p(.addr(addr[12:0]), .romsel(romsel), .ramsel(ramsel));

          endmodule

          recsya_ex1.v

          //------------------------rscsys_ex1.v-------------------------------

          `define VLP vlog1

          `define PERIOD 100 //matches clkgen/vlog_behaviorial/verilog.v

          module rscsys_ex1;

          reg reset_req;

          integer test;

          reg [(3*8):0] mnemonic; //array that holds 3 8-bit ASCII characters

          reg [12:0] PC_addr,IR_addr;

          assign `VLP.rst =reset_req;

          risc vlog1(rst);

          initial //display time in nanoseconds

          begin

          $timeformat(-9,1,"ns",12);

          display_debug_message;

          end

          always @(posedge `VLP.halt) // STOP when HALT instruction decoded

          begin

          #500

          $display("\n************************************");

          $display("*A HALT INSTRUCTION WAS PROCESSED!!! *");

          $display("************************************\n");

          display_debug_message;

          end

          task display_debug_message;

          begin

          $display("\n************************************");

          $display("*THE FOLLOWING DEBUG TASK ARE AVAILABLE: *");

          $display("* test1 to load the 1st diagnostic program. *");

          $display("* test2 to load the 2nd diagnostic program. *");

          $display("* test3 to load the Fibonacci program.*");

          $display("************************************\n");

          test1;

          test2;

          test3;

          $stop;

          end

          endtask

          task test1;

          begin

          test = 0;

          disable MONITOR;

          $readmemb("test1.pro",`VLP.sys_rom1p.memory);

          $display("rom loaded successfully!");

          $readmemb("test1.dat",`VLP.sys_ram3p.ram);

          $display("ram loaded successfully!");

          #1 test = 1;

          sys_reset;

          end

          endtask

          task test2;

          begin

          test = 0;

          disable MONITOR;

          $readmemb("test2.pro",`VLP.sys_rom1p.memory);

          $display("rom loaded successfully!");

          $readmemb("test2.dat",`VLP.sys_ram3p.ram);

          $display("ram loaded successfully!");

          #1 test = 2;

          sys_reset;

          end

          endtask

          task test3;

          begin

          test = 0;

          disable MONITOR;

          $readmemb("test3.pro",`VLP.sys_rom1p.memory);

          $display("rom loaded successfully!");

          $readmemb("test3.dat",`VLP.sys_ram3p.ram);

          $display("ram loaded successfully!");

          #1 test = 3;

          sys_reset;

          end

          endtask

          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 results when running test 1

          $display("\n*** RUNNING CPUtest1 ----The Basic CPU Diagnostic Program ***");

          $display("\n TIME PC INSTR ADDR DATA");$display("-------");

          while(test==1)

          @(`VLP.sys_rsc4p.adr22p.pc_addr)

          if((`VLP.sys_rsc4p.adr22p.pc_addr%2==1)&&(`VLP.sys_rsc4p.adr22p.fetch==1))

          begin

          #60 PC_addr<=`VLP.sys_rsc4p.adr22p.pc_addr-1;

          IR_addr<=`VLP.sys_rsc4p.adr22p.ir_addr;

          #340 $strobe("%t %h %s %h %h",

          $time,PC_addr,mnemonic,IR_addr,`VLP.data);

          end

          end

          2:begin

          $display("\n***RUNNING CPUtest2-The ad cpu program***");

          $display("\n time pc instr addr data");

          $display("-------------------------");

          while(test==2)

          @(`VLP.sys_rsc4p.adr22p.pc_addr)

          if((`VLP.sys_rsc4p.adr22p.pc_addr%2==1)&&(`VLP.sys_rsc4p.adr22p.fetch==1))

          begin

          #60 PC_addr<=`VLP.sys_rsc4p.adr22p.pc_addr-1;

          IR_addr<=`VLP.sys_rsc4p.adr22p.ir_addr;

          #340 $strobe("%t %h %s %h %h",

          $time,PC_addr,mnemonic,IR_addr,`VLP.data);

          end

          end

          3:begin

          $display("\n***RUNNING CPUtest3- an executable program***");

          $display("***this pro should calculate the fibaci");

          $display("***no sequence from 0 to 144***");

          $display("\nTIME FIBOCI NO");

          $display("-------------------------");

          while(test==3)

          begin

          wait(`VLP.sys_rsc4p.alu15p.opcode==3'h1)

          $strobe("%t %d",$time,`VLP.sys_ram3p.ram[10'h2]);

          wait(`VLP.sys_rsc4p.alu15p.opcode!=3'h1);

          end

          end

          endcase

          end

          always@(`VLP.sys_rsc4p.alu15p.opcode)

          case(`VLP.sys_rsc4p.alu15p.opcode)

          3'h0 :mnemonic="HLT";

          3'h1 :mnemonic="SKZ";

          3'h2 :mnemonic="ADD";

          3'h3 :mnemonic="AND";

          3'h4 :mnemonic="XOR";

          3'h5 :mnemonic="LDA";

          3'h6 :mnemonic="STO";

          3'h7 :mnemonic="JMP";

          default : mnemonic="???";

          endcase

          endmodule

          posted on 2007-06-07 07:47 閑情萬萬 閱讀(3672) 評(píng)論(2)  編輯  收藏

          只有注冊用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 望奎县| 长垣县| 砀山县| 大理市| 商河县| 科技| 清镇市| 利辛县| 泗洪县| 唐山市| 来凤县| 县级市| 边坝县| 仪陇县| 屏东市| 龙岩市| 扶余县| 十堰市| 嵊州市| 全椒县| 乌拉特中旗| 宜良县| 宜丰县| 当涂县| 庆城县| 高陵县| 襄城县| 舒城县| 玉溪市| 杭锦旗| 恩施市| 玉屏| 常熟市| 蒙自县| 五大连池市| 凤山县| 图木舒克市| 东乌珠穆沁旗| 子洲县| 和政县| 大城县|