- 第一部分 運(yùn)用TDM-CM++實(shí)驗(yàn)臺(tái)的實(shí)驗(yàn)
- 第二部分 用Verilog-HDL進(jìn)行計(jì)算機(jī)設(shè)計(jì)的實(shí)驗(yàn)
- 附錄一:
計(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)行。
- 2. 掌握微程序控制器的組成原理。
[實(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)TS1-TS4。
- φ:時(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)TS1-TS4將周而復(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位,其中UA5-UA0為6位的后續(xù)微地址,A、B、C為三個(gè)譯碼字段,分別由三個(gè)控制位譯碼出多位。
- START鍵是實(shí)驗(yàn)板上一個(gè)微動(dòng)開關(guān)START的按鍵信號(hào)。
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í)行微程序。
_img_0.jpg)
[實(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~SE1,MA5~MA0全置“1”。單步運(yùn)行微程序。通過改變開關(guān)狀態(tài),把所有微程序全部執(zhí)行。(注意:微地址“1”要變“0”)
- 2. 運(yùn)行實(shí)驗(yàn)臺(tái)系統(tǒng)程序NCMP53,按F7 。
[解釋數(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=1;SWB=1,處于啟動(dòng)程序狀態(tài)。經(jīng)過控制臺(tái)指令地址從00-》01,啟動(dòng)控制臺(tái)。
_img_3.jpg)
第二部分 用Verilog-HDL進(jìn)行計(jì)算機(jī)設(shè)計(jì)的實(shí)驗(yàn)
[實(shí)驗(yàn)?zāi)康腯
- 1. 了解工作原理。
- 2. 學(xué)會(huì)編寫模塊程序
- 3. 學(xué)會(huì)編寫測試的模塊程序。
- 2. 學(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ì)的正確性。
- 2. 編寫測試程序;
[實(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_a與add_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_a與add_b end endmodule |
_img_4.jpg)
- 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; //間隔2ns,data_ena改變 always #1 in=in+1; //間隔1ns,in的值在原來的基礎(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: //rd與load_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_PC從0變?yōu)?/span>1,故PC增1,ROM送來低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: //PC增1,指向下一條指令 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,XORR或LDA,讀相應(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 // PC增1,否則保持原值 {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,XORR或LDA,讀相應(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)); //將machinectl與machine連接起來 //machinectl.v與machine.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 zero,inc_pc, load_acc, load_pc,load_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 |