開放電腦計畫 -- 計算機硬體結構
|
|
|
- 野裕 宦
- 9 years ago
- Views:
Transcription
1
2 開 放 電 腦 計 畫 -- 計 算 機 硬 體 結 構 2014 年 7 月 出 版 作 者 : 陳 鍾 誠 ( 創 作 共 用 : 姓 名 標 示 相 同 方 式 分 享 授 權 )
3 開 放 電 腦 計 畫 -- 計 算 機 硬 體 結 構 前 言 序 授 權 聲 明 開 放 電 腦 計 畫 簡 介 硬 體 : 計 算 機 結 構 軟 體 : 系 統 程 式 結 語 參 考 文 獻 電 腦 硬 體 架 構 電 腦 的 結 構 CPU0 處 理 器 CPU0 的 指 令 集 CPU0 指 令 格 式 狀 態 暫 存 器 位 元 組 順 序 中 斷 程 序 CPU0 的 組 合 語 言 與 機 器 碼 參 考 文 獻 硬 體 描 述 語 言 -- Verilog Verilog 基 礎 區 塊 式 設 計 流 程 式 設 計 結 語 參 考 文 獻 組 合 邏 輯 (Combinatorial Logic) 簡 介 加 法 器 32 位 元 加 法 器 前 瞻 進 位 加 法 器 (Carry Lookahead Adder) 結 語 參 考 文 獻 算 術 邏 輯 單 元 ALU 的 設 計 加 減 器 採 用 CASE 語 法 設 計 ALU 模 組 完 整 的 ALU 設 計 ( 含 測 試 程 式 ) 結 語 參 考 文 獻 記 憶 單 元 (Memory Unit) 時 序 邏 輯 (Sequential Logic)
4 正 反 器 ( 閂 鎖 器 ) SR 正 反 器 有 enable 的 正 反 器 閘 級 延 遲 (Gate Delay) 利 用 閘 級 延 遲 製 作 脈 波 變 化 偵 測 器 (Pulse Transition Detector, PTD) 使 用 脈 衝 偵 測 電 路 製 作 邊 緣 觸 發 正 反 器 使 用 脈 衝 偵 測 電 路 設 計 邊 緣 觸 發 暫 存 器 使 用 脈 衝 偵 測 電 路 製 作 計 數 電 路 暫 存 器 單 元 記 憶 體 結 語 控 制 單 元 簡 介 流 程 式 設 計 區 塊 式 設 計 微 處 理 器 (Micro Processor) MCU0 的 迷 你 版 -- mcu0m MCU0 的 區 塊 式 設 計 -- MCU0bm.v MCU0 完 整 版 輸 出 入 單 元 (I/O) 前 言 BUS ( 總 線, 匯 流 排 ) 同 步 匯 流 排 (Synchronous BUS) 異 步 匯 流 排 (Asynchronous BUS) 匯 流 排 仲 裁 (BUS arbitery) 循 序 與 平 行 輸 出 入 (Serial vs. Parallel) 常 見 的 輸 出 入 協 定 MCU0 的 輸 出 入 -- 輪 詢 篇 記 憶 系 統 (Storage) 記 憶 體 階 層 (Memory Hierarchy) 快 取 記 憶 體 (Cache) 高 階 處 理 器 (Processor) 哈 佛 架 構 (Harvard Architecture) 流 水 線 架 構 (Pipeline) CPU0 迷 你 版 - CPU0m CPU0 完 整 版 -- cpu0s 速 度 議 題 乘 法 與 除 法 浮 點 數 運 算 繪 圖 加 速 功 能 (Graphics) 平 行 處 理 (Parallel) 結 語
5 附 錄 本 書 內 容 與 相 關 資 源
6 前 言 序 本 書 是 開 放 電 腦 計 畫 的 硬 體 部 份, 描 述 如 何 設 計 電 腦 硬 體 的 方 法, 透 過 這 本 書, 我 們 希 望 讓 計 算 機 結 構 這 門 課 程, 變 成 是 可 以 動 手 實 作 的 我 們 相 信, 透 過 實 作 的 訓 練, 您 將 對 理 論 會 有 更 深 刻 的 體 會, 而 這 些 體 會, 將 會 進 一 步 讓 您 更 瞭 解 現 代 電 腦 工 業 的 結 構 是 如 何 建 構 出 來 的 授 權 聲 明 本 書 許 多 資 料 修 改 自 維 基 百 科, 採 用 創 作 共 用 : 姓 名 標 示 相 同 方 式 分 享 授 權, 若 您 想 要 修 改 本 書 產 生 衍 生 著 作 時, 至 少 應 該 遵 守 下 列 授 權 條 件 : 1. 標 示 原 作 者 姓 名 ( 包 含 該 文 章 作 者, 若 有 來 自 維 基 百 科 的 部 份 也 請 一 併 標 示 ) 2. 採 用 創 作 共 用 : 姓 名 標 示 相 同 方 式 分 享 的 方 式 公 開 衍 生 著 作 另 外 當 本 書 中 有 文 章 或 素 材 並 非 採 用 姓 名 標 示 相 同 方 式 分 享 時, 將 會 在 該 文 章 或 素 材 後 面 標 示 其 授 權, 此 時 該 文 章 將 以 該 標 示 的 方 式 授 權 釋 出, 請 修 改 者 注 意 這 些 授 權 標 示, 以 避 免 產 生 侵 權 糾 紛 例 如 有 些 文 章 可 能 不 希 望 被 作 為 商 業 性 使 用, 此 時 就 可 能 會 採 用 創 作 共 用 : 姓 名 標 示 非 商 業 性 相 同 方 式 分 享 的 授 權, 此 時 您 就 不 應 當 將 該 文 章 用 於 商 業 用 途 上 最 後 若 讀 者 有 需 要 轉 貼 或 修 改 這 些 文 章 使 用, 請 遵 守 創 作 共 用 的 精 神, 讓 大 家 都 可 以 在 開 放 原 始 碼 的 基 礎 上 逐 步 改 進 這 些 作 品
7 開 放 電 腦 計 畫 簡 介 如 果 您 是 資 工 系 畢 業 的 學 生, 必 然 會 上 過 計 算 機 結 構 編 譯 器 作 業 系 統 系 統 程 式 等 等 課 程, 這 些 課 程 都 是 設 計 出 一 台 電 腦 所 必 需 的 基 本 課 程 但 是 如 果 有 人 問 您 您 是 否 會 設 計 電 腦 呢?, 相 信 大 部 分 人 的 回 答 應 該 是 : 我 不 會, 也 沒 有 設 計 過 光 是 設 計 一 個 作 業 系 統, 就 得 花 上 十 年 的 工 夫, 遑 論 還 要 自 己 設 計 CPU 匯 流 排 組 譯 器 編 譯 器 作 業 系 統 等 等 因 此, 我 們 都 曾 經 有 過 這 樣 的 夢 想, 然 後 在 年 紀 越 大, 越 來 越 瞭 解 整 個 工 業 結 構 之 後, 我 們 就 放 棄 了 這 樣 一 個 夢 想, 因 為 我 們 必 須 與 現 實 妥 協 但 是, 身 為 一 個 大 學 教 師, 我 有 責 任 教 導 學 生, 告 訴 他 們 電 腦 是 怎 麼 做 出 來 的, 因 此 我 不 自 量 力 的 提 出 了 這 樣 一 個 計 畫, 那 就 是 開 放 電 腦 計 畫, 我 們 將 以 千 里 之 行 始 於 足 下 的 精 神, 設 計 出 一 台 全 世 界 最 簡 單 且 清 楚 的 電 腦, 包 含 軟 體 與 硬 體 從 2007 年 我 開 始 寫 系 統 程 式 這 本 書 以 來, 就 有 一 個 想 法 逐 漸 在 內 心 發 酵, 這 個 想 法 就 是 : 我 想 從 CPU 設 計 組 譯 器 虛 擬 機 編 譯 器 到 作 業 系 統, 自 己 打 造 一 台 電 腦, 於 是 開 放 電 腦 計 畫 就 誕 生 了! 那 麼 開 放 電 腦 計 畫 的 產 品 會 是 什 麼 呢? 應 該 有 些 人 會 認 為 是 一 套 自 行 編 寫 的 軟 硬 體 程 式, 當 然 這 部 份 是 包 含 在 開 放 電 腦 計 畫 當 中 的 但 是 更 重 要 的 事 情 是, 我 們 希 望 透 過 開 放 電 腦 計 畫 讓 學 生 能 夠 學 會 整 個 電 腦 的 軟 硬 體 設 計 方 式, 並 且 透 過 這 個 踏 腳 石 瞭 解 整 個 電 腦 軟 硬 體 工 業, 進 而 能 夠 達 到 以 理 論 指 導 實 務 以 實 務 驗 證 理 論 的 目 標 為 了 達 成 這 個 目 標, 我 們 將 開 放 電 腦 計 畫 分 成 三 個 階 段, 也 就 是 簡 單 設 計 ( 程 式 ) => 理 論 闡 述 ( 書 籍 ) => 開 源 實 作 ( 工 業 軟 硬 體 與 流 程 ), 整 體 的 構 想 說 明 如 下 : 1. 簡 單 設 計 ( 程 式 ): 採 用 Verilog + C 設 計 CPU 組 譯 器 編 譯 器 作 業 系 統 等 軟 硬 體, 遵 循 KISS (Keep It Simple and Stupid) 原 則, 不 考 慮 效 能 與 商 業 競 爭 力 等 問 題, 甚 至 在 實 用 性 上 進 行 了 不 少 妥 協, 一 律 採 用 容 易 理 解 為 最 高 指 導 原 則, 目 的 是 清 楚 的 展 現 整 個 軟 硬 體 系 統 的 架 構 2. 理 論 闡 述 ( 書 籍 ): 但 是 要 瞭 解 像 處 理 器 系 統 軟 體 編 譯 器 作 業 系 統 這 些 領 域, 只 有 程 式 是 不 夠 的 因 為 程 式 通 常 不 容 易 懂, 而 且 對 於 沒 有 背 景 知 識 的 人 而 言, 往 往 難 如 天 書 所 以 我 們 將 撰 寫 一 系 列 書 籍, 用 來 說 明 上 述 簡 單 程 式 的 設 計 原 理, 然 後 開 始 進 入 計 算 機 結 構 編 譯 器 作 業 系 統 系 統 程 式 的 理 論 體 系 中, 導 引 出 進 一 步 的 設 計 可 能 性 與 工 業 考 量 等 議 題 3. 開 源 實 作 ( 工 業 ): 一 但 有 了 前 述 的 理 論 與 實 作 基 礎 之 後, 我 們 就 會 採 用 開 放 原 始 碼 來 進 行 案 例 研 究 舉 例 而 言 在 計 算 機 結 構 上 我 們 會 以 ARM 為 實 務 核 心 編 譯 器 領 域 則 以 gcc, LLVM 為 研 究 標 的, 作 業 系 統 上 則 會 對 FreeRTOS Linux 等 進 行 案 例 研 究, 虛 擬 機 上 則 會 以 QEMU V8 等 開 源 案 例 為 研 究 對 象
8 圖 開 放 電 腦 計 畫 地 圖 根 據 以 上 規 劃, 本 書 乃 為 一 系 列 書 籍 中 的 一 本, 完 整 的 書 籍 架 構 如 下 : 開 放 電 腦 計 畫 書 籍 簡 易 程 式 工 業 實 作 系 統 程 式 as0, vm0, cc0, os0 gcc/llvm 計 算 機 結 構 mcu0, cpu0 ARM/OpenRISC 編 譯 器 c 0c, j0c g cc/llvm 作 業 系 統 os0, XINU, MINIX FreeRTOS, Linux 這 些 書 籍 分 別 描 述 不 同 的 面 向, 其 涵 蓋 範 圍 如 下 圖 所 示 :
9 圖 開 放 電 腦 計 畫 書 籍 圖 硬 體 : 計 算 機 結 構 在 硬 體 方 面, 我 們 將 自 行 設 計 兩 款 處 理 器, 一 款 是 用 來 展 示 簡 單 微 處 理 器 設 計 原 理 的 16 位 元 微 控 制 器 MCU0, 而 另 一 款 則 是 用 來 展 示 高 階 處 理 器 設 計 原 理 的 32 位 元 處 理 器 CPU0 透 過 MCU0, 我 們 希 望 展 示 一 顆 最 簡 易 微 處 理 器 的 設 計 方 法, 我 們 將 採 用 流 程 式 與 區 塊 式 的 方 法 分 別 實 作 一 遍, 讓 讀 者 可 以 分 別 從 硬 體 人 與 軟 體 人 的 角 度 去 體 會 處 理 器 的 設 計 方 式 由 於 流 程 式 的 方 法 比 較 簡 單, 因 此 我 們 會 先 用 此 法 進 行 設 計, 當 讀 者 理 解 何 謂 微 處 理 器 之 後, 在 將 同 樣 的 功 能 改 用 區 塊 式 的 方 法 實 作 一 遍, 這 樣 應 該 就 能 逐 漸 由 易 至 難 由 淺 入 深 了 在 MCU0 當 中, 我 們 採 用 CPU 與 記 憶 體 合 一 的 設 計 方 式, 這 種 方 式 比 較 像 系 統 單 晶 片 (SOC) 的 設 計 方 法, 其 記 憶 體 容 量 較 小, 因 此 可 以 直 接 用 Verilog 陣 列 宣 告 放 入 FPGA 當 中 使 用, 不 需 考 慮 外 部 DRAM 存 取 速 度 較 慢 的 問 題, 也 不 用 考 慮 記 憶 階 層 的 速 度 問 題, 因 此 設 計 起 來 會 相 對 容 易 許 多 接 著, 我 們 將 再 度 設 計 一 個 32 位 元 的 處 理 器 -- CPU0 並 透 過 CPU0 來 討 論 當 CPU 速 度 比 DRAM 記 憶 體 快 上 許 多 的 時 候, 如 何 能 透 過 快 取 (cache) 與 記 憶 體 管 理 單 元 (MMU) 達 到 又 快 又 大 的 目 的, 並 且 討 論 如 何 透 過 流 水 線 架 構 (Pipeline) 達 到 加 速 的 目 的, 這 些 都 屬 於 高 階 處 理 器 所 需 要 討 論 的 問 題 軟 體 : 系 統 程 式
10 有 了 MCU0 與 CPU0 等 硬 體 之 後, 我 們 就 可 以 建 構 運 作 於 這 些 硬 體 之 上 的 軟 體 了, 這 些 軟 體 包 含 組 譯 器 虛 擬 機 編 譯 器 作 業 系 統 等 等 我 們 已 經 分 別 用 C 與 JavaSript 建 構 出 簡 易 的 組 譯 器 虛 擬 機 編 譯 器 工 具 了, 讓 我 們 先 說 明 一 下 在 CPU0 上 這 些 程 式 的 使 用 方 法, 以 下 示 範 是 採 用 node.js+javascript 實 作 的 工 具 版 本, 因 此 必 須 安 裝 node.js 才 能 執 行 組 合 語 言 (Assembly Language) 接 著 讓 我 們 從 組 合 語 言 的 角 度, 來 看 看 CPU0 處 理 器 的 設 計, 以 下 是 一 個 可 以 計 算 的 程 式, 計 算 完 成 之 後 會 透 過 呼 叫 軟 體 中 斷 SWI 程 序 ( 類 似 DOS 時 代 的 INT 中 斷 ), 在 螢 幕 上 印 出 下 列 訊 息 =55 以 下 的 檔 案 sum.as0 正 是 完 成 這 樣 功 能 的 一 個 CPU0 組 合 語 言 程 式 檔 案 :sum.as0 LD R1, sum ; R1 = sum = 0 LD R2, i ; R2 = i = 1 LDI R3, 10 ; R3 = 10 FOR: CMP R2, R3 ; if (R2 > R3) JGT EXIT ; goto EXIT ADD R1, R1, R2 ; R1 = R1 + R2 (sum = sum + i) ADDI R2, R2, 1 ; R2 = R2 + 1 ( i = i + 1) JMP FOR ; goto FOR EXIT: ST R1, sum ; sum = R1 ST R2, i ; i = R2 LD R9, msgptr ; R9= pointer(msg) = &msg SWI 3 ; SWI 3 : 印 出 R9 (=&msg) 中 的 字 串 MOV R9, R1 ; R9 = R1 = sum SWI 4 ; SWI 4 : 印 出 R9 (=R1=sum) 中 的 整 數 RET ; return 返 回 上 一 層 呼 叫 函 數 i: RESW 1 ; int i sum: WORD 0 ; int sum=0 msg: BYTE " =", 0 ; char *msg = "sum=" msgptr: WORD msg ; char &msgptr = &msg 組 譯 器 (Assembler) 我 們 可 以 用 以 下 指 令 呼 叫 組 譯 器 AS0 對 上 述 檔 案 進 行 組 譯 :
11 node as0 sum.as0 sum.ob0 上 述 的 程 式 經 過 組 譯 之 後, 會 輸 出 組 譯 報 表, 如 下 所 示 sum.as0 的 組 譯 報 表 0000 LD R1,sum L F003C 0004 LD R2,i L F LDI R3,10 L A 000C FOR CMP R2,R3 A JGT EXIT J C 0014 ADD R1,R1,R2 A ADDI R2,R2,1 A 1B 1B C JMP FOR J 26 26FFFFEC 0020 EXIT ST R1,sum L F001C 0024 ST R2,i L F LD R9,msgptr L F C SWI 3 J 2A 2A MOV R9,R1 A SWI 2 J 2A 2A RET J 2C 2C C i RESW 1 D F sum WORD 0 D F msg BYTE " =",0 D F3 312B2E2E2E2B31303D00 004E msgptr WORD msg D F 最 後 組 譯 器 AS0 會 輸 出 機 器 碼 到 目 的 檔 sum.ob0 當 中, 其 內 容 如 下 所 示 sum.as0 的 機 器 碼 ( 以 16 進 位 顯 示 ) 001F003C 002F A C B FFFFEC 011F001C 012F F0022 2A A C B2E2E 2E2B3130 3D 虛 擬 機 (Virtual Machine) 如 果 我 們 用 虛 擬 機 VM0 去 執 行 上 述 的 目 的 檔 sum.ob0, 會 看 到 程 式 的 執 行 結 果, 是 在 螢 幕 上 列 印 出 =55, 以 下 是 我 們 的 操 作 過 程
12 =55 編 譯 器 (Compiler) 當 然 一 個 完 整 的 現 代 電 腦 應 該 包 含 比 組 譯 器 更 高 階 的 工 具, 不 只 支 援 組 合 語 言, 還 要 支 援 高 階 語 言 因 此 我 們 設 計 了 一 個 稱 為 J0 的 高 階 語 言, 語 法 有 點 像 JavaScript, 但 卻 是 經 過 簡 化 的 版 本 然 後 我 們 又 設 計 了 一 個 可 以 用 來 編 譯 J0 語 言 的 編 譯 器, 稱 為 J0C (J0 Compiler), 可 以 用 來 將 J0 語 言 編 譯 成 中 間 碼, 也 可 以 直 接 將 中 間 碼 轉 換 為 CPU0 的 組 合 語 言 以 下 是 一 個 J0 語 言 的 範 例, 檔 案 :sum.j0 s = sum(10); return s; function sum(n) { s = 0; i=1; while (i<=10) { s = s + i; i++; } return s; } 當 我 們 使 用 j0c 編 譯 器 將 上 述 程 式 編 譯 之 後, 會 輸 出 兩 個 檔 案, 一 個 是 sum.ir, 是 編 譯 器 中 間 格 式 (Intermediate Representation, 虛 擬 碼 pcode) 的 輸 出 檔, 其 內 容 如 下 : D:\Dropbox\Public\web\oc\code>node j0c sum arg 10 call T1 sum = s T1 return s sum function param n = s 0 = i 1 L1 <= T2 i 10
13 L2 if0 T2 L2 + T3 s i = s T3 ++ i goto L1 return s f 另 一 個 是 將 上 述 中 間 格 式 轉 換 成 轉 換 成 CPU0 組 合 語 言 之 後 的 結 果, 如 下 所 示 : sum L1 else1 POP n LDI R1 0 ST R1 s LDI R1 1 ST R1 i LD R1 i LDI R2 10 LDI R3 0 CMP R1 R2 JLE else1 LDI R3 1 ST R3 T1 LDI R1 T1 CMP R1 0 JEQ L2 LD R1 s LD R2 i ADD R3 R1 R2 ST R3 T2 LDI R1 T2 ST R1 s LD R1 i ADDI R1 R1 1 ST R1 i
14 L2 JMP L1 LD R1 s RET LDI R1 10 PUSH R1 CALL sum ST R1 T3 LDI R1 T3 ST R1 s s WORD 0 i WORD 0 T1 WORD 0 T2 WORD 0 T3 WORD 0 上 述 由 j0c 所 編 譯 產 生 的 組 合 語 言, 感 覺 相 對 冗 長, 是 因 為 這 個 編 譯 器 是 最 簡 版 本, 完 全 沒 有 做 任 何 優 化 動 作, 甚 至 連 暫 存 器 都 是 每 次 重 新 載 入 的, 所 以 效 率 並 不 會 很 好 作 業 系 統 (Operating System) 當 然 囉! 一 個 完 整 的 電 腦 還 必 須 要 有 作 業 系 統, 不 過 如 果 是 嵌 入 式 系 統 的 話, 沒 有 作 業 系 統 也 沒 關 係, 只 要 將 全 部 的 程 式 連 結 在 一 起, 就 可 以 形 成 一 台 電 腦 了, 目 前 開 放 電 腦 計 畫 的 作 業 系 統 還 在 研 究 開 發 當 中, 希 望 很 快 就 能 提 供 大 家 一 個 最 簡 單 的 作 業 系 統 版 本 目 前 我 們 已 經 寫 了 一 個 可 以 進 行 兩 個 行 程 切 換 Task Switching 範 例, 接 著 我 們 將 參 考 UNIXv6, L4 等 作 業 系 統, 以 建 構 更 完 整 的 簡 易 作 業 系 統 結 語 當 然 即 使 我 們 從 CPU 硬 體 一 路 設 計 到 組 譯 器 虛 擬 機 編 譯 器 作 業 系 統 等, 未 來 仍 然 有 更 多 領 域 等 待 我 們 去 探 索, 例 如 網 路 模 組 TCP/IP Ethernet 無 線 RF 的 硬 體 模 組 繪 圖 卡 OpenGL... 等 等, 希 望 我 們 能 夠 用 最 簡 單 的 話 語, 將 這 些 電 腦 的 原 理 說 明 清 楚, 並 用 簡 單 的 方 式 實 作 得 更 完 整 參 考 文 獻 陳 鍾 誠 的 網 站 / 免 費 電 子 書 :Verilog 電 路 設 計 系 統 程 式 陳 鍾 誠 著, 旗 標 出 版 社. JavaScript (6) Node.js 命 令 列 程 式 設 計
15 電 腦 硬 體 架 構 電 腦 的 結 構 傳 統 的 電 腦 架 構, 最 經 典 的 模 型 是 由 數 學 大 師 馮 紐 曼 (Von Neumann) 所 描 述 的, 因 此 稱 為 馮 紐 曼 架 構, 如 以 下 兩 個 圖 片 所 示 : 圖 馮 紐 曼 架 構 (1) 圖 片 來 源 : 圖 馮 紐 曼 架 構 (2) 圖 片 來 源 : 在 早 期 晶 片 線 路 成 本 還 算 高 的 時 候, 最 常 見 的 馮 紐 曼 架 構 電 腦, 是 採 用 單 匯 流 排 的 架 構, 如 下 圖 所 示 :
16 圖 單 一 匯 流 排 的 馮 紐 曼 架 構 圖 片 來 源 : 但 是 自 從 RISC 精 簡 指 令 集 電 腦 出 現, 由 於 pipeline 必 須 讓 指 令 與 資 料 可 以 同 時 被 存 取, 很 多 電 腦 改 採 以 下 指 令 與 資 料 分 開 的 哈 佛 架 構 (Harvard Architecture): 圖 指 令 與 資 料 匯 流 排 分 開 的 哈 佛 架 構 圖 片 來 源 : 必 須 注 意 的 是, 雖 然 哈 佛 架 構 當 中 的 指 令 與 資 料 是 完 全 分 開 的, 但 是 如 果 真 的 將 指 令 與 資 料 個 記 憶 體 整 個 分 開 的 話, 會 需 要 兩 套 記 憶 體 與 匯 流 排, 這 會 讓 CPU 的 接 腳 數 大 增, 也 會 讓 記 憶 體 運 用 沒 效 率, 因 此 在 實 務 上, 通 常 是 將 快 取 記 憶 體 分 成 兩 邊, 一 邊 是 指 令 快 取, 一 邊 是 資 料 快 取, 這 樣 就 只 有 內 部 匯 流 排 需 要 分 開 成 兩 套, 而 CPU 對 外 則 只 要 一 套 匯 流 排 與 記 憶 體, 這 種 架 構 可 以 看 成 哈 佛 架 構 的 一 種 變 形 CPU0 處 理 器 CPU0 是 一 個 簡 易 的 32 位 元 單 匯 流 排 處 理 器, 其 架 構 如 下 圖 所 示, 包 含 R0..R15, IR, MAR, MDR 等 暫 存 器, 其 中 IR 是 指 令 暫 存 器, R0 是 一 個 永 遠 為 常 數 0 的 唯 讀 暫 存 器,R15 是 程 式 計 數 器 (Program Counter : PC),R14 是 連 結 暫 存 器 (Link Register : LR), R13 是 堆 疊 指 標 暫 存 器 (Stack Pointer : SP), 而 R12 是 狀 態 暫 存
17 器 (Status Word : SW) 圖 CPU0 的 架 構 圖 CPU0 的 指 令 集 CPU0 包 含 載 入 儲 存 運 算 指 令 跳 躍 指 令 堆 疊 指 令 等 四 大 類 指 令, 以 下 表 格 是 CPU0 的 指 令 編 碼 表, 記 載 了 CPU0 的 指 令 集 與 每 個 指 令 的 編 碼 格 式 指 令 OP 說 明 語 法 語 意 L LD 00 載 入 word LD Ra, [Rb+Cx] Ra=[Rb+Cx] L ST 01 儲 存 word ST Ra, [Rb+Cx] Ra=[Rb+Cx] L LDB 02 載 入 byte LDB Ra, [Rb+Cx] Ra=(byte)[Rb+Cx] L STB 03 儲 存 byte STB Ra, [Rb+Cx] Ra=(byte)[Rb+Cx] A LDR 04 LD 的 暫 存 器 版 LDR Ra, [Rb+Rc] Ra=[Rb+Rc] A STR 05 ST 的 暫 存 器 版 STR Ra, [Rb+Rc] Ra=[Rb+Rc] A LBR 06 LDB 的 暫 存 器 版 LBR Ra, [Rb+Rc] Ra=(byte)[Rb+Rc] A SBR 07 STB 的 暫 存 器 版 SBR Ra, [Rb+Rc] Ra=(byte)[Rb+Rc] L LDI 08 載 入 常 數 LDI Ra, Cx Ra=Cx A CMP 10 比 較 CMP Ra, Rb SW=Ra >=< Rb A MOV 12 移 動 MOV Ra, Rb Ra=Rb
18 A ADD 13 加 法 ADD Ra, Rb, Rc Ra=Rb+Rc A SUB 14 減 法 SUB Ra, Rb, Rc Ra=Rb-Rc A MUL 15 乘 法 MUL Ra, Rb, Rc Ra=Rb*Rc A DIV 16 除 法 DIV Ra, Rb, Rc Ra=Rb/Rc A AND 18 邏 輯 AND AND Ra, Rb, Rc Ra=Rb and Rc A OR 19 邏 輯 OR OR Ra, Rb, Rc Ra=Rb or Rc A XOR 1A 邏 輯 XOR XOR Ra, Rb, Rc Ra=Rb xor Rc A ADDI 1B 常 數 加 法 ADDI Ra, Rb, Cx Ra=Rb + Cx A ROL 1C 向 左 旋 轉 ROL Ra, Rb, Cx Ra=Rb rol Cx A ROR 1D 向 右 旋 轉 ROR Ra, Rb, Cx Ra=Rb ror Cx A SHL 1E 向 左 移 位 SHL Ra, Rb, Cx Ra=Rb << Cx A SHR 1F 向 右 移 位 SHR Ra, Rb, Cx Ra=Rb >> Cx J JEQ 20 跳 躍 ( 相 等 ) JEQ Cx if SW(=) PC=PC+Cx J JNE 21 跳 躍 ( 不 相 等 ) JNE Cx if SW(!=) PC=PC+Cx J JLT 22 跳 躍 (<) JLT Cx if SW(<) PC=PC+Cx J JGT 23 跳 躍 (>) JGT Cx if SW(>) PC=PC+Cx J JLE 24 跳 躍 (<=) JLE Cx if SW(<=) PC=PC+Cx J JGE 25 跳 躍 (>=) JGE Cx if SW(>=) PC=PC+Cx J JMP 26 跳 躍 ( 無 條 件 ) JMP Cx PC=PC+Cx J SWI 2A 軟 體 中 斷 SWI Cx LR=PC; PC=Cx; INT=1 J CALL 2B 跳 到 副 程 式 CALL Cx LR=PC; PC=PC+Cx J RET 2C 返 回 RET PC=LR J IRET 2D 中 斷 返 回 IRET PC=LR; INT=0 A PUSH 30 推 入 word PUSH Ra SP-=4; [SP]=Ra; A POP 31 彈 出 word POP Ra Ra=[SP]; SP+=4; A PUSHB 32 推 入 byte PUSHB Ra SP--; [SP]=Ra; (byte)
19 A POPB 33 彈 出 byte POPB Ra Ra=[SP]; SP++; (byte) CPU0 指 令 格 式 CPU0 所 有 指 令 長 度 均 為 32 位 元, 這 些 指 令 也 可 根 據 編 碼 方 式 分 成 三 種 不 同 的 格 式, 分 別 是 A 型 J 型 與 L 型 大 部 分 的 運 算 指 令 屬 於 A (Arithmatic) 型, 而 載 入 儲 存 指 令 通 常 屬 於 L (Load & Store) 型, 跳 躍 指 令 則 通 常 屬 於 J (Jump) 型, 這 三 種 型 態 的 指 令 格 式 如 下 圖 所 示 圖 CPU0 的 指 令 格 式 狀 態 暫 存 器 R12 狀 態 暫 存 器 (Status Word : SW) 是 用 來 儲 存 CPU 的 狀 態 值, 這 些 狀 態 是 許 多 旗 標 的 組 合 例 如, 零 旗 標 (Zero, 簡 寫 為 Z) 代 表 比 較 的 結 果 為 0, 負 旗 標 (Negative, 簡 寫 為 N) 代 表 比 較 的 結 果 為 負 值, 另 外 常 見 的 旗 標 還 有 進 位 旗 標 (Carry, 簡 寫 為 C), 溢 位 旗 標 (Overflow, 簡 寫 為 V) 等 等 下 圖 顯 示 了 CPU0 的 狀 態 暫 存 器 格 式, 最 前 面 的 四 個 位 元 N Z C V 所 代 表 的, 正 是 上 述 的 幾 個 旗 標 值 圖 CPU0 中 狀 態 暫 存 器 SW 的 結 構 條 件 旗 標 的 N Z 旗 標 值 可 以 用 來 代 表 比 較 結 果 是 大 於 (>) 等 於 (=) 還 是 小 於 (<), 當 執 行 CMP Ra, Rb 動 作 後, 會 有 下 列 三 種 可 能 的 情 形 1. 若 Ra > Rb, 則 N=0, Z=0 2. 若 Ra < Rb, 則 N=1, Z=0 3. 若 Ra = Rb, 則 N=0, Z=1 如 此, 用 來 進 行 條 件 跳 躍 的 JGT JGE JLT JLE JEQ JNE 指 令, 就 可 以 根 據 SW 暫 存 器 當 中 的 N Z 等 旗 標 決 定 是 否 進 行 跳 躍 SW 中 還 包 含 中 斷 控 制 旗 標 I (Interrupt) 與 T (Trap), 用 以 控 制 中 斷 的 啟 動 與 禁 止 等 行 為, 假 如 將 I 旗 標 設 定
20 為 0, 則 CPU0 將 禁 止 所 有 種 類 的 中 斷, 也 就 是 對 任 何 中 斷 都 不 會 起 反 應 但 如 果 只 是 將 T 旗 標 設 定 為 0, 則 只 會 禁 止 軟 體 中 斷 指 令 SWI (Software Interrupt), 不 會 禁 止 由 硬 體 觸 發 的 中 斷 SW 中 還 儲 存 有 處 理 器 模 式 的 欄 位,M=0 時 為 使 用 者 模 式 (user mode) 與 M=1 時 為 特 權 模 式 (super mode) 等, 這 在 作 業 系 統 的 設 計 上 經 常 被 用 來 製 作 安 全 保 護 功 能 在 使 用 者 模 式 當 中, 任 何 設 定 狀 態 暫 存 器 R12 的 動 作 都 會 被 視 為 是 非 法 的, 這 是 為 了 進 行 保 護 功 能 的 緣 故 但 是 在 特 權 模 式 中, 允 許 進 行 任 何 動 作, 包 含 設 定 中 斷 旗 標 與 處 理 器 模 式 等 位 元, 通 常 作 業 系 統 會 使 用 特 權 模 式 (M=1), 而 一 般 程 式 只 能 處 於 使 用 者 模 式 (M=0) 位 元 組 順 序 CPU0 採 用 大 者 優 先 (Big Endian) 的 位 元 組 順 序 (Byte Ordering), 因 此 代 表 值 越 大 的 位 元 組 會 在 記 憶 體 的 前 面 ( 低 位 址 處 ), 代 表 值 小 者 會 在 高 位 址 處 由 於 CPU0 是 32 位 元 的 電 腦, 因 此, 一 個 字 組 (Word) 占 用 4 個 位 元 組 (Byte), 因 此, 像 LD R1, [100] 這 樣 的 指 令, 其 實 是 將 記 憶 體 中 的 字 組 取 出, 存 入 到 暫 存 器 R1 當 中 LDB 與 STB 等 指 令, 其 中 的 B 是 指 Byte, 因 此,LDB R1, [100] 會 將 記 憶 體 100 中 的 byte 取 出, 載 入 到 R1 當 中 但 是, 由 於 R1 的 大 小 是 32 bits, 相 當 於 4 個 byte, 此 時,LDB 與 STB 指 令 到 底 是 存 取 四 個 byte 當 中 的 哪 一 個 byte 呢? 這 個 問 題 的 答 案 是 byte 3, 也 就 是 最 後 的 一 個 byte 中 斷 程 序 CPU0 的 中 斷 為 不 可 重 入 式 中 斷, 其 中 斷 分 為 軟 體 中 斷 SWI (Trap) 與 硬 體 中 斷 HWI (Interrupt) 兩 類 硬 體 中 斷 發 生 時, 中 段 代 號 INT_ADDR 會 從 中 段 線 路 傳 入, 此 時 執 行 下 列 動 作 : 1. LR=PC; INT=1 2. PC=INT_ADDR 軟 體 中 斷 SWI Cx 發 生 時, 會 執 行 下 列 動 作 : 1. LR=PC; INT=1 2. PC=Cx; 中 斷 最 後 可 以 使 用 IRET 返 回, 返 回 前 會 設 定 允 許 中 斷 狀 態 1. PC=LR; INT=0 CPU0 的 組 合 語 言 與 機 器 碼 接 著 讓 我 們 從 組 合 語 言 的 角 度, 來 看 看 CPU0 處 理 器 的 設 計, 以 下 是 一 個 可 以 計 算 的 程 式, 計 算 完 成 之 後 會 透 過 呼 叫 軟 體 中 斷 SWI 程 序 ( 類 似 DOS 時 代 的 INT 中 斷 ), 在 螢 幕 上 印 出 下 列 訊 息 =55 以 下 的 檔 案 sum.as0 正 是 完 成 這 樣 功 能 的 一 個 CPU0 組 合 語 言 程 式
21 檔 案 :sum.as0 LD R1, sum ; R1 = sum = 0 LD R2, i ; R2 = i = 1 LDI R3, 10 ; R3 = 10 FOR: CMP R2, R3 ; if (R2 > R3) JGT EXIT ; goto EXIT ADD R1, R1, R2 ; R1 = R1 + R2 (sum = sum + i) ADDI R2, R2, 1 ; R2 = R2 + 1 ( i = i + 1) JMP FOR ; goto FOR EXIT: ST R1, sum ; sum = R1 ST R2, i ; i = R2 LD R9, msgptr ; R9= pointer(msg) = &msg SWI 3 ; SWI 3 : 印 出 R9 (=&msg) 中 的 字 串 MOV R9, R1 ; R9 = R1 = sum SWI 4 ; SWI 4 : 印 出 R9 (=R1=sum) 中 的 整 數 RET ; return 返 回 上 一 層 呼 叫 函 數 i: RESW 1 ; int i sum: WORD 0 ; int sum=0 msg: BYTE " =", 0 ; char *msg = "sum=" msgptr: WORD msg ; char &msgptr = &msg 我 們 可 以 用 以 下 指 令 呼 叫 組 譯 器 AS0 對 上 述 檔 案 進 行 組 譯 : node as0 sum.as0 sum.ob0 上 述 的 程 式 經 過 組 譯 之 後, 會 輸 出 組 譯 報 表, 如 下 所 示 sum.as0 的 組 譯 報 表 0000 LD R1,sum L F003C 0004 LD R2,i L F LDI R3,10 L A 000C FOR CMP R2,R3 A JGT EXIT J C 0014 ADD R1,R1,R2 A ADDI R2,R2,1 A 1B 1B C JMP FOR J 26 26FFFFEC 0020 EXIT ST R1,sum L F001C 0024 ST R2,i L F0014
22 0028 LD R9,msgptr L F C SWI 3 J 2A 2A MOV R9,R1 A SWI 2 J 2A 2A RET J 2C 2C C i RESW 1 D F sum WORD 0 D F msg BYTE " =",0 D F3 312B2E2E2E2B31303D00 004E msgptr WORD msg D F 最 後 組 譯 器 AS0 會 輸 出 機 器 碼 到 目 的 檔 sum.ob0 當 中, 其 內 容 如 下 所 示 sum.as0 的 機 器 碼 ( 以 16 進 位 顯 示 ) 001F003C 002F A C B FFFFEC 011F001C 012F F0022 2A A C B2E2E 2E2B3130 3D 如 果 我 們 用 虛 擬 機 VM0 去 執 行 上 述 的 目 的 檔 sum.ob0, 會 看 到 程 式 的 執 行 結 果, 是 在 螢 幕 上 列 印 出 =55, 以 下 是 我 們 的 操 作 過 程 =55 參 考 文 獻 系 統 程 式 ( 陳 鍾 誠 著, 旗 標 出 版 社 ) -- JavaScript (6) Node.js 命 令 列 程 式 設 計
23 硬 體 描 述 語 言 -- Verilog Verilog 與 VHDL 都 是 用 來 設 計 數 位 電 路 的 硬 體 描 述 語 言, 但 VHDL 在 1983 年 被 提 出 後,1987 防 部 和 IEEE 確 定 為 標 準 的 硬 體 描 述 語 言 年 被 美 國 國 Verilog 是 由 Gateway Design Automation 公 司 於 1984 年 開 始 發 展 的, Cadence Design Systems 公 司 於 1990 年 購 併 了 Gateway 公 司,Cadence 隨 後 將 Verilog 提 交 到 Open Verilog International 成 為 開 放 公 用 標 準,1995 年 Verilog 被 IEEE 認 可 成 為 IEEE 標 準, 簡 稱 為 Verilog-95 此 一 標 準 於 2001 年 更 新 後 成 為 Verilog 相 較 於 VHDL 而 言,Verilog 的 語 法 較 為 簡 潔, 因 此 經 常 被 專 業 的 數 位 電 路 設 計 者 採 用, 而 VHDL 的 使 用 族 群 則 有 較 多 的 初 學 者 當 我 們 想 學 習 數 位 電 路 設 計 時, 經 常 會 難 以 選 擇 要 用 哪 一 種 語 言, 因 為 VHDL 的 書 籍 與 教 材 似 乎 比 Verilog 多 一 些, 但 是 Verilog 的 高 階 設 計 電 路 ( 像 是 開 放 原 始 碼 CPU 等 ) 則 比 VHDL 多 很 多 筆 者 是 為 了 要 設 計 CPU 而 學 習 數 位 電 路 設 計 的, 因 此 決 定 學 習 Verilog 語 言, 而 非 VHDL 語 言 雖 然 筆 者 也 學 過 VHDL 語 言, 但 後 來 發 現 Verilog 相 當 好, 相 對 而 言 語 法 簡 潔 了 許 多, 因 此 筆 者 比 較 偏 好 Verilog 語 言 在 本 文 中, 我 們 將 介 紹 Verilog 的 基 本 語 法, 並 且 採 用 Icarus 作 為 主 要 開 發 測 試 工 具, 以 便 讓 讀 者 能 很 快 的 進 入 Verilog 硬 體 設 計 的 領 域 Verilog 基 礎 Verilog 的 基 本 型 態 在 一 般 的 程 式 語 言 當 中, 資 料 的 最 基 本 型 態 通 常 是 位 元 (bit), 但 是 在 Verilog 這 種 硬 體 描 述 語 言 當 中, 我 們 必 須 有 面 向 硬 體 的 思 考 方 式, 因 此 最 基 本 的 型 態 從 位 元 轉 換 為 線 路 (wire) 一 條 線 路 的 可 能 值, 除 了 0 與 1 之 外, 還 有 可 能 是 未 定 值 X, 以 及 高 阻 抗 Z, 如 下 表 所 示 : 值 意 義 說 明 0 低 電 位 布 林 代 數 中 的 假 值 1 高 電 位 布 林 代 數 中 的 真 值 Z 高 阻 抗 三 態 緩 衝 器 的 輸 出, 高 阻 抗 斷 線 X 未 定 值 像 是 線 路 未 初 始 化 之 前, 以 及 有 0,1 兩 者 衝 突 的 線 路 值, 或 者 是 輸 入 為 Z 的 輸 出 值 其 中 的 0 對 應 到 低 電 位 1 對 應 到 高 電 位, 這 是 比 較 容 易 理 解 的 部 分, 但 是 未 定 值 X 與 高 阻 抗 Z 各 代 表 甚 麼 意 義 呢? 對 於 一 條 沒 有 阻 抗 的 線 路 而 言, 假 如 我 們 在 某 點 對 該 線 路 輸 出 1, 另 一 點 對 該 線 路 輸 出 0, 那 麼 這 條 線 路 到 底 應 該 是 高 電 位 還 是 低 電 位 呢?
24 圖 造 成 未 定 值 X 的 情 況 對 於 這 種 衝 突 的 情 況,Verilog 採 用 X 來 代 表 該 線 路 的 值 而 高 阻 抗, 則 基 本 上 是 代 表 斷 線, 您 可 以 想 像 該 線 路 如 果 是 非 導 體, 例 如 塑 膠 木 頭 開 關 開 路 或 者 是 處 於 高 阻 抗 情 況 的 半 導 體 等, 就 會 使 用 者 種 Z 值 來 代 表 根 據 這 樣 的 四 種 線 路 狀 態, 一 個 原 本 簡 易 的 AND 閘, 在 數 位 邏 輯 中 只 要 用 2*2 的 真 值 表 就 能 表 示 了, 但 在 Verilog 當 中 則 有 4*4 種 可 能 的 情 況, 以 下 是 Verilog 中 各 種 運 算 (AND, OR, XOR, XNOR) 在 這 四 種 型 態 上 的 真 值 表 定 義 : AND 0 1 X Z (&) X X X 0 X X X Z 0 X X X OR ( ) 0 1 X Z X X X X 1 X X Z X 1 X X XOR(^) 0 1 X Z X X X X X X X X X Z 1 X X X XNOR(^~) 0 1 X Z X X X X X X X X X Z X X X X 在 Verilog 當 中, 如 果 我 們 要 宣 告 一 條 線 路, 只 要 用 下 列 語 法 就 可 以 了 : wire w1; 如 果 我 們 想 一 次 宣 告 很 多 條 線 路, 那 麼 我 們 可 以 用 很 多 個 變 數 描 述 :
25 wire w, x, y, z; 但 是 如 果 我 們 想 宣 告 一 整 個 排 線 ( 例 如 匯 流 排 ), 那 我 們 就 可 以 用 下 列 的 陣 列 語 法 : wire [31:0] bus; 如 果 想 要 一 次 宣 告 很 多 組 排 線, 那 我 們 就 可 以 用 下 列 的 陣 列 群 語 法 : wire [31:0] bus [0:3]; 當 然 除 了 線 路 之 外,Verilog 還 有 可 以 穩 定 儲 存 位 元 的 型 態, 稱 為 reg ( 暫 存 器 ),reg 可 以 用 來 儲 存 位 元, 而 非 像 線 路 一 樣 只 是 一 種 連 接 方 式 而 已, 以 下 是 一 些 reg 的 宣 告 方 式 : reg w; reg x, y, z; reg [31:0] r1; reg [31:0] R [0:15]; // 宣 告 一 位 元 的 暫 存 器 變 數 w // 宣 告 三 個 一 位 元 的 暫 存 器 變 數 x, y, z // 宣 告 32 位 元 的 暫 存 器 r1 // 宣 告 16 個 32 位 元 的 暫 存 器 群 組 R[0..15] 在 Verilog 中,wire 與 reg 是 比 較 常 用 的 基 本 型 態, 另 外 還 有 一 些 較 不 常 用 的 基 本 型 態, 像 是 tri ( 三 態 線 路 ) trireg ( 三 態 暫 存 器 ) integer ( 整 數 ) 等, 在 此 我 們 先 不 進 行 介 紹 Icarus : Verilog 的 編 譯 執 行 工 具 Icarus 是 由 Stephen Williams 所 設 計 的 Verilog 開 發 工 具, 採 用 GPL 授 權 協 議, 並 且 可 以 在 Linux, BSD, OS X, MS Windows 等 環 境 下 執 行 Icarus 支 援 Verilog 的 IEEE 1995 IEEE 2001 和 IEEE 2005 三 種 標 準 語 法, 也 支 援 部 分 的 SystemVerilog 語 法, 其 官 方 網 站 網 址 如 下 : 如 果 您 是 MS Windows 的 使 用 者, 可 以 從 以 下 網 址 中 下 載 Icarus 的 MS Windows 版 本, 其 安 裝 非 常 容 易 : 範 例 1:XOR3 的 電 路 module xor3(input a, b, c, output abc); wire ab; xor g1(ab, a, b); xor g2(abc, c, ab); module module xor3test;
26 reg a, b, c; wire abc; xor3 g(a,b,c, abc); initial begin a = 0; b = 0; c = 0; always #50 begin a = a+1; $monitor("%4dns monitor: a=%d b=%d c=%d a^b^c=%d", $stime, a, b, c, abc ); always #100 begin b = b+1; always #200 begin c = c+1; initial #2000 $finish; module Icarus 執 行 結 果 D:\ccc101\icarus\ccc>iverilog -o xor3test xor3test.v D:\ccc101\icarus\ccc>vvp xor3test 50ns monitor: a=1 b=0 c=0 a^b^c=1 100ns monitor: a=0 b=1 c=0 a^b^c=1 150ns monitor: a=1 b=1 c=0 a^b^c=0
27 200ns monitor: a=0 b=0 c=1 a^b^c=1 250ns monitor: a=1 b=0 c=1 a^b^c=0 300ns monitor: a=0 b=1 c=1 a^b^c=0 350ns monitor: a=1 b=1 c=1 a^b^c=1 400ns monitor: a=0 b=0 c=0 a^b^c=0 450ns monitor: a=1 b=0 c=0 a^b^c=1 500ns monitor: a=0 b=1 c=0 a^b^c=1 550ns monitor: a=1 b=1 c=0 a^b^c=0 600ns monitor: a=0 b=0 c=1 a^b^c=1 650ns monitor: a=1 b=0 c=1 a^b^c=0 700ns monitor: a=0 b=1 c=1 a^b^c=0 750ns monitor: a=1 b=1 c=1 a^b^c=1 800ns monitor: a=0 b=0 c=0 a^b^c=0 850ns monitor: a=1 b=0 c=0 a^b^c=1 900ns monitor: a=0 b=1 c=0 a^b^c=1 950ns monitor: a=1 b=1 c=0 a^b^c=0 1000ns monitor: a=0 b=0 c=1 a^b^c=1 1050ns monitor: a=1 b=0 c=1 a^b^c=0 1100ns monitor: a=0 b=1 c=1 a^b^c=0 1150ns monitor: a=1 b=1 c=1 a^b^c=1 1200ns monitor: a=0 b=0 c=0 a^b^c=0 1250ns monitor: a=1 b=0 c=0 a^b^c=1 1300ns monitor: a=0 b=1 c=0 a^b^c=1 1350ns monitor: a=1 b=1 c=0 a^b^c=0 1400ns monitor: a=0 b=0 c=1 a^b^c=1 1450ns monitor: a=1 b=0 c=1 a^b^c=0 1500ns monitor: a=0 b=1 c=1 a^b^c=0 1550ns monitor: a=1 b=1 c=1 a^b^c=1 1600ns monitor: a=0 b=0 c=0 a^b^c=0 1650ns monitor: a=1 b=0 c=0 a^b^c=1 1700ns monitor: a=0 b=1 c=0 a^b^c=1 1750ns monitor: a=1 b=1 c=0 a^b^c=0 1800ns monitor: a=0 b=0 c=1 a^b^c=1 1850ns monitor: a=1 b=0 c=1 a^b^c=0 1900ns monitor: a=0 b=1 c=1 a^b^c=0 1950ns monitor: a=1 b=1 c=1 a^b^c=1 2000ns monitor: a=0 b=0 c=0 a^b^c=0
28 仔 細 觀 察 上 述 輸 出 結 果, 您 會 發 現 這 個 結 果 與 真 值 表 的 內 容 完 全 一 致, 因 此 驗 證 了 該 設 計 的 正 確 性! 透 過 這 種 方 式, 您 就 可 以 用 Verilog 設 計 電 路 的 程 式, 然 後 用 Icarus 編 譯 並 驗 證 電 路 是 否 正 確 區 塊 式 設 計 閘 級 的 線 路 設 計 方 法 Verilog 既 然 是 硬 體 描 述 語 言, 那 當 然 會 有 邏 輯 閘 的 表 示 法,Verilog 提 供 的 邏 輯 閘 有 and, nand, or, nor, xor, xnor, not 等 元 件, 因 此 您 可 以 用 下 列 Verilog 程 式 描 述 一 個 全 加 器 : module fulladder (input a, b, c_in, output sum, c_out); wire s1, c1, c2; xor g1(s1, a, b); xor g2(sum, s1, c_in); and g3(c1, a,b); and g4(c2, s1, c_in) ; or g5(c_out, c2, c1) ; module 上 述 程 式 所 對 應 的 電 路 如 下 圖 所 示 : 全 加 器 電 路 圖 這 些 邏 輯 閘 並 不 受 限 於 兩 個 輸 入, 也 可 以 是 多 個 輸 入 的, 例 如 以 下 範 例 中 的 g 閘, 就 一 次 將 三 個 輸 入 a, b, c_in 進 行 xor 運 算, 產 生 輸 出 sum 的 結 果 xor g(sum, a, b, c_in);
29 範 例 2: 全 加 器 的 閘 級 設 計 傳 統 的 數 位 邏 輯 課 程 當 中, 我 們 通 常 會 用 邏 輯 閘 的 組 合 方 式, 來 設 計 出 所 要 的 電 路, 以 下 我 們 就 用 全 加 器 當 範 例, 說 明 如 何 用 閘 級 的 語 法, 在 Verilog 當 中 設 計 數 位 電 路 全 加 器 總 共 有 3 個 輸 入 (a, b, c_in), 兩 個 輸 出 值 (sum, c_out), 其 真 值 表 如 下 所 示 : a b c_in c_out sum 根 據 這 個 真 值 表, 我 們 可 以 用 卡 諾 圖 得 到 化 簡 後 的 電 路 ( 但 必 須 注 意 的 是, 卡 諾 圖 化 簡 出 來 的 電 路 只 有 AND, OR, NOT, 沒 有 XOR), 然 後 根 據 化 簡 後 的 算 式 繪 製 電 路 圖 ( 在 此 範 例 中,c_out 可 以 採 用 卡 諾 圖 化 簡 出 來, 但 sum 使 用 的 並 非 化 簡 的 結 果, 而 是 以 經 驗 得 到 的 XOR 組 合 式 ) 當 您 完 成 邏 輯 運 算 式 設 計 之 後, 就 可 以 用 TinyCAD 這 個 軟 體, 繪 製 出 全 加 器 的 電 路 如 下 圖 所 示 : 用 TinyCAD 繪 製 的 全 加 器 電 路 圖 接 著 我 們 可 以 按 照 以 上 的 線 路, 根 據 Verilog 的 語 法, 設 計 出 對 應 元 件 與 測 試 程 式 如 下 所 示 :
30 程 式 :fulladder.v // 以 下 為 全 加 器 模 組 的 定 義 module fulladder (input a, b, c_in, output sum, c_out); wire s1, c1, c2; xor g1(s1, a, b); xor g2(sum, s1, c_in); and g3(c1, a,b); and g4(c2, s1, c_in) ; or g5(c_out, c2, c1) ; module // 以 下 為 測 試 程 式 module main; reg a, b, c_in; wire sum, c_out; fulladder fa1(a, b, c_in, sum, c_out); initial begin a = 0; b = 0; c_in = 0; $monitor("%04dns monitor: a=%d b=%d c_in=%d c_out=%d sum=%d", $stime, a, b, c_in, c_out, sum); #1000 $finish; always #50 c_in = c_in+1; always #100 b = b+1; always #200 a = a+1; module 然 後 我 們 就 可 以 利 用 Icarus 進 行 編 譯 與 測 試, 看 看 fulladder.v 的 模 擬 執 行 結 果 是 否 正 確 編 譯 執 行 結 果 :
31 D:\Dropbox\Public\pmag\201306\code>iverilog -o fulladder fulladder.v D:\Dropbox\Public\pmag\201306\code>vvp fulladder 0000ns monitor: a=0 b=0 c_in=0 c_out=0 sum=0 0050ns monitor: a=0 b=0 c_in=1 c_out=0 sum=1 0100ns monitor: a=0 b=1 c_in=0 c_out=0 sum=1 0150ns monitor: a=0 b=1 c_in=1 c_out=1 sum=0 0200ns monitor: a=1 b=0 c_in=0 c_out=0 sum=1 0250ns monitor: a=1 b=0 c_in=1 c_out=1 sum=0 0300ns monitor: a=1 b=1 c_in=0 c_out=1 sum=0 0350ns monitor: a=1 b=1 c_in=1 c_out=1 sum=1 0400ns monitor: a=0 b=0 c_in=0 c_out=0 sum=0 0450ns monitor: a=0 b=0 c_in=1 c_out=0 sum=1 0500ns monitor: a=0 b=1 c_in=0 c_out=0 sum=1 0550ns monitor: a=0 b=1 c_in=1 c_out=1 sum=0 0600ns monitor: a=1 b=0 c_in=0 c_out=0 sum=1 0650ns monitor: a=1 b=0 c_in=1 c_out=1 sum=0 0700ns monitor: a=1 b=1 c_in=0 c_out=1 sum=0 0750ns monitor: a=1 b=1 c_in=1 c_out=1 sum=1 0800ns monitor: a=0 b=0 c_in=0 c_out=0 sum=0 0850ns monitor: a=0 b=0 c_in=1 c_out=0 sum=1 0900ns monitor: a=0 b=1 c_in=0 c_out=0 sum=1 0950ns monitor: a=0 b=1 c_in=1 c_out=1 sum=0 1000ns monitor: a=1 b=0 c_in=0 c_out=0 sum=1 習 題 1: 請 證 明 nand 閘 是 全 能 的 ( 提 示 : 只 要 用 nand 做 出 and, or, not 就 行 了 ) 習 題 2: 請 用 卡 諾 圖 去 化 簡 全 加 器 的 Cout 電 路 習 題 3: 請 寫 一 個 Verilog 程 式 用 nand 兜 出 or 電 路, 並 測 試 之 區 塊 式 設 計 的 注 意 事 項 當 您 採 用 區 塊 式 設 計 時, 有 一 些 常 見 的 初 學 者 錯 誤 必 須 注 意, 列 舉 如 下 : 1. assign 的 指 定 是 針 對 線 路, 而 暫 存 器 的 指 定 必 須 放 在 always 或 initial 區 塊 裏 因 此, 下 列 程 式 中 在 assign 指 定 reg 型 態 的 變 數 o1 = i1 是 錯 的, 必 須 將 reg 去 掉, 或 者 改 放 到 always 區 塊 裏
32 圖 在 assign 裏 只 能 指 定 wire 型 態 的 變 數, 不 能 指 定 reg 型 態 的 2. 相 反 的,always 區 塊 裏 的 指 定, 只 能 針 對 reg 型 態 的 變 數 進 行, 不 能 套 用 在 線 路 (wire: 含 input, output, inout) 型 態 的 變 數 上 因 此 下 列 程 式 當 中 若 沒 有 將 o1 加 上 reg 型 態, 則 會 發 生 錯 誤 圖 在 always 裏 才 能 指 定 reg 型 態 的 變 數 3. 上 述 的 參 數 output reg o1 其 實 是 一 種 將 暫 存 器 與 線 路 同 時 宣 告 的 縮 寫, 事 實 上 我 們 可 以 將 該 宣 告 拆 開 成 相 同 名 稱 的 兩 部 份 (output o1, reg o1) 或 者 甚 至 乾 脆 使 用 不 同 的 名 稱 來 宣 告 暫 存 器, 然 後 再 透 過 assign 將 線 路 與 暫 存 器 綁 在 一 起, 這 三 種 寫 法 的 意 義 其 實 都 是 相 同 的, 請 參 考 下 圖 :
33 圖 同 時 具 備 wire + reg 的 宣 告 方 式 4. assign 裏 面 除 了 指 定 敘 述 = 與 基 本 運 算 (&!^...) 之 外, 還 可 以 用 (cond)?case1:case2; 的 這 種 語 法 舉 例 而 言, 以 下 是 微 控 制 器 mcu0 裏 控 制 單 元 的 範 例, 您 可 以 看 到 類 似 層 次 性 if else 的 語 法 也 可 用 這 種 方 式 在 aluop 這 個 語 句 上 實 現 module control(input [3:0] op, input z, output mw, aw, pcmux, sww, outpu t [3:0] aluop); assign mw=(op==mcu0.st); assign aw=(op==mcu0.ld op==mcu0.add); assign sww=(op==mcu0.cmp); assign pcmux=(op==mcu0.jmp (op==mcu0.jeq && z)); assign aluop=(op==mcu0.ld)?alu0.apass: (op==mcu0.cmp)?alu0.cmp: (op==mcu0.add)?alu0.add:alu0.zero; module 流 程 式 設 計 所 謂 RTL 是 Register Transfer Language 的 縮 寫, 也 就 是 暫 存 器 轉 換 語 言, 這 種 寫 法 與 C, Java 等 高 階 語 言 非 常 相 似, 因 此 讓 程 式 人 也 有 機 會 透 過 Verilog 設 計 自 己 的 硬 體 舉 例 而 言, 在 數 位 邏 輯 當 中, 多 工 器 是 一 個 很 有 用 的 電 路, 假 如 我 們 想 設 計 一 個 二 選 一 的 多 工 器, 那 麼 我 們 可 以 很 直 覺 得 用 以 下 的 RTL 寫 法, 去 完 成 這 樣 的 電 路 設 計 module mux(f, a, b, sel);
34 output f; input a, b, sel; reg f; // reg 型 態 會 記 住 某 些 值, 直 到 被 某 個 assign 指 定 改 變 為 止 or b or sel) // 當 任 何 變 數 改 變 的 時 候, 會 執 行 內 部 區 塊 if (sel) f = a; // Always 內 部 的 區 塊 採 用 imperative 程 式 語 言 的 寫 法 else f = b; module 對 於 上 述 程 式, 您 還 可 以 進 一 步 的 將 參 數 部 分 化 簡, 將 型 態 寫 入 到 參 數 中, 成 為 以 下 的 形 式 : module mux(output reg f, input a, b, sel); or b or sel) // 當 任 何 變 數 改 變 的 時 候, 會 執 行 內 部 區 塊 if (sel) f = a; // Always 內 部 的 區 塊 採 用 imperative 程 式 語 言 的 寫 法 else f = b; module 在 verilog 當 中,if, case 等 陳 述 一 定 要 放 在 always 或 initial 的 理 代 表 在 cond 的 條 件 之 下 要 執 行 該 區 塊, 例 如 上 述 的 or b or sel) 則 是 在 a, b, 或 sel 有 改 變 的 時 後, 就 必 須 執 行 裏 面 的 動 作 有 時 我 們 只 希 望 在 波 型 的 正 邊 緣 或 負 邊 緣 時, 才 執 行 某 些 動 作, 這 時 候 就 可 以 用 posedge 或 negedge 這 兩 個 修 飾 詞, 例 如 以 下 的 程 式 : clock) begin // 當 clock 時 脈 在 正 邊 緣 時 才 執 行 f = a; 而 initial 則 通 常 是 在 測 試 程 式 test bench 當 中 使 用 的, 在 一 開 始 初 始 化 的 時 後, 可 以 透 過 initial 設 定 初 值, 例 如 以 下 的 程 式 : initial begin clock = 0 Verilog 程 式 的 許 多 地 方, 都 可 以 用 #delay 指 定 時 間 延 遲, 例 如 #50 就 是 延 遲 50 單 位 的 時 間 ( 通 常 一 單 位 時 間 是 一 奈 秒 ns) 舉 例 而 言, 假 如 我 們 想 要 每 個 50 奈 秒 讓 clock 變 化 一 次, 那 麼 我 們 就 可 以 用 下 列 寫 法 達 到 目 的 : always #50 begin clock = ~clock; // 將 clock 反 相 (0 變 1 1 變 0)
35 以 上 的 延 遲 也 可 以 寫 在 裡 面, 而 不 是 直 接 寫 在 always 後 面, 例 如 改 用 以 下 寫 法, 也 能 得 到 相 同 的 結 果 always begin #50; clock = ~clock; // 將 clock 反 相 (0 變 1 1 變 0) 範 例 3: 計 數 器 的 RTL 設 計 接 著 讓 我 們 用 一 個 整 合 的 計 數 器 範 例, 來 示 範 這 些 語 法 的 實 際 用 途, 以 下 是 我 們 的 程 式 內 容 檔 案 :counter.v // 定 義 計 數 器 模 組 counter, 包 含 重 置 reset, 時 脈 clock 與 暫 存 器 count module counter(input reset, clock, output reg [7:0] count); // 當 reset 有 任 何 改 變 時 if (reset) count = 0; // 如 果 reset 是 1, 就 將 count 重 置 為 0 clock) begin // 在 clock 時 脈 的 正 邊 緣 時 count = count + 1; // 將 count 加 1 module module main; // 測 試 主 程 式 開 始 wire [7:0] i; // i: 計 數 器 的 輸 出 值 reg reset, clock; // reset: 重 置 訊 號, clock: 時 脈 // 宣 告 一 個 counter 模 組 c0 計 數 器 的 值 透 過 線 路 i 輸 出, 以 便 觀 察 counter c0(reset, clock, i); initial begin $display("%4dns: reset=%d clock=%d i=%d", $stime, reset, clock, i); // 印 出 0ns: reset=x clock=x i= x #10 reset = 1; clock=0; // 10ns 之 後, 將 啟 動 重 置 訊 號, 並 將 clock 初 值 設 為 0 $display("%4dns: reset=%d clock=%d i=%d", $stime, reset, clock, i); // 印 出 10ns: reset=1 clock=0 i= x #10 reset = 0; // 又 經 過 10ns 之 後, 重 置 完 畢, 將 reset 歸 零 $display("%4dns: reset=%d clock=%d i=%d", $stime, reset, clock, i); //
36 印 出 20ns: reset=0 clock=0 i= 0 #500 $finish; // 再 經 過 500ns 之 後, 結 束 程 式 always #40 begin // 延 遲 40ns 之 後, 開 始 作 下 列 動 作 clock=~clock; // 將 時 脈 反 轉 (0 變 1 1 變 0) #10; // 再 延 遲 10ns 之 後 $display("%4dns: reset=%d clock=%d i=%d", $stime, reset, clock, i); // 印 出 reset, clock 與 i 等 變 數 值 module 在 上 述 程 式 中,$display() 函 數 可 以 用 來 顯 示 變 數 的 內 容, 其 作 用 就 像 C 語 言 的 printf() 一 樣 不 過 由 於 Verilog 設 計 的 是 硬 體, 因 此 像 $display() 這 樣 前 面 有 錢 字 $ 符 號 的 指 令, 其 實 是 不 會 被 合 成 為 電 路 的, 只 是 方 便 除 錯 時 使 用 而 已 以 下 是 我 們 用 icarus 軟 體 編 譯 並 執 行 上 述 程 式 的 過 程 與 輸 出 結 果 : D:\Dropbox\Public\pmag\201307\code>iverilog -o counter counter.v D:\Dropbox\Public\pmag\201307\code>vvp counter 0ns: reset=x clock=x i= x 10ns: reset=1 clock=0 i= x 20ns: reset=0 clock=0 i= 0 50ns: reset=0 clock=1 i= 1 100ns: reset=0 clock=0 i= 1 150ns: reset=0 clock=1 i= 2 200ns: reset=0 clock=0 i= 2 250ns: reset=0 clock=1 i= 3 300ns: reset=0 clock=0 i= 3 350ns: reset=0 clock=1 i= 4 400ns: reset=0 clock=0 i= 4 450ns: reset=0 clock=1 i= 5 500ns: reset=0 clock=0 i= 5 您 可 以 看 到, 在 一 開 始 的 時 候 以 下 的 initial 區 塊 會 被 執 行, 但 由 於 此 時 reset, clock, i 都 尚 未 被 賦 值, 所 以 第 一 個 $display() 印 出 了 代 表 未 定 值 的 x 符 號 initial begin
37 $display("%4dns: reset=%d clock=%d i=%d", $stime, reset, clock, i); // 印 出 0ns: reset=x clock=x i= x #10 reset = 1; clock=0; // 10ns 之 後, 將 啟 動 重 置 訊 號, 並 將 clock 初 值 設 為 0 $display("%4dns: reset=%d clock=%d i=%d", $stime, reset, clock, i); // 印 出 10ns: reset=1 clock=0 i= x #10 reset = 0; // 又 經 過 10ns 之 後, 重 置 完 畢, 將 reset 歸 零 $display("%4dns: reset=%d clock=%d i=%d", $stime, reset, clock, i); // 印 出 20ns: reset=0 clock=0 i= 0 #500 $finish; // 再 經 過 500ns 之 後, 結 束 程 式 接 著 #10 reset = 1; clock=0 指 令 在 延 遲 10ns 後, 執 行 reset=1; clock=0, 於 是 後 來 的 $display() 就 印 出 了 10ns: reset=1 clock=0 i= x 的 結 果 但 是 就 在 reset 被 設 為 1 的 時 候, 由 於 reset 的 值 有 所 改 變, 因 此 下 列 模 組 中 的 被 觸 發 了, 於 是 開 始 執 行 if (reset) count = 0 這 個 陳 述, 將 count 暫 存 器 設 定 為 0 module counter(input reset, clock, output reg [7:0] count); // 當 reset 有 任 何 改 變 時 if (reset) count = 0; // 如 果 reset 是 1, 就 將 count 重 置 為 0 clock) begin // 在 clock 時 脈 的 正 邊 緣 時 count = count + 1; // 將 count 加 1 module 然 後 #10 reset = 0 指 令 又 在 延 遲 10ns 後 執 行 了 reset = 0, 之 後 再 用 $display() 時, 由 於 count 已 經 被 設 定 為 0, 所 以 此 時 印 出 的 結 果 為 20ns: reset=0 clock=0 i= 0 initial 區 塊 的 最 後 一 個 陳 述,#500 $finish, 會 在 520ns 的 時 候 才 執 行, 執 行 時 $finish 會 將 整 個 測 試 程 式 結 束 但 在 程 式 結 束 之 前, 以 下 的 程 式 會 在 延 遲 40ns 之 後, 開 始 將 clock 反 相, 然 後 再 等 待 10ns 之 後 用 $display() 印 出 變 數 內 容, 因 此 整 個 區 塊 每 50ns (=40ns+10ns) 會 被 執 行 一 次 always #40 begin // 延 遲 40ns 之 後, 開 始 作 下 列 動 作 clock=~clock; // 將 時 脈 反 轉 (0 變 1 1 變 0) #10; // 再 延 遲 10ns 之 後 $display("%4dns: reset=%d clock=%d i=%d", $stime, reset, clock, i); // 印 出 reset, clock 與 i 等 變 數 值
38 所 以 您 才 會 看 到 像 下 面 的 輸 出 結 果, 如 果 仔 細 觀 察, 會 發 現 clock 每 50ns 變 換 一 次, 符 合 上 述 的 程 式 邏 輯, 而 且 每 當 clock 從 0 變 成 1 的 正 邊 緣, 就 會 觸 發 counter 模 組, 讓 count 變 數 加 1, 並 且 透 過 線 路 i 的 輸 出 被 我 們 觀 察 到 50ns: reset=0 clock=1 i= 1 100ns: reset=0 clock=0 i= 1 150ns: reset=0 clock=1 i= 2 200ns: reset=0 clock=0 i= 2 250ns: reset=0 clock=1 i= 3 300ns: reset=0 clock=0 i= 3 ( 註 : 或 許 您 有 注 意 到 上 期 當 中 我 們 用 $monitor() 來 觀 察 全 加 器 的 輸 出,$display() 與 $monitor() 的 語 法 幾 乎 一 模 一 樣, 但 是 $display() 是 顯 示 該 時 間 點 的 變 數 內 容, 而 $monitor() 則 會 在 受 觀 察 的 變 數 有 改 變 時 就 列 印 變 數 內 容, 兩 者 的 的 功 能 有 明 顯 的 差 異 ) 阻 塞 vs. 非 阻 塞 (Blocking vs. Nonblocking) 您 可 能 會 注 意 到 在 Verilog 當 中 有 兩 種 指 定 方 式, 一 種 用 = 表 示, 另 一 種 用 <= 表 示, 這 兩 種 指 定 方 法 看 來 很 類 似, 但 意 義 上 卻 有 很 細 緻 的 差 異, 一 般 Verilog 初 學 者 往 往 分 不 清 楚, 因 而 造 成 很 多 程 式 上 的 錯 誤 基 本 上 = 指 令 是 阻 塞 式 的 (Blocking), 因 此 程 式 會 按 照 循 序 的 方 式, 一 個 指 令 接 著 一 個 指 令 執 行, 就 像 C 語 言 裏 的 a=b, b=c 這 樣,b=c 會 在 a=b 執 行 完 之 後 才 執 行, 以 下 是 一 個 範 例 但 是 <= 指 令 卻 是 非 阻 塞 式 的 (Nonblocking), 所 以 程 式 會 採 用 平 行 的 方 式 執 行 舉 例 而 言, 像 是 a<=b, b<=c 會 同 時 執 行 兩 者, 所 以 a 會 取 得 上 一 輪 的 b 值, 而 b 則 會 取 得 上 一 輪 的 c 值 Blocking 的 語 法 (=) 通 常 用 在 組 合 電 路 上, 也 就 是 語 句 裏 面, 而 Nonblocking 的 語 法 (<=) 通 常 用 在 採 用 邊 緣 觸 發 的 循 序 電 路 上, 也 就 是 clock) 的 語 句 裏 面 且 讓 我 們 用 幾 個 範 例 來 說 明 blocking = 與 Nonblocking <= 的 差 別 範 例 1: 阻 塞 式 (Blocking =) 非 阻 塞 式 (Nonblocking <=) or b or c) begin a=0; b=a; c=b; clock or reset) begi n a<=0; b<=a; c<=b; 結 果 :a=0; b= 上 一 輪 的 a 值 ; c= 上 一 輪 的 b 值 合 成 電 路 :
39 結 果 : a=b=c=0; 合 成 電 路 : 注 意 : 通 常 blocking assignment = 會 用 在 語 句 裏 面 注 意 : 通 常 nonblocking assignment <= 會 用 在 clock or reset) 語 句 裏 面 結 語 有 些 人 說 在 設 計 Verilog 程 式 的 時 候, 必 須 先 心 中 有 電 路, 才 能 夠 設 計 的 出 來 但 是 從 我 這 樣 一 個 程 式 人 的 角 度 看 來, 並 非 如 此, 採 用 流 程 式 的 寫 法 也 可 以 設 計 得 出 Verilog 程 式, 不 需 一 定 要 有 電 路 圖 當 然 採 用 流 程 式 寫 法 的 話, 如 果 是 用 blocking 的 = 方 式, 那 麼 可 能 會 造 成 很 長 的 鏈 狀 結 構, 這 或 許 會 讓 電 路 效 能 變 差 但 是 由 於 流 程 式 寫 法 簡 單 又 清 楚, 因 此 程 式 碼 往 往 比 區 塊 式 寫 法 短, 而 且 更 容 易 懂, 這 是 流 程 式 寫 法 的 好 處 當 然 如 果 兩 種 寫 法 都 會, 那 是 最 好 的 了, 我 們 將 在 後 續 的 章 節 當 中 陸 續 用 完 整 的 案 例 示 範 如 何 用 這 兩 種 寫 法 分 別 撰 寫 開 放 電 腦 計 畫 中 的 處 理 器, 以 便 讓 讀 者 能 深 入 體 會 兩 種 寫 法 的 好 處 與 缺 點 參 考 文 獻 ( 筆 記 ) dispaly() strobe() monitor() fwrite() 與 blocking / nonblocking 的 關 係
40 組 合 邏 輯 (Combinatorial Logic) 簡 介 在 數 位 電 路 當 中, 邏 輯 電 路 通 常 被 分 為 兩 類, 一 類 是 沒 有 回 饋 線 路 (No feedback) 的 組 合 邏 輯 電 路 (Combinatorial Logic), 另 一 類 是 有 回 饋 線 路 的 循 序 邏 輯 電 路 (Sequential Logic) 組 合 邏 輯 的 線 路 只 是 將 輸 入 訊 號 轉 換 成 輸 出 訊 號, 像 是 加 法 器 多 工 器 等 都 是 組 合 邏 輯 電 路 的 範 例, 由 於 中 間 不 會 暫 存, 因 此 無 法 記 憶 位 元 而 循 序 邏 輯 由 於 有 回 饋 線 路, 所 以 可 以 製 作 出 像 Flip-Flop,Latch 等 記 憶 單 元, 可 以 記 憶 位 元 在 本 文 中, 我 們 將 先 專 注 在 組 合 邏 輯 上, 看 看 如 何 用 基 本 的 閘 級 寫 法, 寫 出 像 多 工 器 加 法 器 減 法 器 等 組 成 CPU 的 基 礎 電 路 元 件 加 法 器 接 著 讓 我 們 用 先 前 已 經 示 範 過 的 全 加 器 範 例, 一 個 一 個 連 接 成 四 位 元 的 加 法 器, 電 路 圖 如 下 所 示 圖 用 4 個 全 加 器 組 成 4 位 元 加 法 器 上 圖 寫 成 Verilog 就 變 成 以 下 adder4 模 組 的 程 式 內 容 module adder4(input signed [3:0] a, input signed [3:0] b, input c_in, ou tput signed [3:0] sum, output c_out); wire [3:0] c; fulladder fa1(a[0],b[0], c_in, sum[0], c[1]) ; fulladder fa2(a[1],b[1], c[1], sum[1], c[2]) ; fulladder fa3(a[2],b[2], c[2], sum[2], c[3]) ; fulladder fa4(a[3],b[3], c[3], sum[3], c_out) ; module 以 下 是 完 整 的 4 位 元 加 法 器 之 Verilog 程 式
41 檔 案 :adder4.v module fulladder (input a, b, c_in, output sum, c_out); wire s1, c1, c2; xor g1(s1, a, b); xor g2(sum, s1, c_in); and g3(c1, a,b); and g4(c2, s1, c_in) ; xor g5(c_out, c2, c1) ; module module adder4(input signed [3:0] a, input signed [3:0] b, input c_in, ou tput signed [3:0] sum, output c_out); wire [3:0] c; fulladder fa1(a[0],b[0], c_in, sum[0], c[1]) ; fulladder fa2(a[1],b[1], c[1], sum[1], c[2]) ; fulladder fa3(a[2],b[2], c[2], sum[2], c[3]) ; fulladder fa4(a[3],b[3], c[3], sum[3], c_out) ; module module main; reg signed [3:0] a; reg signed [3:0] b; wire signed [3:0] sum; wire c_out; adder4 DUT (a, b, 1'b0, sum, c_out); initial begin a = 4'b0101; b = 4'b0000;
42 always #50 begin b=b+1; $monitor("%dns monitor: a=%d b=%d sum=%d", $stime, a, b, sum); initial #2000 $finish; module 執 行 結 果 D:\ccc101\icarus\ccc>iverilog -o sadd4 sadd4.v D:\ccc101\icarus\ccc>vvp sadd4 50ns monitor: a= 5 b= 1 sum= 6 100ns monitor: a= 5 b= 2 sum= 7 150ns monitor: a= 5 b= 3 sum=-8 200ns monitor: a= 5 b= 4 sum=-7 250ns monitor: a= 5 b= 5 sum=-6 300ns monitor: a= 5 b= 6 sum=-5 350ns monitor: a= 5 b= 7 sum=-4 400ns monitor: a= 5 b=-8 sum=-3 450ns monitor: a= 5 b=-7 sum=-2 500ns monitor: a= 5 b=-6 sum=-1 550ns monitor: a= 5 b=-5 sum= 0 600ns monitor: a= 5 b=-4 sum= 1 650ns monitor: a= 5 b=-3 sum= 2 700ns monitor: a= 5 b=-2 sum= 3 750ns monitor: a= 5 b=-1 sum= 4 800ns monitor: a= 5 b= 0 sum= 5 850ns monitor: a= 5 b= 1 sum= 6 900ns monitor: a= 5 b= 2 sum= 7 950ns monitor: a= 5 b= 3 sum= ns monitor: a= 5 b= 4 sum= ns monitor: a= 5 b= 5 sum= ns monitor: a= 5 b= 6 sum= ns monitor: a= 5 b= 7 sum= ns monitor: a= 5 b=-8 sum=-3
43 1250ns monitor: a= 5 b=-7 sum= ns monitor: a= 5 b=-6 sum= ns monitor: a= 5 b=-5 sum= ns monitor: a= 5 b=-4 sum= ns monitor: a= 5 b=-3 sum= ns monitor: a= 5 b=-2 sum= ns monitor: a= 5 b=-1 sum= ns monitor: a= 5 b= 0 sum= ns monitor: a= 5 b= 1 sum= ns monitor: a= 5 b= 2 sum= ns monitor: a= 5 b= 3 sum= ns monitor: a= 5 b= 4 sum= ns monitor: a= 5 b= 5 sum= ns monitor: a= 5 b= 6 sum= ns monitor: a= 5 b= 7 sum= ns monitor: a= 5 b=-8 sum=-3 在 上 述 執 行 結 果 中, 您 可 以 看 到 在 沒 有 溢 位 的 情 況 下,sum = a+b, 但 是 一 但 加 總 值 超 過 7 之 後, 那 就 會 變 成 負 值, 這 也 正 是 有 號 二 補 數 表 示 法 溢 位 時 會 產 生 的 結 果 32 位 元 加 法 器 當 然 上 述 的 四 位 元 加 法 器 的 範 圍, 只 能 從 -8 到 +7, 這 個 範 圍 實 在 太 小 了, 並 不 具 備 任 何 實 用 性, 但 是 萬 事 起 頭 難, 只 要 您 能 夠 做 出 四 位 元 加 法 器, 那 麼 就 可 以 利 用 這 個 元 件 進 行 串 接, 將 8 個 四 位 元 加 法 器 串 接 起 來, 立 刻 得 到 了 一 組 32 位 元 的 加 法 器, 以 下 是 這 個 32 位 元 加 法 器 的 模 組 定 義 module adder32(input signed [31:0] a, input signed [31:0] b, input c_in, output signed [31:0] sum, output c_out); wire [7:0] c; adder4 a0(a[3:0],b[3:0], c_in, sum[3:0], c[0]) ; adder4 a1(a[7:4],b[7:4], c[0], sum[7:4], c[1]) ; adder4 a2(a[11:8],b[11:8], c[1], sum[11:8], c[2]) ; adder4 a3(a[15:12],b[15:12], c[2], sum[15:12],c[3]) ; adder4 a4(a[19:16],b[19:16], c[3], sum[19:16],c[4]) ; adder4 a5(a[23:20],b[23:20], c[4], sum[23:20],c[5]) ; adder4 a6(a[27:24],b[27:24], c[5], sum[27:24],c[6]) ; adder4 a7(a[31:28],b[31:28], c[6], sum[31:28],c_out);
44 module 有 了 這 個 模 組 之 後, 您 就 可 以 寫 出 下 列 完 整 的 程 式, 以 測 試 驗 證 該 32 位 元 加 法 器 是 否 正 確 了 module fulladder (input a, b, c_in, output sum, c_out); wire s1, c1, c2; xor g1(s1, a, b); xor g2(sum, s1, c_in); and g3(c1, a,b); and g4(c2, s1, c_in) ; xor g5(c_out, c2, c1) ; module module adder4(input signed [3:0] a, input signed [3:0] b, input c_in, ou tput signed [3:0] sum, output c_out); wire [3:0] c; fulladder fa1(a[0],b[0], c_in, sum[0], c[1]) ; fulladder fa2(a[1],b[1], c[1], sum[1], c[2]) ; fulladder fa3(a[2],b[2], c[2], sum[2], c[3]) ; fulladder fa4(a[3],b[3], c[3], sum[3], c_out) ; module module adder32(input signed [31:0] a, input signed [31:0] b, input c_in, output signed [31:0] sum, output c_out); wire [7:0] c; adder4 a0(a[3:0],b[3:0], c_in, sum[3:0], c[0]) ; adder4 a1(a[7:4],b[7:4], c[0], sum[7:4], c[1]) ; adder4 a2(a[11:8],b[11:8], c[1], sum[11:8], c[2]) ; adder4 a3(a[15:12],b[15:12], c[2], sum[15:12],c[3]) ; adder4 a4(a[19:16],b[19:16], c[3], sum[19:16],c[4]) ; adder4 a5(a[23:20],b[23:20], c[4], sum[23:20],c[5]) ; adder4 a6(a[27:24],b[27:24], c[5], sum[27:24],c[6]) ; adder4 a7(a[31:28],b[31:28], c[6], sum[31:28],c_out);
45 module module main; reg signed [31:0] a; reg signed [31:0] b; wire signed [31:0] sum; wire c_out; adder32 DUT (a, b, 0, sum, c_out); initial begin a = ; b = ; $monitor("%dns monitor: a=%d b=%d sum=%d", $stime, a, b, sum); always #50 begin b=b ; initial #500 $finish; module 然 後 我 們 就 可 以 用 icarus 進 行 測 試, 以 下 是 測 試 結 果 : D:\Dropbox\Public\web\oc\code>iverilog -o adder32 adder32.v D:\Dropbox\Public\web\oc\code>vvp adder32 0ns monitor: a= b= sum= ns monitor: a= b= sum= ns monitor: a= b= sum= ns monitor: a= b= sum= ns monitor: a= b= sum= ns monitor: a= b= sum=
46 300ns monitor: a= b= sum= ns monitor: a= b= sum= ns monitor: a= b= sum= ns monitor: a= b= sum= ns monitor: a= b= sum= 您 可 以 看 到 sum 的 確 是 a+b 的 結 果, 因 此 這 個 32 位 元 加 法 器 的 初 步 驗 證 是 正 確 的 前 瞻 進 位 加 法 器 (Carry Lookahead Adder) 圖 4 位 元 前 瞻 進 位 加 法 器 圖 片 來 源 : 檔 案 :cladder4.v module cladder4(output [3:0] S, output Cout,PG,GG, input [3:0] A,B, inpu t Cin); wire [3:0] G,P,C; assign G = A & B; //Generate assign P = A ^ B; //Propagate assign C[0] = Cin; assign C[1] = G[0] (P[0]&C[0]); assign C[2] = G[1] (P[1]&G[0]) (P[1]&P[0]&C[0]); assign C[3] = G[2] (P[2]&G[1]) (P[2]&P[1]&G[0]) (P[2]&P[1]&P[0]& C[0]); assign Cout = G[3] (P[3]&G[2]) (P[3]&P[2]&G[1]) (P[3]&P[2]&P[1]& G[0]) (P[3]&P[2]&P[1]&P[0]&C[0]);
47 assign S = P ^ C; assign PG = P[3] & P[2] & P[1] & P[0]; assign GG = G[3] (P[3]&G[2]) (P[3]&P[2]&G[1]) (P[3]&P[2]&P[1]&G[ 0]); module module main; reg signed [3:0] a; reg signed [3:0] b; wire signed [3:0] sum; wire c_out; cladder4 DUT (sum, cout, pg, gg, a, b, 0); initial begin a = 5; b = -3; $monitor("%dns monitor: a=%d b=%d sum=%d", $stime, a, b, sum); module 執 行 結 果 D:\Dropbox\Public\web\oc\code>iverilog -o cladder4 cladder4.v D:\Dropbox\Public\web\oc\code>vvp cladder4 0ns monitor: a= 5 b=-3 sum= 2 結 語 在 本 文 中, 我 們 大 致 將 CPU 設 計 當 中 最 重 要 的 組 合 邏 輯 電 路, 也 就 是 多 工 器 加 法 器 減 法 器 的 設 計 原 理 說 明 完 畢 了, 希 望 透 過 Verilog 的 實 作 方 式, 能 讓 讀 者 更 瞭 解 數 位 電 路 的 設 計 原 理, 並 且 為 接 下 來 所 要 介 紹 的 處 理 器 設 計 進 行 鋪 路 的 工 作 參 考 文 獻
48 LSU EE Spring Computer Organization : Verilog Notes 7 -- Integer Multiply and Divide 陳 鍾 誠 的 網 站 :Verilog 電 路 設 計 -- 多 工 器 陳 鍾 誠 的 網 站 :Verilog 電 路 設 計 -- 4 位 元 加 法 器 陳 鍾 誠 的 網 站 :Verilog 電 路 設 計 -- 加 減 器 Wikipedia:Adder Wikipedia:Adder subtractor Wikipedia:Multiplexer 本 文 由 陳 鍾 誠 取 材 ( 主 要 為 圖 片 ) 並 修 改 自 維 基 百 科
49 算 術 邏 輯 單 元 ALU 的 設 計 在 上 一 章 中, 我 們 探 討 了 組 合 邏 輯 電 路 的 設 計 方 式, 採 用 閘 級 的 拉 線 方 式 設 計 了 多 工 器 與 加 法 器 等 元 件, 在 本 章 當 中, 我 們 將 從 加 法 器 再 度 往 上, 探 討 如 何 設 計 一 個 ALU 單 元 加 減 器 我 們 只 要 把 加 法 器, 加 上 一 組 控 制 的 互 斥 或 閘, 並 控 制 輸 入 進 位 與 否, 就 可 以 成 為 加 減 器 了, 這 是 因 為 我 們 採 用 了 二 補 數 的 關 係 二 補 數 讓 我 們 可 以 很 容 易 的 延 伸 加 法 器 電 路 就 能 做 出 減 法 器 我 們 可 以 在 運 算 元 B 之 前 加 上 2 選 1 多 工 器 或 XOR 閘 來 控 制 B 是 否 應 該 取 補 數, 並 且 運 用 OP 控 制 線 路 來 進 行 控 制, 以 下 是 採 用 2 選 1 多 工 器 的 電 路 做 法 圖 圖 採 用 2 選 1 多 工 器 控 制 的 加 減 器 電 路 另 一 種 更 簡 單 的 做 法 是 採 用 XOR 閘 去 控 制 B 是 否 要 取 補 數, 如 下 圖 所 示 :
50 圖 採 用 XOR 控 制 的 加 減 器 電 路 清 楚 了 電 路 圖 的 布 局 之 後, 讓 我 們 來 看 看 如 何 用 Verilog 實 做 加 減 器 吧! 關 鍵 部 分 的 程 式 如 下 所 示, 這 個 模 組 就 對 應 到 上 述 的 採 用 XOR 控 制 的 加 減 器 電 路 之 圖 形 module addsub4(input op, input signed [3:0] a, input signed [3:0] b, output signed [3:0] sum, output c_out); wire [3:0] bop; xor4 x1(b, {op,op,op,op}, bop); adder4 a1(a, bop, op, sum, c_out); module 接 著 讓 我 們 來 看 看 完 整 的 加 減 器 程 式 與 測 試 結 果 檔 案 :addsub4.v module fulladder (input a, b, c_in, output sum, c_out); wire s1, c1, c2; xor g1(s1, a, b); xor g2(sum, s1, c_in); and g3(c1, a,b); and g4(c2, s1, c_in) ; xor g5(c_out, c2, c1) ; module module adder4(input signed [3:0] a, input signed [3:0] b, input c_in, wire [3:0] c; output signed [3:0] sum, output c_out); fulladder fa1(a[0],b[0], c_in, sum[0], c[1]) ; fulladder fa2(a[1],b[1], c[1], sum[1], c[2]) ; fulladder fa3(a[2],b[2], c[2], sum[2], c[3]) ; fulladder fa4(a[3],b[3], c[3], sum[3], c_out) ;
51 module module xor4(input [3:0] a, input [3:0] b, output [3:0] y); assign y = a ^ b; module module addsub4(input op, input signed [3:0] a, input signed [3:0] b, output signed [3:0] sum, output c_out); wire [3:0] bop; xor4 x1(b, {op,op,op,op}, bop); adder4 a1(a, bop, op, sum, c_out); module module main; reg signed [3:0] a; reg signed [3:0] b; wire signed [3:0] sum; reg op; wire c_out; addsub4 DUT (op, a, b, sum, c_out); initial begin a = 4'b0101; b = 4'b0000; op = 1'b0; always #50 begin op=op+1; $monitor("%dns monitor: op=%d a=%d b=%d sum=%d", $stime, op, a, b, sum) ;
52 always #100 begin b=b+1; initial #2000 $finish; module 執 行 結 果 : D:\ccc101\icarus\ccc>iverilog -o addsub4 addsub4.v D:\ccc101\icarus\ccc>vvp addsub4 50ns monitor: op=1 a= 5 b= 0 sum= 5 100ns monitor: op=0 a= 5 b= 1 sum= 6 150ns monitor: op=1 a= 5 b= 1 sum= 4 200ns monitor: op=0 a= 5 b= 2 sum= 7 250ns monitor: op=1 a= 5 b= 2 sum= 3 300ns monitor: op=0 a= 5 b= 3 sum=-8 350ns monitor: op=1 a= 5 b= 3 sum= 2 400ns monitor: op=0 a= 5 b= 4 sum=-7 450ns monitor: op=1 a= 5 b= 4 sum= 1 500ns monitor: op=0 a= 5 b= 5 sum=-6 550ns monitor: op=1 a= 5 b= 5 sum= 0 600ns monitor: op=0 a= 5 b= 6 sum=-5 650ns monitor: op=1 a= 5 b= 6 sum=-1 700ns monitor: op=0 a= 5 b= 7 sum=-4 750ns monitor: op=1 a= 5 b= 7 sum=-2 800ns monitor: op=0 a= 5 b=-8 sum=-3 850ns monitor: op=1 a= 5 b=-8 sum=-3 900ns monitor: op=0 a= 5 b=-7 sum=-2 950ns monitor: op=1 a= 5 b=-7 sum= ns monitor: op=0 a= 5 b=-6 sum= ns monitor: op=1 a= 5 b=-6 sum= ns monitor: op=0 a= 5 b=-5 sum= ns monitor: op=1 a= 5 b=-5 sum= ns monitor: op=0 a= 5 b=-4 sum= 1
53 1250ns monitor: op=1 a= 5 b=-4 sum= ns monitor: op=0 a= 5 b=-3 sum= ns monitor: op=1 a= 5 b=-3 sum= ns monitor: op=0 a= 5 b=-2 sum= ns monitor: op=1 a= 5 b=-2 sum= ns monitor: op=0 a= 5 b=-1 sum= ns monitor: op=1 a= 5 b=-1 sum= ns monitor: op=0 a= 5 b= 0 sum= ns monitor: op=1 a= 5 b= 0 sum= ns monitor: op=0 a= 5 b= 1 sum= ns monitor: op=1 a= 5 b= 1 sum= ns monitor: op=0 a= 5 b= 2 sum= ns monitor: op=1 a= 5 b= 2 sum= ns monitor: op=0 a= 5 b= 3 sum= ns monitor: op=1 a= 5 b= 3 sum= ns monitor: op=0 a= 5 b= 4 sum=-7 在 上 述 結 果 中, 您 可 以 看 到 當 op=0 時, 電 路 所 作 的 是 加 法 運 算, 例 如 :200ns monitor: op=0 a= 5 b= 2 sum= 7 而 當 op=1 時, 電 路 所 做 的 是 減 法 運 算, 例 如 :250ns monitor: op=1 a= 5 b= 2 sum= 3 採 用 CASE 語 法 設 計 ALU 模 組 其 實 在 Verilog 當 中, 我 們 並 不 需 要 自 行 設 計 加 法 器, 因 為 Verilog 提 供 了 高 階 的 +, -, *, / 等 基 本 運 算, 可 以 讓 我 們 直 接 使 用, 更 方 便 的 是, 只 要 搭 配 case 語 句, 我 們 就 可 以 很 輕 易 的 設 計 出 一 個 ALU 單 元 了 以 下 是 一 個 簡 易 的 ALU 單 元 之 程 式 碼, // 輸 入 a, b 後 會 執 行 op 所 指 定 的 運 算, 然 後 將 結 果 放 在 暫 存 器 y 當 中 module alu(input [7:0] a, input [7:0] b, input [2:0] op, output reg [7:0 ] y); always@(a or b or op) begin // 當 a, b 或 op 有 改 變 時, 就 進 入 此 區 塊 執 行 case(op) // 根 據 op 決 定 要 執 行 何 種 運 算 3'b000: y = a + b; // op=000, 執 行 加 法 3'b001: y = a - b; // op=000, 執 行 減 法 3'b010: y = a * b; // op=000, 執 行 乘 法 3'b011: y = a / b; // op=000, 執 行 除 法 3'b100: y = a & b; // op=000, 執 行 AND 3'b101: y = a b; // op=000, 執 行 OR 3'b110: y = ~a; // op=000, 執 行 NOT
54 3'b111: y = a ^ b; // op=000, 執 行 XOR case module Verilog 語 法 的 注 意 事 項 上 述 這 種 寫 法 感 覺 就 好 像 在 用 高 階 寫 程 式 一 樣, 這 讓 ALU 的 設 計 變 得 非 常 簡 單 但 是 仍 然 需 要 注 意 以 下 幾 點 與 高 階 語 言 不 同 之 處 : 注 意 事 項 1. always 語 句 的 用 法 case 等 陳 述 句 的 外 面 一 定 要 有 always 或 initial 語 句, 因 為 這 是 硬 體 線 路, 所 以 是 採 用 連 線 wiring 的 方 式,always 語 句 只 有 中 間 的 trigger 觸 發 條 件 符 合 時 才 會 被 觸 發 當 trigger 中 的 變 數 有 任 何 改 變 的 時 候,always 語 句 就 會 被 觸 發, 像 是 always@(a or b or op) 就 代 表 當 (a, b, op) 當 中 任 何 一 個 有 改 變 的 時 候, 該 語 句 就 會 被 觸 發 有 時 我 們 可 以 在 always 語 句 當 中 加 上 posedge 的 條 件, 指 定 只 有 在 正 邊 緣 ( 上 昇 邊 緣 ) 時 觸 發 或 者 加 上 negedge 的 條 件, 指 定 只 有 在 負 邊 緣 ( 下 降 邊 緣 ) 的 時 候 觸 發, 例 如 我 們 可 以 常 常 在 Verilog 當 中 看 到 下 列 語 句 : clock) begin... 上 述 語 句 就 只 有 在 clock 這 一 條 線 路 的 電 波 上 昇 邊 緣 會 被 觸 發, 如 此 我 們 就 能 更 精 細 的 控 制 觸 發 的 動 作, 採 用 正 邊 緣 或 負 邊 緣 觸 發 的 方 式 注 意 事 項 2. 指 定 陳 述 的 左 項 之 限 制 在 上 述 程 式 中,a, b, op 被 宣 告 為 input ( 輸 入 線 路 ), 而 y 則 宣 告 為 output reg ( 輸 出 暫 存 器 ), 在 這 裏 必 須 注 意 的 是 y 不 能 只 宣 告 為 output 而 不 加 上 reg, 因 為 只 有 reg 型 態 的 變 數 才 能 被 放 在 always 區 塊 裡 的 等 號 左 方, 進 行 指 定 的 動 作 事 實 上 在 Verilog 當 中, 像 output reg [7:0] y 這 樣 的 宣 告, 其 實 也 可 以 用 比 較 繁 雜 的 兩 次 宣 告 方 式, 一 次 宣 告 output, 另 一 次 則 宣 告 reg, 如 下 所 示 : module alu(input [7:0] a, input [7:0] b, input [2:0] op, output [7:0] y) ; reg y; always@(a or b or op) begin... 甚 至, 您 也 可 以 將 該 變 數 分 開 為 兩 個 不 同 名 稱, 然 後 再 利 用 assign 的 方 式 指 定, 如 下 所 示 :
55 // 輸 入 a, b 後 會 執 行 op 所 指 定 的 運 算, 然 後 將 結 果 放 在 暫 存 器 y 當 中 module alu(input [7:0] a, input [7:0] b, input [2:0] op, output [7:0] y) ; reg ty; always@(a or b or op) begin // 當 a, b 或 op 有 改 變 時, 就 進 入 此 區 塊 執 行 case(op) // 根 據 op 決 定 要 執 行 何 種 運 算 3'b000: ty = a + b; // op=000, 執 行 加 法 3'b001: ty = a - b; // op=000, 執 行 減 法 3'b010: ty = a * b; // op=000, 執 行 乘 法 3'b011: ty = a / b; // op=000, 執 行 除 法 3'b100: ty = a & b; // op=000, 執 行 AND 3'b101: ty = a b; // op=000, 執 行 OR 3'b110: ty = ~a; // op=000, 執 行 NOT 3'b111: ty = a ^ b; // op=000, 執 行 XOR case $display("base 10 : %dns : op=%d a=%d b=%d y=%d", $stime, op, a, b, y); // 印 出 op, a, b, y 的 10 進 位 值 $display("base 2 : %dns : op=%b a=%b b=%b y=%b", $stime, op, a, b, y); // 印 出 op, a, b, y 的 2 進 位 值 assign y=ty; module 在 上 述 程 式 中, 由 於 只 有 reg 型 態 的 變 數 可 以 放 在 always 區 塊 內 的 等 號 左 邊, 因 此 我 們 必 須 用 reg 型 態 的 ty 去 儲 存 運 算 結 果 但 是 在 assign 指 令 的 等 號 左 邊, 則 不 需 要 是 暫 存 器 型 態 的 變 數, 也 可 以 是 線 路 型 態 的 變 數, 因 此 我 們 可 以 用 assign y=ty 這 樣 一 個 指 令 去 將 ty 的 暫 存 器 內 容 輸 出 事 實 上,assign 語 句 代 表 的 是 一 種 不 需 儲 存 的 立 即 輸 出 接 線, 因 此 我 們 才 能 將 output 型 態 的 變 數 寫 在 等 號 左 邊 啊! 完 整 的 ALU 設 計 ( 含 測 試 程 式 ) 瞭 解 了 這 些 Verilog 語 法 特 性 之 後, 我 們 就 可 以 搭 配 測 試 程 式, 對 這 個 ALU 模 組 進 行 測 試, 以 下 是 完 整 的 程 式 碼 : 檔 案 :alu.v // 輸 入 a, b 後 會 執 行 op 所 指 定 的 運 算, 然 後 將 結 果 放 在 暫 存 器 y 當 中 module alu(input [7:0] a, input [7:0] b, input [2:0] op, output reg [7:0
56 ] y); or b or op) begin // 當 a, b 或 op 有 改 變 時, 就 進 入 此 區 塊 執 行 case(op) // 根 據 op 決 定 要 執 行 何 種 運 算 3'b000: y = a + b; // op=000, 執 行 加 法 3'b001: y = a - b; // op=000, 執 行 減 法 3'b010: y = a * b; // op=000, 執 行 乘 法 3'b011: y = a / b; // op=000, 執 行 除 法 3'b100: y = a & b; // op=000, 執 行 AND 3'b101: y = a b; // op=000, 執 行 OR 3'b110: y = ~a; // op=000, 執 行 NOT 3'b111: y = a ^ b; // op=000, 執 行 XOR case $display("base 10 : %dns : op=%d a=%d b=%d y=%d", $stime, op, a, b, y); // 印 出 op, a, b, y 的 10 進 位 值 $display("base 2 : %dns : op=%b a=%b b=%b y=%b", $stime, op, a, b, y); // 印 出 op, a, b, y 的 2 進 位 值 module module main; reg [7:0] a, b; wire [7:0] y; reg [2:0] op; // 測 試 程 式 開 始 // 宣 告 a, b 為 8 位 元 暫 存 器 // 宣 告 y 為 8 位 元 線 路 // 宣 告 op 為 3 位 元 暫 存 器 alu alu1(a, b, op, y); // 建 立 一 個 alu 單 元, 名 稱 為 alu1 initial begin // 測 試 程 式 的 初 始 化 動 作 a = 8'h07; // 設 定 a 為 數 值 7 b = 8'h03; // 設 定 b 為 數 值 3 op = 3'b000; // 設 定 op 的 初 始 值 為 000 always #50 begin // 每 個 50 奈 秒 就 作 下 列 動 作 op = op + 1; // 讓 op 的 值 加 1 initial #1000 $finish; // 時 間 到 1000 奈 秒 就 結 束
57 module 在 上 述 程 式 中, 為 了 更 清 楚 的 印 出 ALU 的 輸 出 結 果, 我 們 在 ALU 模 組 的 結 尾 放 入 以 下 的 兩 行 $display() 指 令, 以 便 同 時 顯 示 (op, a, b, y) 等 變 數 的 10 進 位 與 2 進 位 結 果 值, 方 便 讀 者 觀 察 $display("base 10 : %dns : op=%d a=%d b=%d y=%d", $stime, op, a, b, y); // 印 出 op, a, b, y 的 10 進 位 值 $display("base 2 : %dns : op=%b a=%b b=%b y=%b", $stime, op, a, b, y); // 印 出 op, a, b, y 的 2 進 位 值 測 試 執 行 結 果 上 述 程 式 的 執 行 測 試 結 果 如 下 : D:\Dropbox\Public\pmag\201310\code>iverilog -o alu alu.v D:\Dropbox\Public\pmag\201310\code>vvp alu base 10 : 0ns : op=0 a= 7 b= 3 y= 10 base 2 : 0ns : op=000 a= b= y= base 10 : 50ns : op=1 a= 7 b= 3 y= 4 base 2 : 50ns : op=001 a= b= y= base 10 : 100ns : op=2 a= 7 b= 3 y= 21 base 2 : 100ns : op=010 a= b= y= base 10 : 150ns : op=3 a= 7 b= 3 y= 2 base 2 : 150ns : op=011 a= b= y= base 10 : 200ns : op=4 a= 7 b= 3 y= 3 base 2 : 200ns : op=100 a= b= y= base 10 : 250ns : op=5 a= 7 b= 3 y= 7 base 2 : 250ns : op=101 a= b= y= base 10 : 300ns : op=6 a= 7 b= 3 y=248 base 2 : 300ns : op=110 a= b= y= base 10 : 350ns : op=7 a= 7 b= 3 y= 4 base 2 : 350ns : op=111 a= b= y= base 10 : 400ns : op=0 a= 7 b= 3 y= 10 base 2 : 400ns : op=000 a= b= y= base 10 : 450ns : op=1 a= 7 b= 3 y= 4 base 2 : 450ns : op=001 a= b= y= base 10 : 500ns : op=2 a= 7 b= 3 y= 21
58 base 2 : 500ns : op=010 a= b= y= base 10 : 550ns : op=3 a= 7 b= 3 y= 2 base 2 : 550ns : op=011 a= b= y= base 10 : 600ns : op=4 a= 7 b= 3 y= 3 base 2 : 600ns : op=100 a= b= y= base 10 : 650ns : op=5 a= 7 b= 3 y= 7 base 2 : 650ns : op=101 a= b= y= base 10 : 700ns : op=6 a= 7 b= 3 y=248 base 2 : 700ns : op=110 a= b= y= base 10 : 750ns : op=7 a= 7 b= 3 y= 4 base 2 : 750ns : op=111 a= b= y= base 10 : 800ns : op=0 a= 7 b= 3 y= 10 base 2 : 800ns : op=000 a= b= y= base 10 : 850ns : op=1 a= 7 b= 3 y= 4 base 2 : 850ns : op=001 a= b= y= base 10 : 900ns : op=2 a= 7 b= 3 y= 21 base 2 : 900ns : op=010 a= b= y= base 10 : 950ns : op=3 a= 7 b= 3 y= 2 base 2 : 950ns : op=011 a= b= y= base 10 : 1000ns : op=4 a= 7 b= 3 y= 3 執 行 結 果 分 析 您 可 以 看 到 一 開 始 0ns 時,op=0, 所 以 執 行 加 法, 得 到 y=a+b=7+3=10, 然 後 50ns 時 op=1, 所 以 執 行 減 法, 以 下 是 整 個 執 行 結 果 的 簡 化 列 表 : a b op y (+) (-) (*) (/) (AND) (OR) (NOT) (XOR)
59 透 過 上 述 的 測 試, 我 們 知 道 整 個 ALU 的 設 計 方 式 是 正 確 的 結 語 對 於 沒 有 學 過 硬 體 描 述 語 言 的 人 來 說, 通 常 會 認 為 要 設 計 一 個 ALU 單 元, 應 該 是 很 複 雜 的 但 是 從 上 述 的 程 式 當 中, 您 可 以 看 到 在 Verilog 當 中 設 計 ALU 其 實 是 很 簡 單 的, 只 要 用 10 行 左 右 的 程 式 碼, 甚 至 不 需 要 自 己 設 計 加 法 器 就 能 完 成 這 是 因 為 Verilog 將 +, -, *, / 等 運 算 內 建 在 語 言 當 中 了, 所 以 讓 整 個 程 式 的 撰 寫 只 要 透 過 一 個 case 語 句 就 能 做 完 了, 這 種 設 計 方 式 非 常 的 像 高 階 語 言, 讓 硬 體 的 設 計 變 得 更 加 的 容 易 了 事 實 上, 在 使 用 Verilog 設 計 像 CPU 這 樣 的 複 雜 元 件 時,ALU 或 暫 存 器 等 單 元 都 變 得 非 常 的 容 易 真 正 複 雜 的 其 實 是 控 制 單 元, 而 這 也 是 CPU 設 計 的 精 髓 之 所 在, 我 們 會 在 開 放 電 腦 計 劃 系 列 的 文 章 中, 完 成 CPU 與 控 制 單 元 的 設 計 參 考 文 獻 陳 鍾 誠 的 網 站 : 用 Verilog 設 計 ALU
60 時 序 邏 輯 (Sequential Logic) 記 憶 單 元 (Memory Unit) 組 合 邏 輯 (Combinatorial Logic) 是 一 種 沒 有 回 饋 線 路 的 數 位 電 路 系 統, 而 循 序 邏 輯 ( 時 序 邏 輯, Sequential Logic) 則 是 一 種 包 含 回 饋 線 路 的 系 統 舉 例 而 言, 在 下 圖 (a) 的 全 加 器 的 電 路 裏, 您 可 以 看 到 從 輸 入 線 路 一 路 輸 入 接 向 輸 出, 這 種 稱 為 組 合 邏 輯 電 路 而 在 下 圖 (b) 的 栓 鎖 器 ( 正 反 器 ) 線 路 裏, 線 路 從 輸 出 Q 又 拉 回 S 做 為 輸 入, 這 種 有 倒 勾 的 線 路 就 稱 為 循 序 邏 輯 電 路 暫 存 器 靜 態 記 憶 體 等 記 憶 單 元, 都 是 由 這 種 有 反 饋 電 路 的 時 序 邏 輯 所 構 成 的, 因 此 要 瞭 解 記 憶 單 元 之 前, 先 瞭 解 時 序 邏 輯 的 電 路 結 構 會 是 有 幫 助 的 正 反 器 ( 閂 鎖 器 ) 正 反 器 有 很 多 種 型 式, 以 下 是 來 自 維 基 百 科 的 一 些 正 反 器 說 明 與 範 例 參 考 : 摘 自 維 基 百 科 : 正 反 器 ( 英 語 :Flip-flop, FF, 中 國 大 陸 譯 作 觸 發 器, 港 澳 譯 作 ), 學 名 雙 穩 態 多 諧 振 盪 器 (Bistable Multivibrator), 是 一 種 應 用 在 數 位 電 路 上 具 有 記 憶 功 能 的 循 序 邏 輯 元 件, 可 記 錄 二 進 位 制 數 位 訊 號 1 和 0 正 反 器 是 構 成 序 向 邏 輯 電 路 以 及 各 種 複 雜 數 位 系 統 的 基 本 邏 輯 單 元
61 圖 各 種 正 反 器 SR 正 反 器 正 反 器 是 可 以 用 來 儲 存 位 元, 是 循 序 電 路 的 基 礎, 以 下 是 一 個 用 NAND 閘 構 成 的 正 反 器 圖 NAND 閘 構 成 的 正 反 器 我 們 可 以 根 據 上 圖 實 作 出 對 應 的 Verilog 程 式 如 下 : 檔 案 :latch.v module latch(input Sbar, Rbar, output Q, Qbar); nand LS(Q, Sbar, Qbar); nand LR(Qbar, Rbar, Q); module module main; reg Sbar, Rbar; wire Q, Qbar;
62 latch latch1(sbar, Rbar, Q, Qbar); initial begin $monitor("%4dns monitor: Sbar=%d Rbar=%d Q=%d Qbar=%d", $stime, Sbar, R bar, Q, Qbar); $dumpfile("latch.vcd"); // 輸 出 給 GTK wave 顯 示 波 型 $dumpvars; always #50 begin Sbar = 0; Rbar = 1; #50; Sbar = 1; Rbar = 1; #50; Sbar = 1; Rbar = 0; #50; initial #500 $finish; module 執 行 結 果 : D:\verilog>iverilog -o latch latch.v D:\verilog>vvp latch VCD info: dumpfile latch.vcd opened for output. 0ns monitor: Sbar=x Rbar=x Q=x Qbar=x 50ns monitor: Sbar=0 Rbar=1 Q=1 Qbar=0 100ns monitor: Sbar=1 Rbar=1 Q=1 Qbar=0 150ns monitor: Sbar=1 Rbar=0 Q=0 Qbar=1 250ns monitor: Sbar=0 Rbar=1 Q=1 Qbar=0 300ns monitor: Sbar=1 Rbar=1 Q=1 Qbar=0 350ns monitor: Sbar=1 Rbar=0 Q=0 Qbar=1 450ns monitor: Sbar=0 Rbar=1 Q=1 Qbar=0 500ns monitor: Sbar=1 Rbar=1 Q=1 Qbar=0
63 圖 latch.vcd 的 顯 示 圖 形 有 enable 的 正 反 器 如 果 我 們 在 上 述 正 反 器 前 面 再 加 上 兩 個 NAND 閘 進 行 控 制, 就 可 以 形 成 一 組 有 enable 的 正 反 器, 以 下 是 該 正 反 器 的 圖 形 圖 有 enable 的 正 反 器 根 據 上 述 圖 形 我 們 可 以 設 計 出 以 下 的 Verilog 程 式 檔 案 :enlatch.v module latch(input Sbar, Rbar, output Q, Qbar); nand LS(Q, Sbar, Qbar); nand LR(Qbar, Rbar, Q); module module enlatch(input en, S, R, output Q, Qbar); nand ES(Senbar, en, S); nand ER(Renbar, en, R);
64 latch L1(Senbar, Renbar, Q, Qbar); module module main; reg S, en, R; wire Q, Qbar; enlatch enlatch1(en, S, R, Q, Qbar); initial begin $monitor("%4dns monitor: en=%d S=%d R=%d Q=%d Qbar=%d", $stime, en, S, R, Q, Qbar); $dumpfile("enlatch.vcd"); // 輸 出 給 GTK wave 顯 示 波 型 $dumpvars; always #50 begin en = 1; #50; S = 1; R = 0; #50; S = 0; R = 0; #50; S = 0; R = 1; #50 en = 0; #50; S = 1; R = 0; #50; S = 0; R = 0; #50; S = 0; R = 1; initial #1000 $finish;
65 module 執 行 結 果 D:\verilog>iverilog -o enlatch enlatch.v D:\verilog>vvp enlatch VCD info: dumpfile enlatch.vcd opened for output. 0ns monitor: en=x Sbar=x Rbar=x Q=x Qbar=x 50ns monitor: en=1 Sbar=x Rbar=x Q=x Qbar=x 100ns monitor: en=1 Sbar=1 Rbar=0 Q=1 Qbar=0 150ns monitor: en=1 Sbar=0 Rbar=0 Q=1 Qbar=0 200ns monitor: en=1 Sbar=0 Rbar=1 Q=0 Qbar=1 250ns monitor: en=0 Sbar=0 Rbar=1 Q=0 Qbar=1 300ns monitor: en=0 Sbar=1 Rbar=0 Q=0 Qbar=1 350ns monitor: en=0 Sbar=0 Rbar=0 Q=0 Qbar=1 400ns monitor: en=0 Sbar=0 Rbar=1 Q=0 Qbar=1 450ns monitor: en=1 Sbar=0 Rbar=1 Q=0 Qbar=1 500ns monitor: en=1 Sbar=1 Rbar=0 Q=1 Qbar=0 550ns monitor: en=1 Sbar=0 Rbar=0 Q=1 Qbar=0 600ns monitor: en=1 Sbar=0 Rbar=1 Q=0 Qbar=1 650ns monitor: en=0 Sbar=0 Rbar=1 Q=0 Qbar=1 700ns monitor: en=0 Sbar=1 Rbar=0 Q=0 Qbar=1 750ns monitor: en=0 Sbar=0 Rbar=0 Q=0 Qbar=1 800ns monitor: en=0 Sbar=0 Rbar=1 Q=0 Qbar=1 850ns monitor: en=1 Sbar=0 Rbar=1 Q=0 Qbar=1 900ns monitor: en=1 Sbar=1 Rbar=0 Q=1 Qbar=0 950ns monitor: en=1 Sbar=0 Rbar=0 Q=1 Qbar=0 1000ns monitor: en=1 Sbar=0 Rbar=1 Q=0 Qbar=1
66 圖 enlatch.vcd 的 顯 示 圖 形 閘 級 延 遲 (Gate Delay) 在 Verilog 模 型 下, 邏 輯 閘 預 設 是 沒 有 任 何 延 遲 的, 因 此 呈 現 出 來 永 遠 是 即 時 的 結 果, 但 現 實 世 界 的 電 路 總 是 有 少 許 延 遲 的, 每 經 過 一 個 閘 就 會 延 遲 一 點 點 的 時 間, 經 過 的 閘 數 越 多, 延 遲 也 就 會 越 久 參 考 : 為 了 模 擬 這 種 延 遲,Verilog 允 許 你 在 閘 上 面 附 加 延 遲 時 間 的 語 法, 您 可 以 分 別 指 定 最 小 延 遲 min, 典 型 延 遲 typical 與 最 大 延 遲 max 舉 例 而 言, 以 下 的 語 法 宣 告 了 一 個 not 閘, 其 中 的 #(1:3:5) 語 法 指 定 了 最 小 延 遲 min=1, 典 型 延 遲 typical=3, 最 大 延 遲 max=5 not #(1:3:5) n2(nclk2, clk); 假 如 您 不 想 分 別 指 定 這 三 種 延 遲, 也 可 以 只 指 定 一 個 延 遲 參 數, 這 樣 min, typical, max 三 者 都 會 設 定 為 該 數 值, 舉 例 而 言, 以 下 是 一 個 宣 告 延 遲 固 定 為 2 的 not 閘 not #2 n1(nclk1, clk); 為 了 說 明 這 種 延 遲 狀 況, 我 們 寫 了 一 個 範 例 程 式 delay.v 來 示 範 設 定 了 閘 級 延 遲 的 效 果, 請 參 考 下 列 程 式 : module main; reg clk; not #2 n1(nclk1, clk); not #(1:3:5) n2(nclk2, clk); initial begin
67 clk = 0; $monitor("%dns monitor: clk=%b nclk1=%d nclk2=%d", $stime, clk, nclk1, nclk2); $dumpfile("delay.vcd"); // 輸 出 給 GTK wave 顯 示 波 型 $dumpvars; always #10 begin clk = clk + 1; initial #100 $finish; module 執 行 結 果 : D:\Dropbox\Public\web\oc\code>iverilog -o delay delay.v delay.v:5: warning: choosing typ expression. D:\Dropbox\Public\web\oc\code>vvp delay VCD info: dumpfile delay.vcd opened for output. 0ns monitor: clk=0 nclk1=z nclk2=z 2ns monitor: clk=0 nclk1=1 nclk2=z 3ns monitor: clk=0 nclk1=1 nclk2=1 10ns monitor: clk=1 nclk1=1 nclk2=1 12ns monitor: clk=1 nclk1=0 nclk2=1 13ns monitor: clk=1 nclk1=0 nclk2=0 20ns monitor: clk=0 nclk1=0 nclk2=0 22ns monitor: clk=0 nclk1=1 nclk2=0 23ns monitor: clk=0 nclk1=1 nclk2=1 30ns monitor: clk=1 nclk1=1 nclk2=1 32ns monitor: clk=1 nclk1=0 nclk2=1 33ns monitor: clk=1 nclk1=0 nclk2=0 40ns monitor: clk=0 nclk1=0 nclk2=0 42ns monitor: clk=0 nclk1=1 nclk2=0 43ns monitor: clk=0 nclk1=1 nclk2=1 50ns monitor: clk=1 nclk1=1 nclk2=1
68 52ns monitor: clk=1 nclk1=0 nclk2=1 53ns monitor: clk=1 nclk1=0 nclk2=0 60ns monitor: clk=0 nclk1=0 nclk2=0 62ns monitor: clk=0 nclk1=1 nclk2=0 63ns monitor: clk=0 nclk1=1 nclk2=1 70ns monitor: clk=1 nclk1=1 nclk2=1 72ns monitor: clk=1 nclk1=0 nclk2=1 73ns monitor: clk=1 nclk1=0 nclk2=0 80ns monitor: clk=0 nclk1=0 nclk2=0 82ns monitor: clk=0 nclk1=1 nclk2=0 83ns monitor: clk=0 nclk1=1 nclk2=1 90ns monitor: clk=1 nclk1=1 nclk2=1 92ns monitor: clk=1 nclk1=0 nclk2=1 93ns monitor: clk=1 nclk1=0 nclk2=0 100ns monitor: clk=0 nclk1=0 nclk2=0 以 上 輸 出 的 波 形 如 下, 您 可 以 看 到 nclk1 的 延 遲 固 定 為 2, 而 nclk2 的 延 遲 則 介 於 1 到 5 之 間 圖 delay.vcd 的 顯 示 波 型 利 用 閘 級 延 遲 製 作 脈 波 變 化 偵 測 器 (Pulse Transition Detector, PTD) 雖 然 延 遲 現 象 看 起 來 像 是 個 缺 陷, 但 事 實 上 如 果 好 好 的 利 用 這 種 現 象, 有 時 反 而 可 以 達 到 很 好 的 效 果, 脈 波 變 化 偵 測 器 電 路 就 是 利 用 這 種 現 象 所 設 計 的 一 種 電 路, 可 以 用 來 偵 測 脈 波 的 上 升 邊 緣 或 下 降 邊 緣 以 下 是 脈 波 變 化 偵 測 電 路 的 圖 形, 其 中 的 關 鍵 是 在 左 邊 的 not 閘 身 上, 由 於 每 個 閘 都 會 造 成 延 遲, 因 此 多 了 not 閘 的 那 條 路 徑 所 造 成 的 延 遲 較 多, 這 讓 輸 出 部 份 會 因 為 延 遲 而 形 成 一 個 脈 衝 波 形
69 圖 脈 波 變 化 偵 測 器 以 下 是 這 個 電 路 以 Verilog 實 作 的 結 果 檔 案 :ptd.v module ptd(input clk, output ppulse); not #2 P1(nclkd, clk); nand #2 P2(npulse, nclkd, clk); not #2 P3(ppulse, npulse); module module main; reg clk; wire p; ptd ptd1(clk, p); initial begin clk = 0; $monitor("%dns monitor: clk=%b p=%d", $stime, clk, p); $dumpfile("ptd.vcd"); // 輸 出 給 GTK wave 顯 示 波 型 $dumpvars; always #50 begin clk = clk + 1; initial #500 $finish;
70 module 執 行 結 果 D:\Dropbox\Public\pmag\201311\code>iverilog -o ptd ptd.v D:\Dropbox\Public\pmag\201311\code>vvp ptd VCD info: dumpfile ptd.vcd opened for output. 0ns monitor: clk=0 p=z 4ns monitor: clk=0 p=0 50ns monitor: clk=1 p=0 54ns monitor: clk=1 p=1 56ns monitor: clk=1 p=0 100ns monitor: clk=0 p=0 150ns monitor: clk=1 p=0 154ns monitor: clk=1 p=1 156ns monitor: clk=1 p=0 200ns monitor: clk=0 p=0 250ns monitor: clk=1 p=0 254ns monitor: clk=1 p=1 256ns monitor: clk=1 p=0 300ns monitor: clk=0 p=0 350ns monitor: clk=1 p=0 354ns monitor: clk=1 p=1 356ns monitor: clk=1 p=0 400ns monitor: clk=0 p=0 450ns monitor: clk=1 p=0 454ns monitor: clk=1 p=1 456ns monitor: clk=1 p=0 500ns monitor: clk=0 p=0
71 圖 ptd.vcd 的 顯 示 圖 形 使 用 脈 衝 偵 測 電 路 製 作 邊 緣 觸 發 正 反 器 有 了 正 反 器 與 脈 波 變 化 偵 測 電 路 之 後, 我 們 就 可 以 組 合 出 邊 緣 觸 發 正 反 器 了, 以 下 是 其 電 路 圖 圖 邊 緣 觸 發 的 正 反 器 事 實 上, 上 述 電 路 圖 只 是 將 有 enable 的 正 反 器 前 面 加 上 一 個 脈 波 變 化 偵 測 電 路 而 已, 其 實 做 的 Verilog 程 式 如 下 檔 案 :ptdlatch.v module latch(input Sbar, Rbar, output Q, Qbar); nand LS(Q, Sbar, Qbar); nand LR(Qbar, Rbar, Q); module module enlatch(input en, S, R, output Q, Qbar);
72 nand ES(Senbar, en, S); nand ER(Renbar, en, R); latch L1(Senbar, Renbar, Q, Qbar); module module ptd(input clk, output ppulse); not #2 P1(nclkd, clk); nand #2 P2(npulse, nclkd, clk); not #2 P3(ppulse, npulse); module module ptdlatch(input clk, S, R, output Q, Qbar); ptd PTD(clk, ppulse); enlatch EL(ppulse, S, R, Q, Qbar); module module main; reg S, clk, R; wire Q, Qbar; ptdlatch ptdlatch1(clk, S, R, Q, Qbar); initial begin clk = 0; $monitor("%4dns monitor: clk=%d ppulse=%d S=%d R=%d Q=%d Qbar=%d", $sti me, clk, ptdlatch1.ppulse, S, R, Q, Qbar); $dumpfile("ptdlatch.vcd"); // 輸 出 給 GTK wave 顯 示 波 型 $dumpvars; always #20 begin clk = ~clk; always #50 begin S = 1; R = 0;
73 #50; S = 0; R = 0; #50; S = 0; R = 1; #50; initial #500 $finish; module 執 行 結 果 D:\verilog>iverilog -o ptdlatch ptdlatch.v D:\verilog>vvp ptdlatch VCD info: dumpfile ptdlatch.vcd opened for output. 0ns monitor: clk=0 ppulse=z S=x R=x Q=x Qbar=x 4ns monitor: clk=0 ppulse=0 S=x R=x Q=x Qbar=x 20ns monitor: clk=1 ppulse=0 S=x R=x Q=x Qbar=x 24ns monitor: clk=1 ppulse=1 S=x R=x Q=x Qbar=x 26ns monitor: clk=1 ppulse=0 S=x R=x Q=x Qbar=x 40ns monitor: clk=0 ppulse=0 S=x R=x Q=x Qbar=x 50ns monitor: clk=0 ppulse=0 S=1 R=0 Q=x Qbar=x 60ns monitor: clk=1 ppulse=0 S=1 R=0 Q=x Qbar=x 64ns monitor: clk=1 ppulse=1 S=1 R=0 Q=1 Qbar=0 66ns monitor: clk=1 ppulse=0 S=1 R=0 Q=1 Qbar=0 80ns monitor: clk=0 ppulse=0 S=1 R=0 Q=1 Qbar=0 100ns monitor: clk=1 ppulse=0 S=0 R=0 Q=1 Qbar=0 104ns monitor: clk=1 ppulse=1 S=0 R=0 Q=1 Qbar=0 106ns monitor: clk=1 ppulse=0 S=0 R=0 Q=1 Qbar=0 120ns monitor: clk=0 ppulse=0 S=0 R=0 Q=1 Qbar=0 140ns monitor: clk=1 ppulse=0 S=0 R=0 Q=1 Qbar=0 144ns monitor: clk=1 ppulse=1 S=0 R=0 Q=1 Qbar=0 146ns monitor: clk=1 ppulse=0 S=0 R=0 Q=1 Qbar=0 150ns monitor: clk=1 ppulse=0 S=0 R=1 Q=1 Qbar=0 160ns monitor: clk=0 ppulse=0 S=0 R=1 Q=1 Qbar=0 180ns monitor: clk=1 ppulse=0 S=0 R=1 Q=1 Qbar=0
74 184ns monitor: clk=1 ppulse=1 S=0 R=1 Q=0 Qbar=1 186ns monitor: clk=1 ppulse=0 S=0 R=1 Q=0 Qbar=1 200ns monitor: clk=0 ppulse=0 S=0 R=1 Q=0 Qbar=1 220ns monitor: clk=1 ppulse=0 S=0 R=1 Q=0 Qbar=1 224ns monitor: clk=1 ppulse=1 S=0 R=1 Q=0 Qbar=1 226ns monitor: clk=1 ppulse=0 S=0 R=1 Q=0 Qbar=1 240ns monitor: clk=0 ppulse=0 S=0 R=1 Q=0 Qbar=1 250ns monitor: clk=0 ppulse=0 S=1 R=0 Q=0 Qbar=1 260ns monitor: clk=1 ppulse=0 S=1 R=0 Q=0 Qbar=1 264ns monitor: clk=1 ppulse=1 S=1 R=0 Q=1 Qbar=0 266ns monitor: clk=1 ppulse=0 S=1 R=0 Q=1 Qbar=0 280ns monitor: clk=0 ppulse=0 S=1 R=0 Q=1 Qbar=0 300ns monitor: clk=1 ppulse=0 S=0 R=0 Q=1 Qbar=0 304ns monitor: clk=1 ppulse=1 S=0 R=0 Q=1 Qbar=0 306ns monitor: clk=1 ppulse=0 S=0 R=0 Q=1 Qbar=0 320ns monitor: clk=0 ppulse=0 S=0 R=0 Q=1 Qbar=0 340ns monitor: clk=1 ppulse=0 S=0 R=0 Q=1 Qbar=0 344ns monitor: clk=1 ppulse=1 S=0 R=0 Q=1 Qbar=0 346ns monitor: clk=1 ppulse=0 S=0 R=0 Q=1 Qbar=0 350ns monitor: clk=1 ppulse=0 S=0 R=1 Q=1 Qbar=0 360ns monitor: clk=0 ppulse=0 S=0 R=1 Q=1 Qbar=0 380ns monitor: clk=1 ppulse=0 S=0 R=1 Q=1 Qbar=0 384ns monitor: clk=1 ppulse=1 S=0 R=1 Q=0 Qbar=1 386ns monitor: clk=1 ppulse=0 S=0 R=1 Q=0 Qbar=1 400ns monitor: clk=0 ppulse=0 S=0 R=1 Q=0 Qbar=1 420ns monitor: clk=1 ppulse=0 S=0 R=1 Q=0 Qbar=1 424ns monitor: clk=1 ppulse=1 S=0 R=1 Q=0 Qbar=1 426ns monitor: clk=1 ppulse=0 S=0 R=1 Q=0 Qbar=1 440ns monitor: clk=0 ppulse=0 S=0 R=1 Q=0 Qbar=1 450ns monitor: clk=0 ppulse=0 S=1 R=0 Q=0 Qbar=1 460ns monitor: clk=1 ppulse=0 S=1 R=0 Q=0 Qbar=1 464ns monitor: clk=1 ppulse=1 S=1 R=0 Q=1 Qbar=0 466ns monitor: clk=1 ppulse=0 S=1 R=0 Q=1 Qbar=0 480ns monitor: clk=0 ppulse=0 S=1 R=0 Q=1 Qbar=0 500ns monitor: clk=1 ppulse=0 S=0 R=0 Q=1 Qbar=0
75 圖 ptdlatch.vcd 的 顯 示 圖 形 使 用 脈 衝 偵 測 電 路 設 計 邊 緣 觸 發 暫 存 器 有 了 脈 波 變 化 偵 測 電 路, 只 要 與 任 何 需 要 偵 測 脈 波 變 化 的 元 件 串 接 起 來, 就 可 以 達 到 邊 緣 觸 發 的 功 能 其 實 像 是 Verilog 當 中 的 以 下 程 式, 其 實 都 是 利 用 類 似 的 脈 波 變 化 偵 測 電 路 所 完 成 的 clock) begin... 如 果 我 們 真 的 不 想 使 用 posedge clock 這 種 語 法, 我 們 也 可 以 用 前 述 的 脈 波 變 化 偵 測 電 路 (PTD) 來 製 作 這 類 的 邊 緣 觸 發 功 能, 以 下 是 我 們 用 這 種 方 式 設 計 的 一 個 邊 緣 觸 發 暫 存 器 檔 案 : ptdregister.v module ptd(input clk, output ppulse); not #2 g1(nclkd, clk); nand #2 g2(npulse, nclkd, clk); not #2 g3(ppulse, npulse); module module register(input en, input [31:0] d, output reg [31:0] r); begin if (en)
76 r <= d; module module main; reg [31:0] d; wire [31:0] r; reg clk; wire en; ptd ptd1(clk, en); register register1(en, d, r); initial begin clk = 0; d = 3; $monitor("%4dns monitor: clk=%d en=%d d=%d r=%d", $stime, clk, en, d, r ); always #10 begin clk = clk + 1; always #20 begin d = d + 1; initial #100 $finish; module 執 行 結 果 D:\Dropbox\Public\web\oc\code>iverilog -o ptdregister ptdregister.v D:\Dropbox\Public\web\oc\code>vvp ptdregister 0ns monitor: clk=0 en=z d= 3 r= x
77 4ns monitor: clk=0 en=0 d= 3 r= x 10ns monitor: clk=1 en=0 d= 3 r= x 14ns monitor: clk=1 en=1 d= 3 r= 3 16ns monitor: clk=1 en=0 d= 3 r= 3 20ns monitor: clk=0 en=0 d= 4 r= 3 30ns monitor: clk=1 en=0 d= 4 r= 3 34ns monitor: clk=1 en=1 d= 4 r= 4 36ns monitor: clk=1 en=0 d= 4 r= 4 40ns monitor: clk=0 en=0 d= 5 r= 4 50ns monitor: clk=1 en=0 d= 5 r= 4 54ns monitor: clk=1 en=1 d= 5 r= 5 56ns monitor: clk=1 en=0 d= 5 r= 5 60ns monitor: clk=0 en=0 d= 6 r= 5 70ns monitor: clk=1 en=0 d= 6 r= 5 74ns monitor: clk=1 en=1 d= 6 r= 6 76ns monitor: clk=1 en=0 d= 6 r= 6 80ns monitor: clk=0 en=0 d= 7 r= 6 90ns monitor: clk=1 en=0 d= 7 r= 6 94ns monitor: clk=1 en=1 d= 7 r= 7 96ns monitor: clk=1 en=0 d= 7 r= 7 100ns monitor: clk=0 en=0 d= 8 r= 7 其 輸 出 的 波 型 檔 如 下 圖 所 示 : 圖 在 GTKWave 中 顯 示 的 ptdregister.vcd 波 型 檔 使 用 脈 衝 偵 測 電 路 製 作 計 數 電 路
78 如 果 我 們 將 暫 存 器 的 輸 出 在 接 到 一 個 加 法 電 路 上, 進 行 回 饋 性 的 累 加 的 動 作, 如 下 圖 所 示, 那 麼 整 個 電 路 就 會 變 成 一 個 邊 緣 觸 發 的 計 數 電 路 圖 邊 緣 觸 發 的 計 數 電 路 以 上 這 種 電 路 可 以 做 為 採 用 區 塊 方 法 設 計 CPU 的 基 礎, 因 為 CPU 當 中 的 程 式 計 數 器 (Program Counter) 通 常 會 採 用 這 種 邊 緣 觸 發 的 設 計 方 式 以 下 是 上 述 電 路 的 設 計 與 實 作 測 試 結 果 檔 案 : ptdcounter.v module register(input en, input [31:0] d, output reg [31:0] r); begin if (en) r <= d; module module ptd(input clk, output ppulse); not #2 P1(nclkd, clk); nand #2 P2(npulse, nclkd, clk); not #2 P3(ppulse, npulse); module module inc(input [31:0] i, output [31:0] o); assign o = i + 4; module module main; wire [31:0] r, ro; reg clk; wire en;
79 ptd ptd1(clk, en); register r1(en, ro, r); inc i1(r, ro); initial begin clk = 0; r1.r = 0; $monitor("%4dns monitor: clk=%d en=%d r=%d", $stime, clk, en, r); $dumpfile("ptdcounter.vcd"); // 輸 出 給 GTK wave 顯 示 波 型 $dumpvars; always #10 begin clk = clk + 1; initial #100 $finish; module 執 行 結 果 D:\Dropbox\Public\web\oc\code>iverilog -o ptdcounter ptdcounter.v D:\Dropbox\Public\web\oc\code>vvp ptdcounter VCD info: dumpfile ptdcounter.vcd opened for output. 0ns monitor: clk=0 en=z r= 0 4ns monitor: clk=0 en=0 r= 0 10ns monitor: clk=1 en=0 r= 0 14ns monitor: clk=1 en=1 r= 4 16ns monitor: clk=1 en=0 r= 4 20ns monitor: clk=0 en=0 r= 4 30ns monitor: clk=1 en=0 r= 4 34ns monitor: clk=1 en=1 r= 8 36ns monitor: clk=1 en=0 r= 8 40ns monitor: clk=0 en=0 r= 8 50ns monitor: clk=1 en=0 r= 8
80 54ns monitor: clk=1 en=1 r= 12 56ns monitor: clk=1 en=0 r= 12 60ns monitor: clk=0 en=0 r= 12 70ns monitor: clk=1 en=0 r= 12 74ns monitor: clk=1 en=1 r= 16 76ns monitor: clk=1 en=0 r= 16 80ns monitor: clk=0 en=0 r= 16 90ns monitor: clk=1 en=0 r= 16 94ns monitor: clk=1 en=1 r= 20 96ns monitor: clk=1 en=0 r= ns monitor: clk=0 en=0 r= 20 其 輸 出 的 波 型 檔 如 下 圖 所 示 : 圖 在 GTKWave 中 顯 示 的 ptdcounter.vcd 波 型 檔 暫 存 器 單 元 檔 案 :regbank.v module regbank(input [3:0] ra1, output [31:0] rd1, input [3:0] ra2, output [31:0] rd2, input clk, input w_en, input [3:0] wa, input [31:0] wd); reg [31:0] r[15:0]; // 宣 告 16 個 32 位 元 的 暫 存 器 assign rd1 = r[ra1]; // 讀 取 索 引 值 為 ra1 的 暫 存 器 assign rd2 = r[ra2]; // 讀 取 索 引 值 為 ra2 的 暫 存 器 clk)
81 begin if (w_en) // w_en=1 時 寫 入 到 暫 存 器 r[wa] <= wd; // 將 wd 寫 入 到 索 引 值 為 wa 的 暫 存 器 module module main; reg [3:0] ra1, ra2, wa; reg clk, w_en; wire [31:0] rd1, rd2; reg [31:0] wd; regbank rb0(ra1, rd1, ra2, rd2, clk, w_en, wa, wd); initial begin wa = 0; ra1 = 0; ra2 = 0; wd = 0; clk = 0; w_en = 1; initial #200 ra1 = 0; always #50 begin clk = clk + 1; $monitor("%4dns monitor: ra1=%d rd1=%d ra2=%d rd2=%d wa=%d wd=%d", $stime, ra1, rd1, ra2, rd2, wa, wd); always #100 begin wa = wa + 1; wd = wd + 2; ra1 = ra1 + 1; ra2 = ra2-1;
82 initial #1000 $finish; module 執 行 結 果 : D:\Dropbox\Public\web\oc\code\verilog>iverilog -o regbank regbank.v D:\Dropbox\Public\web\oc\code\verilog>vvp regbank 50ns monitor: ra1= 0 rd1= 0 ra2= 0 rd2= 0 wa= 0 wd= 0 100ns monitor: ra1= 1 rd1= x ra2=15 rd2= x wa= 1 wd= 2 150ns monitor: ra1= 1 rd1= 2 ra2=15 rd2= x wa= 1 wd= 2 200ns monitor: ra1= 1 rd1= 2 ra2=14 rd2= x wa= 2 wd= 4 250ns monitor: ra1= 1 rd1= 2 ra2=14 rd2= x wa= 2 wd= 4 300ns monitor: ra1= 2 rd1= 4 ra2=13 rd2= x wa= 3 wd= 6 350ns monitor: ra1= 2 rd1= 4 ra2=13 rd2= x wa= 3 wd= 6 400ns monitor: ra1= 3 rd1= 6 ra2=12 rd2= x wa= 4 wd= 8 450ns monitor: ra1= 3 rd1= 6 ra2=12 rd2= x wa= 4 wd= 8 500ns monitor: ra1= 4 rd1= 8 ra2=11 rd2= x wa= 5 wd= ns monitor: ra1= 4 rd1= 8 ra2=11 rd2= x wa= 5 wd= ns monitor: ra1= 5 rd1= 10 ra2=10 rd2= x wa= 6 wd= ns monitor: ra1= 5 rd1= 10 ra2=10 rd2= x wa= 6 wd= ns monitor: ra1= 6 rd1= 12 ra2= 9 rd2= x wa= 7 wd=
83 14 750ns monitor: ra1= 6 rd1= 12 ra2= 9 rd2= x wa= 7 wd= ns monitor: ra1= 7 rd1= 14 ra2= 8 rd2= x wa= 8 wd= ns monitor: ra1= 7 rd1= 14 ra2= 8 rd2= 16 wa= 8 wd= ns monitor: ra1= 8 rd1= 16 ra2= 7 rd2= 14 wa= 9 wd= ns monitor: ra1= 8 rd1= 16 ra2= 7 rd2= 14 wa= 9 wd= ns monitor: ra1= 9 rd1= 18 ra2= 6 rd2= 12 wa=10 wd= 20 記 憶 體 module memory(input clock, reset, en, rw, input [31:0] abus, input [31:0] dbus_in, output [31:0] db us_out); reg [7:0] m [0:128]; reg [31:0] data; or reset or abus or en or rw or dbus_in) begin if (reset == 1) begin {m[0],m[1],m[2],m[3]} = 32'h002F000C; // 0000 L D R2, K0 {m[4],m[5],m[6],m[7]} = 32'h001F000C; // 0004 L D R1, K1 {m[8],m[9],m[10],m[11]} = 32'h ; // 0008 LOOP: A DD R2, R2, R1 {m[12],m[13],m[14],m[15]} = 32'h26FFFFF8; // 000C J MP LOOP {m[16],m[17],m[18],m[19]} = 32'h ; // 0010 K0: WORD 0 {m[20],m[21],m[22],m[23]} = 32'h ; // 0014 K1: WORD 1
84 data = 32'hZZZZZZZZ; else if (abus >=0 && abus < 128) begin if (en == 1 && rw == 0) // r_w==0:write begin data = dbus_in; {m[abus], m[abus+1], m[abus+2], m[abus+3]} = dbus_in; else if (en == 1 && rw == 1) // r_w==1:read data = {m[abus], m[abus+1], m[abus+2], m[abus+3]}; else data = 32'hZZZZZZZZ; else data = 32'hZZZZZZZZ; assign dbus_out = data; module module main; reg clock, reset, en, rw; reg [31:0] addr; reg [31:0] data_in; wire [31:0] data_out; memory DUT (.clock(clock),.reset(reset),.en(en),.rw(rw),.abus(addr),.dbus_in(data_in),.dbus_out(data_out)); initial // reset: 設 定 memory 內 容 為 0,1,2,...,127 begin clock = 0; reset = 1; en = 0; rw = 1; // rw=1: 讀 取 模 式 #75; en = 1; reset = 0; addr = 0; #500;
85 addr = 4; rw = 0; // 寫 入 模 式 data_in = 8'h3A; #100; addr = 0; rw = 1; // 讀 取 模 式 data_in = 0; always #50 begin clock = clock + 1; $monitor("%4dns monitor: clk=%d en=%d rw=%d, addr=%8h din=%8h dout=%8h", $stime, clock, en, rw, addr, data_in, data_out); always #200 begin addr=addr+1; initial #2000 $finish; module 執 行 結 果 : D:\Dropbox\Public\web\oc\code\verilog>iverilog -o memory32 memory32.v D:\Dropbox\Public\web\oc\code\verilog>vvp memory32 50ns monitor: clk=1 en=0 rw=1, addr=xxxxxxxx din=xxxxxxxx dout=zzzzzzzz 75ns monitor: clk=1 en=1 rw=1, addr= din=xxxxxxxx dout=002f000c 100ns monitor: clk=0 en=1 rw=1, addr= din=xxxxxxxx dout=002f000c 150ns monitor: clk=1 en=1 rw=1, addr= din=xxxxxxxx dout=002f000c 200ns monitor: clk=0 en=1 rw=1, addr= din=xxxxxxxx dout=2f000c00 250ns monitor: clk=1 en=1 rw=1, addr= din=xxxxxxxx dout=2f000c00 300ns monitor: clk=0 en=1 rw=1, addr= din=xxxxxxxx dout=2f000c00 350ns monitor: clk=1 en=1 rw=1, addr= din=xxxxxxxx dout=2f000c00
86 400ns monitor: clk=0 en=1 rw=1, addr= din=xxxxxxxx dout=000c001f 450ns monitor: clk=1 en=1 rw=1, addr= din=xxxxxxxx dout=000c001f 500ns monitor: clk=0 en=1 rw=1, addr= din=xxxxxxxx dout=000c001f 550ns monitor: clk=1 en=1 rw=1, addr= din=xxxxxxxx dout=000c001f 575ns monitor: clk=1 en=1 rw=0, addr= din= a dout= a 600ns monitor: clk=0 en=1 rw=0, addr= din= a dout= a 650ns monitor: clk=1 en=1 rw=0, addr= din= a dout= a 675ns monitor: clk=1 en=1 rw=1, addr= din= dout=002f000c 700ns monitor: clk=0 en=1 rw=1, addr= din= dout=002f000c 750ns monitor: clk=1 en=1 rw=1, addr= din= dout=002f000c 800ns monitor: clk=0 en=1 rw=1, addr= din= dout=2f000c00 850ns monitor: clk=1 en=1 rw=1, addr= din= dout=2f000c00 900ns monitor: clk=0 en=1 rw=1, addr= din= dout=2f000c00 950ns monitor: clk=1 en=1 rw=1, addr= din= dout=2f000c ns monitor: clk=0 en=1 rw=1, addr= din= dout=000c ns monitor: clk=1 en=1 rw=1, addr= din= dout=000c ns monitor: clk=0 en=1 rw=1, addr= din= dout=000c ns monitor: clk=1 en=1 rw=1, addr= din= dout=000c ns monitor: clk=0 en=1 rw=1, addr= din= dout=0c ns monitor: clk=1 en=1 rw=1, addr= din= dout=0c ns monitor: clk=0 en=1 rw=1, addr= din= dout=0c ns monitor: clk=1 en=1 rw=1, addr= din= dout=0c ns monitor: clk=0 en=1 rw=1, addr= din= dout= ns monitor: clk=1 en=1 rw=1, addr= din= dout= ns monitor: clk=0 en=1 rw=1, addr= din= dout= ns monitor: clk=1 en=1 rw=1, addr= din= dout= ns monitor: clk=0 en=1 rw=1, addr= din= dout= a 1650ns monitor: clk=1 en=1 rw=1, addr= din= dout= a 1700ns monitor: clk=0 en=1 rw=1, addr= din= dout= a 1750ns monitor: clk=1 en=1 rw=1, addr= din= dout= a 1800ns monitor: clk=0 en=1 rw=1, addr= din= dout=00003a ns monitor: clk=1 en=1 rw=1, addr= din= dout=00003a ns monitor: clk=0 en=1 rw=1, addr= din= dout=00003a ns monitor: clk=1 en=1 rw=1, addr= din= dout=00003a ns monitor: clk=0 en=1 rw=1, addr= din= dout=003a2210 結 語
87 在 本 章 中, 我 們 介 紹 了 正 反 器 (Flip-Flop, Latch, 栓 鎖 器 ) 等 循 序 電 路 的 概 念, 並 且 利 用 閘 級 延 遲 的 現 象, 設 計 出 了 脈 衝 偵 測 電 路 (Pause Transition Detector, PTD), 於 是 我 們 可 以 利 用 脈 衝 偵 測 電 路 設 計 出 像 邊 緣 觸 發 型 的 電 路, 像 是 邊 緣 觸 發 型 的 正 反 器 暫 存 器 計 數 器 等 等 電 路, 這 些 電 路 是 構 成 電 腦 當 中 的 記 憶 線 路 的 基 礎 一 但 理 解 這 些 基 礎 原 理 之 後, 我 們 就 可 以 用 Verilog 的 高 階 語 法 直 接 宣 告 暫 存 器 一 群 暫 存 器 與 一 整 塊 記 憶 體, 這 種 高 階 寫 法 已 經 非 常 接 近 高 階 語 言 的 寫 法, 只 是 由 於 是 設 計 硬 體, 所 以 這 些 高 階 指 令 最 後 都 會 被 轉 換 為 線 路, 燒 錄 到 FPGA 或 內 建 於 ASIC 裡 面 而 已, 如 此 我 們 就 不 需 要 用 一 條 一 條 的 線 路 去 兜 出 暫 存 器 或 記 憶 體, 可 以 輕 鬆 的 透 過 Verilog 設 計 出 記 憶 單 元 了
88 控 制 單 元 簡 介 如 果 您 曾 經 用 硬 接 線 的 方 式 設 計 過 CPU, 那 就 會 發 現 控 制 單 元 主 要 就 是 一 堆 開 關 與 多 工 器 的 接 線 開 關 可 以 用 來 控 制 某 些 資 料 是 否 要 流 過, 而 多 工 器 則 可 以 從 很 多 組 輸 入 資 料 中 選 擇 一 組 輸 出, 以 下 是 一 個 四 選 一 多 工 器 的 方 塊 圖 圖 4 選 1 多 工 器 4 選 1 多 工 器 的 內 部 電 路 結 構 如 下 : 圖 4 選 1 多 工 器 的 內 部 電 路 接 著 就 讓 我 們 來 看 一 個 完 整 的 Verilog 的 4 選 1 的 多 工 器 程 式, 由 於 Verilog 支 援 像 Case 這 樣 的 高 階 語
89 法, 因 此 在 實 作 時 可 以 不 需 要 採 用 細 部 的 接 線 方 式, 只 要 使 用 case 語 句 就 可 以 輕 易 完 成 多 工 器 的 設 計 檔 案 :mux4.v module mux4(input[1:0] select, input[3:0] d, output reg q ); select or d ) begin case( select ) 0 : q = d[0]; 1 : q = d[1]; 2 : q = d[2]; 3 : q = d[3]; case module module main; reg [3:0] d; reg [1:0] s; wire q; mux4 DUT (s, d, q); initial begin s = 0; d = 4'b0110; always #50 begin s=s+1; $monitor("%4dns monitor: s=%d d=%d q=%d", $stime, s, d, q); initial #1000 $finish; module 執 行 結 果
90 D:\ccc101\icarus>iverilog mux4.v -o mux4 D:\ccc101\icarus>vvp mux4 50ns monitor: s=1 d= 6 q=1 100ns monitor: s=2 d= 6 q=1 150ns monitor: s=3 d= 6 q=0 200ns monitor: s=0 d= 6 q=0 250ns monitor: s=1 d= 6 q=1 300ns monitor: s=2 d= 6 q=1 350ns monitor: s=3 d= 6 q=0 400ns monitor: s=0 d= 6 q=0 450ns monitor: s=1 d= 6 q=1 500ns monitor: s=2 d= 6 q=1 550ns monitor: s=3 d= 6 q=0 600ns monitor: s=0 d= 6 q=0 650ns monitor: s=1 d= 6 q=1 700ns monitor: s=2 d= 6 q=1 750ns monitor: s=3 d= 6 q=0 800ns monitor: s=0 d= 6 q=0 850ns monitor: s=1 d= 6 q=1 900ns monitor: s=2 d= 6 q=1 950ns monitor: s=3 d= 6 q=0 1000ns monitor: s=0 d= 6 q=0 您 可 以 看 到 在 上 述 範 例 中, 輸 入 資 料 6 的 二 進 位 是 0110, 如 下 所 示 : 位 置 s 位 元 d 因 此 當 s=0 時 會 輸 出 0, s=1 時 會 輸 出 1, s=2 時 會 輸 出 1, s=3 時 會 輸 出 0, 這 就 是 上 述 輸 出 結 果 的 意 義 但 是 這 種 採 用 多 工 器 硬 的 接 線 方 式, 必 須 搭 配 區 塊 式 的 設 計, 才 能 建 構 出 CPU, 但 是 這 種 方 式 較 為 困 難, 因 此 我 們 留 待 後 續 章 節 再 來 介 紹 為 了 簡 單 起 見, 我 們 會 先 採 用 流 程 式 的 設 計 方 法 流 程 式 設 計 傳 統 上 當 您 設 計 出 ALU 暫 存 器 等 基 本 元 件 之 後, 就 可 以 設 計 控 制 單 元, 去 控 制 這 些 基 本 元 件, 形 成 一 顆 CPU 但 是 在 Verilog 當 中, +, -, *, /, 暫 存 器 等 都 是 基 本 語 法, 因 此 整 個 CPU 的 設 計 其 實 就 是 一 個 控 制 單 元 的 設 計 而 已, 我 們 只 要 在 適 當 的 時 候 呼 叫 +, -, *, / 運 算 與 暫 存 器 讀 取 寫 入 功 能, 就 能 設 計 完 一
91 顆 CPU 了 換 句 話 說, 只 要 在 Verilog 中 設 計 出 控 制 單 元, 基 本 上 就 已 經 設 計 完 成 整 顆 CPU 了, 因 為 +, -, *, /, 暫 存 器 等 元 件 都 已 經 內 建 了 以 下 是 我 們 用 流 程 法 設 計 mcu0 微 處 理 器 的 重 要 程 式 片 段, 您 可 以 看 到 在 這 種 作 法 上, 整 個 處 理 器 就 僅 僅 是 一 個 控 制 單 元, 而 這 個 控 制 單 元 的 責 任 就 是 根 據 擷 取 解 碼 執 行 的 流 程, 操 控 暫 存 器 的 流 向 與 運 算 module cpu(input clock);... clock) begin // 在 clock 時 脈 的 正 邊 緣 時 觸 發 IR = {m[pc], m[pc+1]}; // 指 令 擷 取 階 段 :IR=m[PC], 2 個 Byte 的 記 憶 體 pc0= PC; // 儲 存 舊 的 PC 值 在 pc0 中 PC = PC+2; // 擷 取 完 成,PC 前 進 到 下 一 個 指 令 位 址 case (`OP) // 解 碼 根 據 OP 執 行 動 作 LD: A = `M; // LD C ST: `M = A; // ST C CMP: begin `N=(A < `M); `Z=(A==`M); // CMP C ADD: A = A + `M; // ADD C JMP: PC = `C; // JMP C JEQ: if (`Z) PC=`C; // JEQ C... case // 印 出 PC, IR, SW, A 等 暫 存 器 值 以 供 觀 察 $display("%4dns PC=%x IR=%x, SW=%x, A=%d", $stime, pc0, IR, SW, A); module 區 塊 式 設 計 module mcu(input clock);... register#(.w(12)) PC(clock, 1, pci, pco); adder#(.w(12)) adder0(2, pco, pcnext); memory mem(mw, `C, ao, pco, ir, `C, mo); register#(.w(16)) A(~clock, aw, aluout, ao);
92 register#(.w(16)) SW(~clock, sww, aluout, swo); alu alu0(aluop, mo, ao, aluout); mux#(.w(12)) muxpc(pcmux, pcnext, `C, pci); control cu(`op, `Z, mw, aw, pcmux, sww, aluop);... module 以 流 程 法 設 計 控 制 單 元 然 而 當 指 令 愈 來 愈 多, 系 統 愈 來 愈 複 雜 時, 區 塊 式 的 設 計 方 法 就 會 愈 來 愈 困 難, 此 時 有 兩 種 解 決 方 式, 一 種 是 採 用 流 程 式 的 設 計 法 來 撰 寫 控 制 單 元, 操 控 各 種 開 關 與 多 工 器 這 種 設 計 方 法 混 合 了 區 塊 式 與 流 程 式 的 設 計 方 法, 算 是 一 種 折 衷 性 的 方 法 module control(input [3:0] op, input z, output mw, aw, pcmux, sww, outpu t [3:0] aluop); reg mw, aw, pcmux, sww; reg [3:0] aluop; begin mw = 0; aw = 0; sww = 0; pcmux = 0; aluop = alu0.zero; case (op) mcu0.ld: begin aw=1; aluop=alu0.apass; // LD C mcu0.st: mw=1; // ST C mcu0.jmp: pcmux=1; // JMP C mcu0.jeq: if (`Z) pcmux=1; // JEQ C mcu0.cmp: begin sww=1; aluop = alu0.cmp; // CMP C mcu0.add: begin aw=1; aluop=alu0.add; // ADD C case module 以 區 塊 法 設 計 控 制 單 元 當 然 我 們 也 可 以 將 上 述 的 控 制 訊 號 硬 是 用 and, or, not 等 方 式 寫 下 來, 這 樣 就 能 將 整 個 設 計 完 全 區 塊 化, 而 去 掉 流 程 式 的 寫 法 了 module control(input [3:0] op, input z, output mw, aw, pcmux, sww, outpu
93 t [3:0] aluop); assign mw=(op==mcu0.st); assign aw=(op==mcu0.ld op==mcu0.add); assign sww=(op==mcu0.cmp); assign pcmux=(op==mcu0.jmp (op==mcu0.jeq && z)); assign aluop=(op==mcu0.ld)?alu0.apass:(op==mcu0.cmp)?alu0.cmp:(op==mcu 0.ADD)?alu0.ADD:alu0.ZERO; module 以 微 指 令 設 計 控 制 單 元 另 一 種 可 以 克 服 區 塊 式 複 雜 度 問 題 的 方 法, 是 採 用 微 指 令 (microcode or microprogram) 的 設 計 方 法, 這 種 方 法 將 指 令 的 擷 取 (fetch) 解 碼 (decode) 執 行 (execute) 與 寫 回 (write-back) 等 分 成 T1, T2, T3, T4,... 等 子 步 驟, 然 後 用 一 個 微 型 計 數 器 mpc 控 制 這 些 子 步 驟 的 執 行, 如 下 圖 所 示 由 於 T1, T2, T3, T4 代 表 擷 取 (fetch) 解 碼 (decode) 執 行 (execute) 與 寫 回 (write-back), 每 個 步 驟 各 佔 用 一 個 Clock, 於 是 一 個 指 令 需 要 四 個 Clock 才 能 完 成, 因 此 我 們 可 以 用 以 下 方 法 將 各 個 開 關 與 多 工 器 的 控 制 編 為 一 個 表 格 T1 T2 T3 T4 C1 C2 C3... Ck 這 樣 就 可 以 很 有 系 統 的 運 用 區 塊 建 構 法 將 控 制 單 元 也 區 塊 化 了, 於 是 我 們 就 不 需 要 採 用 流 程 式 的 寫 法, 也 能 透 過 按 表 操 課 的 方 法 完 成 處 理 器 的 區 塊 式 建 構 了
94 微 處 理 器 (Micro Processor) 現 代 的 處 理 器 通 常 會 被 分 為 微 處 理 器 與 高 階 處 理 器 兩 類 微 處 理 器 指 的 是 能 力 較 弱, 通 常 指 令 長 度 較 短, 以 8 位 於 為 主, 少 數 為 16 位 元, 像 是 8051 AVR8 或 PIC 等 處 理 器, 這 些 處 理 器 通 常 不 會 搭 配 外 部 記 憶 體, 因 此 常 用 在 單 晶 片 或 者 嵌 入 式 系 統 當 中 而 高 階 處 理 器 則 是 能 力 較 強, 通 常 指 令 寬 度 較 大 (32 位 元 以 上 ), 像 是 Intel 的 x86 等 等, 高 階 的 ARM11 ARM Cortex 處 理 器 等 等, 這 些 處 理 器 的 定 址 空 間 很 大, 可 以 搭 配 容 量 很 大 的 記 憶 體 (ex: 4GB), 而 且 速 度 很 快, 因 此 需 要 內 建 記 憶 體 管 理 單 元 (Memory Management Unit, MMU) 與 多 層 快 取 機 制 (cache), 以 便 能 夠 充 分 發 揮 處 理 器 的 效 能 在 本 章 當 中, 我 們 將 透 過 mcu0 這 個 簡 易 的 架 構, 說 明 微 處 理 器 的 設 計 方 法 當 然 微 處 理 器 的 設 計 方 法 有 很 多 種, 在 本 章 中 我 們 將 展 示 兩 種 設 計 方 法, 一 種 是 流 程 式 的 設 計 法, 這 種 方 法 比 較 符 合 軟 體 程 式 人 的 設 計 習 慣, 寫 起 來 有 點 類 似 C 語 言 的 寫 法 另 一 種 是 區 塊 式 的 設 計 法, 這 種 方 法 是 傳 統 硬 體 人 的 設 計 方 法, 採 用 像 積 木 一 樣 的 方 式 由 下 往 上 拼 接 出 來, 然 後 再 透 過 線 路 連 接 各 個 區 塊 形 成 一 個 更 大 的 區 塊 MCU0 的 迷 你 版 -- mcu0m MCU0 處 理 器 MCU0 為 一 個 16 位 元 處 理 器, 包 含 指 令 暫 存 器 IR, 程 式 計 數 器 PC, 狀 態 佔 存 器 SW 與 累 積 器 A 等 四 個 暫 存 器 指 令 表 OP name 格 式 意 義 0 LD LD C A = [C] 1 ADD ADD C A = A + [C] 2 JMP JMP C PC = C 3 ST ST C [C] = A 4 CMP CMP C SW = A CMP [C] 5 JEQ JEQ C if SW[30]=Z=1 then PC = C 組 合 語 言 與 機 器 碼 00 LOOP: LD I CMP K10 401A
95 04 JEQ EXIT ADD K ST I A LD SUM C ADD I E ST SUM JMP LOOP EXIT: JMP EXIT SUM: WORD I: WORD K1: WORD A K10: WORD A 轉 成 Hex 輸 入 檔 格 式 : 檔 案 : mcu0m.hex // 00 LOOP: LD I 40 1A // 02 CMP K // 04 JEQ EXIT 實 作 // 06 ADD K // 08 ST I // 0A LD SUM // 0C ADD I // 0E ST SUM // 10 JMP LOOP // 12 EXIT: JMP EXIT // 14 SUM: WORD // 16 I: WORD // 18 K1: WORD A // 1A K10: WORD 10 Verilog 程 式 實 作 檔 案 : mcu0m.v `define N `define Z `define OP `define C SW[15] // 負 號 旗 標 SW[14] // 零 旗 標 IR[15:12] // 運 算 碼 IR[11:0] // 常 數 欄 位
96 `define M {m[`c], m[`c+1]} module cpu(input clock); // CPU0-Mini 的 快 取 版 :cpu0mc 模 組 parameter [3:0] LD=4'h0,ADD=4'h1,JMP=4'h2,ST=4'h3,CMP=4'h4,JEQ=4'h5; reg signed [15:0] A; // 宣 告 暫 存 器 R[0..15] 等 16 個 32 位 元 暫 存 器 reg [15:0] IR; // 指 令 暫 存 器 IR reg [15:0] SW; // 指 令 暫 存 器 IR reg [15:0] PC; // 程 式 計 數 器 reg [15:0] pc0; reg [7:0] m [0:32]; // 內 部 的 快 取 記 憶 體 integer i; initial // 初 始 化 begin PC = 0; // 將 PC 設 為 起 動 位 址 0 SW = 0; $readmemh("mcu0m.hex", m); for (i=0; i < 32; i=i+2) begin $display("%8x: %8x", i, {m[i], m[i+1]}); clock) begin // 在 clock 時 脈 的 正 邊 緣 時 觸 發 IR = {m[pc], m[pc+1]}; // 指 令 擷 取 階 段 :IR=m[PC], 2 個 Byte 的 記 憶 體 pc0= PC; // 儲 存 舊 的 PC 值 在 pc0 中 PC = PC+2; // 擷 取 完 成,PC 前 進 到 下 一 個 指 令 位 址 case (`OP) // 解 碼 根 據 OP 執 行 動 作 LD: A = `M; // LD C ST: `M = A; // ST C CMP: begin `N=(A < `M); `Z=(A==`M); // CMP C ADD: A = A + `M; // ADD C JMP: PC = `C; // JMP C JEQ: if (`Z) PC=`C; // JEQ C case // 印 出 PC, IR, SW, A 等 暫 存 器 值 以 供 觀 察 $display("%4dns PC=%x IR=%x, SW=%x, A=%d", $stime, pc0, IR, SW, A);
97 module module main; reg clock; // 測 試 程 式 開 始 // 時 脈 clock 變 數 cpu cpux(clock); // 宣 告 cpu0mc 處 理 器 initial clock = 0; // 一 開 始 clock 設 定 為 0 always #10 clock=~clock; // 每 隔 10ns 反 相, 時 脈 週 期 為 20ns initial #2000 $finish; // 在 2000 奈 秒 的 時 候 停 止 測 試 module 執 行 結 果 D:\Dropbox\Public\web\oc\code>iverilog -o mcu0m mcu0m.v D:\Dropbox\Public\web\oc\code>vvp cpu16m WARNING: cpu16m.v:20: $readmemh(cpu16m.hex): Not enough words in the file for th e requested range [0:32] : : 401a : : : a: c: e: : : : : : a: 000a c: xxxx e: xxxx 10ns PC=0000 IR=0016, SW=0000, A= 0
98 30ns PC=0002 IR=401a, SW=8000, A= 0 50ns PC=0004 IR=5012, SW=8000, A= 0 70ns PC=0006 IR=1018, SW=8000, A= 1 90ns PC=0008 IR=3016, SW=8000, A= 1 110ns PC=000a IR=0014, SW=8000, A= 0 130ns PC=000c IR=1016, SW=8000, A= 1 150ns PC=000e IR=3014, SW=8000, A= 1 170ns PC=0010 IR=2000, SW=8000, A= 1 190ns PC=0000 IR=0016, SW=8000, A= 1 210ns PC=0002 IR=401a, SW=8000, A= 1 230ns PC=0004 IR=5012, SW=8000, A= 1 250ns PC=0006 IR=1018, SW=8000, A= 2 270ns PC=0008 IR=3016, SW=8000, A= 2 290ns PC=000a IR=0014, SW=8000, A= 1 310ns PC=000c IR=1016, SW=8000, A= 3 330ns PC=000e IR=3014, SW=8000, A= 3 350ns PC=0010 IR=2000, SW=8000, A= 3 370ns PC=0000 IR=0016, SW=8000, A= 2 390ns PC=0002 IR=401a, SW=8000, A= 2 410ns PC=0004 IR=5012, SW=8000, A= 2 430ns PC=0006 IR=1018, SW=8000, A= 3 450ns PC=0008 IR=3016, SW=8000, A= 3 470ns PC=000a IR=0014, SW=8000, A= 3 490ns PC=000c IR=1016, SW=8000, A= 6 510ns PC=000e IR=3014, SW=8000, A= 6 530ns PC=0010 IR=2000, SW=8000, A= 6 550ns PC=0000 IR=0016, SW=8000, A= 3 570ns PC=0002 IR=401a, SW=8000, A= 3 590ns PC=0004 IR=5012, SW=8000, A= 3 610ns PC=0006 IR=1018, SW=8000, A= 4 630ns PC=0008 IR=3016, SW=8000, A= 4 650ns PC=000a IR=0014, SW=8000, A= 6 670ns PC=000c IR=1016, SW=8000, A= ns PC=000e IR=3014, SW=8000, A= ns PC=0010 IR=2000, SW=8000, A= ns PC=0000 IR=0016, SW=8000, A= 4 750ns PC=0002 IR=401a, SW=8000, A= 4
99 770ns PC=0004 IR=5012, SW=8000, A= 4 790ns PC=0006 IR=1018, SW=8000, A= 5 810ns PC=0008 IR=3016, SW=8000, A= 5 830ns PC=000a IR=0014, SW=8000, A= ns PC=000c IR=1016, SW=8000, A= ns PC=000e IR=3014, SW=8000, A= ns PC=0010 IR=2000, SW=8000, A= ns PC=0000 IR=0016, SW=8000, A= 5 930ns PC=0002 IR=401a, SW=8000, A= 5 950ns PC=0004 IR=5012, SW=8000, A= 5 970ns PC=0006 IR=1018, SW=8000, A= 6 990ns PC=0008 IR=3016, SW=8000, A= ns PC=000a IR=0014, SW=8000, A= ns PC=000c IR=1016, SW=8000, A= ns PC=000e IR=3014, SW=8000, A= ns PC=0010 IR=2000, SW=8000, A= ns PC=0000 IR=0016, SW=8000, A= ns PC=0002 IR=401a, SW=8000, A= ns PC=0004 IR=5012, SW=8000, A= ns PC=0006 IR=1018, SW=8000, A= ns PC=0008 IR=3016, SW=8000, A= ns PC=000a IR=0014, SW=8000, A= ns PC=000c IR=1016, SW=8000, A= ns PC=000e IR=3014, SW=8000, A= ns PC=0010 IR=2000, SW=8000, A= ns PC=0000 IR=0016, SW=8000, A= ns PC=0002 IR=401a, SW=8000, A= ns PC=0004 IR=5012, SW=8000, A= ns PC=0006 IR=1018, SW=8000, A= ns PC=0008 IR=3016, SW=8000, A= ns PC=000a IR=0014, SW=8000, A= ns PC=000c IR=1016, SW=8000, A= ns PC=000e IR=3014, SW=8000, A= ns PC=0010 IR=2000, SW=8000, A= ns PC=0000 IR=0016, SW=8000, A= ns PC=0002 IR=401a, SW=8000, A= ns PC=0004 IR=5012, SW=8000, A= 8
100 1510ns PC=0006 IR=1018, SW=8000, A= ns PC=0008 IR=3016, SW=8000, A= ns PC=000a IR=0014, SW=8000, A= ns PC=000c IR=1016, SW=8000, A= ns PC=000e IR=3014, SW=8000, A= ns PC=0010 IR=2000, SW=8000, A= ns PC=0000 IR=0016, SW=8000, A= ns PC=0002 IR=401a, SW=8000, A= ns PC=0004 IR=5012, SW=8000, A= ns PC=0006 IR=1018, SW=8000, A= ns PC=0008 IR=3016, SW=8000, A= ns PC=000a IR=0014, SW=8000, A= ns PC=000c IR=1016, SW=8000, A= ns PC=000e IR=3014, SW=8000, A= ns PC=0010 IR=2000, SW=8000, A= ns PC=0000 IR=0016, SW=8000, A= ns PC=0002 IR=401a, SW=4000, A= ns PC=0004 IR=5012, SW=4000, A= ns PC=0012 IR=2012, SW=4000, A= ns PC=0012 IR=2012, SW=4000, A= ns PC=0012 IR=2012, SW=4000, A= ns PC=0012 IR=2012, SW=4000, A= ns PC=0012 IR=2012, SW=4000, A= ns PC=0012 IR=2012, SW=4000, A= ns PC=0012 IR=2012, SW=4000, A= 10 MCU0 的 區 塊 式 設 計 -- MCU0bm.v 前 言 我 們 曾 經 在 下 列 文 章 中 設 計 出 了 MCU0 迷 你 版 這 個 只 有 六 個 指 令 的 微 控 制 器, 整 個 實 作 只 有 51 行 開 放 電 腦 計 畫 (6) 一 顆 只 有 51 行 Verilog 程 式 碼 的 16 位 元 處 理 器 MCU0 但 是 上 述 程 式 雖 然 簡 單, 但 卻 是 採 用 流 程 式 的 寫 法 雖 然 筆 者 不 覺 得 流 程 式 的 寫 法 有 甚 麼 特 別 的 缺 陷, 但 是 對 那 些 習 慣 採 用 硬 體 角 度 設 計 Verilog 程 式 的 人 而 言, 似 乎 採 用 區 塊 式 的 設 計 方 式 才 是 正 統, 所 以 筆 者 將 於 本 文 中 採 用 區 塊 式 的 方 式 重 新 設 計 MCU0 迷 你 版, 以 便 能 學 習 硬 體 設 計 者 的 思 考 方 式 MCU0 迷 你 版 的 指 令 表
101 為 了 方 便 讀 者 閱 讀, 不 需 要 查 閱 前 文, 我 們 再 次 列 出 了 MCU0 迷 你 版 的 指 令 表 如 下 : OP name 格 式 意 義 0 LD LD C A = [C] 1 ADD ADD C A = A + [C] 2 JMP JMP C PC = C 3 ST ST C [C] = A 4 CMP CMP C SW = A CMP [C] 5 JEQ JEQ C if SW[30]=Z=1 then PC = C MCU0 迷 你 版 的 區 塊 設 計 圖 在 MCU0 迷 你 版 裏, 總 共 有 三 個 暫 存 器, 分 別 是 A, PC 與 SW, 一 個 具 有 兩 組 讀 取 (i1/d1, i2/d2) 與 一 組 寫 入 的 記 憶 體 (wi/wd), 還 有 一 個 算 術 邏 輯 單 元 ALU, 這 個 電 路 的 設 計 圖 如 下 圖 MCU0bm 的 區 塊 設 計 圖 由 於 筆 者 不 熟 悉 數 位 電 路 設 計 的 繪 圖 軟 體, 因 此 就 簡 單 的 用 LibreOffice 的 Impress 繪 製 了 上 圖, 純 粹 採 用 區 塊 表 達 法, 並 沒 有 使 用 標 準 的 數 位 電 路 設 計 圖 示 原 始 碼 根 據 上 圖, 我 們 設 計 出 了 下 列 Verilog 程 式, 您 應 該 可 以 很 清 楚 的 找 出 程 式 與 圖 形 之 間 的 對 應 關 係 module memory(input w, input [11:0] wi, input [15:0] wd, input [11:0] i1
102 , output [15:0] d1, input [11:0] i2, output [15:0] d2); integer i; reg [7:0] m[0:2**12-1]; initial begin $readmemh("mcu0m.hex", m); for (i=0; i < 32; i=i+2) begin $display("%x: %x", i, {m[i], m[i+1]}); assign d1 = {m[i1], m[i1+1]}; assign d2 = {m[i2], m[i2+1]}; begin if (w) {m[wi], m[wi+1]} = wd; module module adder#(parameter W=16)(input [W-1:0] a, input [W-1:0] b, output [ W-1:0] c); assign c = a + b; module module register#(parameter W=16)(input clock, w, input [W-1:0] ri, outpu t [W-1:0] ro); reg [W-1:0] r; clock) begin if (w) r = ri; assign ro=r; module module alu(input [3:0] op, input [15:0] a, input [15:0] b, output reg [1 5:0] c); parameter [3:0] ZERO=4'h0, ADD=4'h1, CMP=4'he, APASS=4'hf; begin case (op) ADD: c = a+b; CMP: begin c[15]=(a < b); c[14]=(a==b); c[13:0]=14'h0;
103 APASS: c = a; default: c = 0; case module module mux#(parameter W=16)(input sel, input [W-1:0] i0, i1, output [W-1 :0] o); assign o=(sel)?i1:i0; module `define OP ir[15:12] `define C ir[11:0] `define N SW.r[15] `define Z SW.r[14] module control(input [3:0] op, input z, output mw, aw, pcmux, sww, outpu t [3:0] aluop); assign mw=(op==mcu0.st); assign aw=(op==mcu0.ld op==mcu0.add); assign sww=(op==mcu0.cmp); assign pcmux=(op==mcu0.jmp (op==mcu0.jeq && z)); assign aluop=(op==mcu0.ld)?alu0.apass:(op==mcu0.cmp)?alu0.cmp:(op==mcu 0.ADD)?alu0.ADD:alu0.ZERO; module module mcu(input clock); parameter [3:0] LD=4'h0,ADD=4'h1,JMP=4'h2,ST=4'h3,CMP=4'h4,JEQ=4'h5; wire mw, aw, pcmux, sww; wire [3:0] aluop; wire [11:0] pco, pci, pcnext; wire [15:0] aluout, ao, swo, ir, mo; register#(.w(12)) PC(clock, 1, pci, pco); adder#(.w(12)) adder0(2, pco, pcnext); memory mem(mw, `C, ao, pco, ir, `C, mo); register#(.w(16)) A(~clock, aw, aluout, ao);
104 register#(.w(16)) SW(~clock, sww, aluout, swo); alu alu0(aluop, mo, ao, aluout); mux#(.w(12)) muxpc(pcmux, pcnext, `C, pci); control cu(`op, `Z, mw, aw, pcmux, sww, aluop); initial begin PC.r = 0; SW.r = 0; module module main; reg clock; // 測 試 程 式 開 始 // 時 脈 clock 變 數 mcu mcu0(clock); initial begin clock = 0; $monitor("%4dns pc=%x ir=%x mo=%x sw=%x a=%d mw=%b aluout=%x", $stime, mcu0.pc.r, mcu0.ir, mcu0.mo, mcu0.sw.r, mcu0.a.r, mcu0.mw, mcu0.aluout); #1000 $finish; always #5 begin clock=~clock; // 每 隔 5ns 反 相, 時 脈 週 期 為 10ns module 輸 入 的 機 器 碼 mcu0m.hex 為 了 測 試 上 述 程 式, 我 們 同 樣 採 用 了 計 算 SUM= 的 這 個 程 式 作 為 輸 入, 以 下 是 機 器 碼 與 對 應 的 組 合 語 言 程 式 // 00 LOOP: LD I 40 1A // 02 CMP N // 04 JEQ EXIT // 06 ADD K // 08 ST I // 0A LD SUM // 0C ADD I // 0E ST SUM
105 20 00 // 10 JMP LOOP // 12 EXIT: JMP EXIT // 14 SUM: WORD // 16 I: WORD // 18 K1: WORD A // 1A N: WORD 10 執 行 結 果 編 寫 完 成 之 後, 我 們 就 可 以 測 試 整 個 mcu0bm.v 程 式 了, 其 執 行 結 果 如 下 所 示 D:\Dropbox\Public\web\co\code\mcu0>iverilog mcu0bm.v -o mcu0bm D:\Dropbox\Public\web\co\code\mcu0>vvp mcu0bm WARNING: mcu0bm.v:5: $readmemh(mcu0m.hex): Not enough words in the file f or the requested range [0:4095] : : 401a : : : a: c: e: : : : : : a: 000a c: xxxx e: xxxx 0ns pc=000 ir=0016 mo=0000 sw=0000 a= 0 mw=0 aluout=0000 5ns pc=002 ir=401a mo=000a sw=0000 a= 0 mw=0 aluout= ns pc=004 ir=5012 mo=2012 sw=0000 a= 0 mw=0 aluout= ns pc=006 ir=1018 mo=0001 sw=0000 a= 0 mw=0 aluout= ns pc=006 ir=1018 mo=0001 sw=0000 a= 1 mw=0 aluout=0002
106 35ns pc=008 ir=3016 mo=0001 sw=0000 a= 45ns pc=00a ir=0014 mo=0000 sw=0000 a= 50ns pc=00a ir=0014 mo=0000 sw=0000 a= 55ns pc=00c ir=1016 mo=0001 sw=0000 a= 60ns pc=00c ir=1016 mo=0001 sw=0000 a= 65ns pc=00e ir=3014 mo=0001 sw=0000 a= 75ns pc=010 ir=2000 mo=0016 sw=0000 a= 85ns pc=000 ir=0016 mo=0001 sw=0000 a= 95ns pc=002 ir=401a mo=000a sw=0000 a= 105ns pc=004 ir=5012 mo=2012 sw=0000 a= 115ns pc=006 ir=1018 mo=0001 sw=0000 a= 120ns pc=006 ir=1018 mo=0001 sw=0000 a= 125ns pc=008 ir=3016 mo=0002 sw=0000 a= 135ns pc=00a ir=0014 mo=0001 sw=0000 a= 140ns pc=00a ir=0014 mo=0001 sw=0000 a= 145ns pc=00c ir=1016 mo=0002 sw=0000 a= 150ns pc=00c ir=1016 mo=0002 sw=0000 a= 155ns pc=00e ir=3014 mo=0003 sw=0000 a= 165ns pc=010 ir=2000 mo=0016 sw=0000 a= 175ns pc=000 ir=0016 mo=0002 sw=0000 a= 180ns pc=000 ir=0016 mo=0002 sw=0000 a= 185ns pc=002 ir=401a mo=000a sw=0000 a= 195ns pc=004 ir=5012 mo=2012 sw=0000 a= 205ns pc=006 ir=1018 mo=0001 sw=0000 a= 210ns pc=006 ir=1018 mo=0001 sw=0000 a= 215ns pc=008 ir=3016 mo=0003 sw=0000 a= 225ns pc=00a ir=0014 mo=0003 sw=0000 a= 235ns pc=00c ir=1016 mo=0003 sw=0000 a= 240ns pc=00c ir=1016 mo=0003 sw=0000 a= 245ns pc=00e ir=3014 mo=0006 sw=0000 a= 255ns pc=010 ir=2000 mo=0016 sw=0000 a= 265ns pc=000 ir=0016 mo=0003 sw=0000 a= 270ns pc=000 ir=0016 mo=0003 sw=0000 a= 275ns pc=002 ir=401a mo=000a sw=0000 a= 285ns pc=004 ir=5012 mo=2012 sw=0000 a= 295ns pc=006 ir=1018 mo=0001 sw=0000 a= 300ns pc=006 ir=1018 mo=0001 sw=0000 a= 1 mw=1 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=1 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=1 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=1 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=1 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=1 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout=0005
107 305ns pc=008 ir=3016 mo=0004 sw=0000 a= 315ns pc=00a ir=0014 mo=0006 sw=0000 a= 320ns pc=00a ir=0014 mo=0006 sw=0000 a= 325ns pc=00c ir=1016 mo=0004 sw=0000 a= 330ns pc=00c ir=1016 mo=0004 sw=0000 a= 335ns pc=00e ir=3014 mo=000a sw=0000 a= 345ns pc=010 ir=2000 mo=0016 sw=0000 a= 355ns pc=000 ir=0016 mo=0004 sw=0000 a= 360ns pc=000 ir=0016 mo=0004 sw=0000 a= 365ns pc=002 ir=401a mo=000a sw=0000 a= 375ns pc=004 ir=5012 mo=2012 sw=0000 a= 385ns pc=006 ir=1018 mo=0001 sw=0000 a= 390ns pc=006 ir=1018 mo=0001 sw=0000 a= 395ns pc=008 ir=3016 mo=0005 sw=0000 a= 405ns pc=00a ir=0014 mo=000a sw=0000 a= 410ns pc=00a ir=0014 mo=000a sw=0000 a= 415ns pc=00c ir=1016 mo=0005 sw=0000 a= 420ns pc=00c ir=1016 mo=0005 sw=0000 a= 425ns pc=00e ir=3014 mo=000f sw=0000 a= 435ns pc=010 ir=2000 mo=0016 sw=0000 a= 445ns pc=000 ir=0016 mo=0005 sw=0000 a= 450ns pc=000 ir=0016 mo=0005 sw=0000 a= 455ns pc=002 ir=401a mo=000a sw=0000 a= 465ns pc=004 ir=5012 mo=2012 sw=0000 a= 475ns pc=006 ir=1018 mo=0001 sw=0000 a= 480ns pc=006 ir=1018 mo=0001 sw=0000 a= 485ns pc=008 ir=3016 mo=0006 sw=0000 a= 495ns pc=00a ir=0014 mo=000f sw=0000 a= 500ns pc=00a ir=0014 mo=000f sw=0000 a= 505ns pc=00c ir=1016 mo=0006 sw=0000 a= 510ns pc=00c ir=1016 mo=0006 sw=0000 a= 515ns pc=00e ir=3014 mo=0015 sw=0000 a= 525ns pc=010 ir=2000 mo=0016 sw=0000 a= 535ns pc=000 ir=0016 mo=0006 sw=0000 a= 540ns pc=000 ir=0016 mo=0006 sw=0000 a= 545ns pc=002 ir=401a mo=000a sw=0000 a= 555ns pc=004 ir=5012 mo=2012 sw=0000 a= 4 mw=1 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout=000a 10 mw=0 aluout=000e 10 mw=1 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=1 aluout= mw=0 aluout=000a 10 mw=0 aluout=000a 10 mw=0 aluout=000f 15 mw=0 aluout= mw=1 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=1 aluout= mw=0 aluout=000f 15 mw=0 aluout=000f 15 mw=0 aluout= mw=0 aluout=001b 21 mw=1 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout=0000
108 565ns pc=006 ir=1018 mo=0001 sw=0000 a= 570ns pc=006 ir=1018 mo=0001 sw=0000 a= 575ns pc=008 ir=3016 mo=0007 sw=0000 a= 585ns pc=00a ir=0014 mo=0015 sw=0000 a= 590ns pc=00a ir=0014 mo=0015 sw=0000 a= 595ns pc=00c ir=1016 mo=0007 sw=0000 a= 600ns pc=00c ir=1016 mo=0007 sw=0000 a= 605ns pc=00e ir=3014 mo=001c sw=0000 a= 615ns pc=010 ir=2000 mo=0016 sw=0000 a= 625ns pc=000 ir=0016 mo=0007 sw=0000 a= 630ns pc=000 ir=0016 mo=0007 sw=0000 a= 635ns pc=002 ir=401a mo=000a sw=0000 a= 645ns pc=004 ir=5012 mo=2012 sw=0000 a= 655ns pc=006 ir=1018 mo=0001 sw=0000 a= 660ns pc=006 ir=1018 mo=0001 sw=0000 a= 665ns pc=008 ir=3016 mo=0008 sw=0000 a= 675ns pc=00a ir=0014 mo=001c sw=0000 a= 680ns pc=00a ir=0014 mo=001c sw=0000 a= 685ns pc=00c ir=1016 mo=0008 sw=0000 a= 690ns pc=00c ir=1016 mo=0008 sw=0000 a= 695ns pc=00e ir=3014 mo=0024 sw=0000 a= 705ns pc=010 ir=2000 mo=0016 sw=0000 a= 715ns pc=000 ir=0016 mo=0008 sw=0000 a= 720ns pc=000 ir=0016 mo=0008 sw=0000 a= 725ns pc=002 ir=401a mo=000a sw=0000 a= 735ns pc=004 ir=5012 mo=2012 sw=0000 a= 745ns pc=006 ir=1018 mo=0001 sw=0000 a= 750ns pc=006 ir=1018 mo=0001 sw=0000 a= 755ns pc=008 ir=3016 mo=0009 sw=0000 a= 765ns pc=00a ir=0014 mo=0024 sw=0000 a= 770ns pc=00a ir=0014 mo=0024 sw=0000 a= 775ns pc=00c ir=1016 mo=0009 sw=0000 a= 780ns pc=00c ir=1016 mo=0009 sw=0000 a= 785ns pc=00e ir=3014 mo=002d sw=0000 a= 795ns pc=010 ir=2000 mo=0016 sw=0000 a= 805ns pc=000 ir=0016 mo=0009 sw=0000 a= 810ns pc=000 ir=0016 mo=0009 sw=0000 a= 6 mw=0 aluout= mw=0 aluout= mw=1 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout=001c 28 mw=0 aluout= mw=1 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=1 aluout= mw=0 aluout=001c 28 mw=0 aluout=001c 28 mw=0 aluout= mw=0 aluout=002c 36 mw=1 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout=000a 9 mw=1 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout=002d 45 mw=0 aluout= mw=1 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout=0009
109 815ns pc=002 ir=401a mo=000a sw=0000 a= 825ns pc=004 ir=5012 mo=2012 sw=0000 a= 835ns pc=006 ir=1018 mo=0001 sw=0000 a= 840ns pc=006 ir=1018 mo=0001 sw=0000 a= 845ns pc=008 ir=3016 mo=000a sw=0000 a= 855ns pc=00a ir=0014 mo=002d sw=0000 a= 860ns pc=00a ir=0014 mo=002d sw=0000 a= 865ns pc=00c ir=1016 mo=000a sw=0000 a= 870ns pc=00c ir=1016 mo=000a sw=0000 a= 875ns pc=00e ir=3014 mo=0037 sw=0000 a= 885ns pc=010 ir=2000 mo=0016 sw=0000 a= 895ns pc=000 ir=0016 mo=000a sw=0000 a= 900ns pc=000 ir=0016 mo=000a sw=0000 a= 905ns pc=002 ir=401a mo=000a sw=0000 a= 910ns pc=002 ir=401a mo=000a sw=4000 a= 915ns pc=004 ir=5012 mo=2012 sw=4000 a= 925ns pc=012 ir=2012 mo=2012 sw=4000 a= 9 mw=0 aluout= mw=0 aluout= mw=0 aluout=000a 10 mw=0 aluout=000b 10 mw=1 aluout= mw=0 aluout=002d 45 mw=0 aluout=002d 45 mw=0 aluout= mw=0 aluout= mw=1 aluout= mw=0 aluout= mw=0 aluout=000a 10 mw=0 aluout=000a 10 mw=0 aluout= mw=0 aluout= mw=0 aluout= mw=0 aluout=0000 您 可 以 清 楚 的 看 到, 該 程 式 在 870ns 時 計 算 出 了 總 合 SUM=55 的 結 果, 這 代 表 mcu0bm.v 的 設 計 完 成 了 計 算 的 功 能 結 語 在 上 述 實 作 中, 採 用 區 塊 式 設 計 的 mcu0bm.v 總 共 有 98 行, 比 起 同 樣 功 能 的 流 程 式 設 計 mcu0m.v 的 51 行 多 了 將 近 一 倍, 而 且 程 式 的 設 計 難 度 感 覺 高 了 不 少, 但 是 我 們 可 以 很 清 楚 的 掌 握 到 整 個 設 計 的 硬 體 結 構, 這 是 採 用 流 程 式 設 計 所 難 以 確 定 的 當 然 由 於 筆 者 是 程 式 人 員, 並 非 硬 體 設 計 人 員, 因 此 比 較 喜 歡 採 用 流 程 式 的 設 計 方 式 不 過 採 用 了 區 塊 式 設 計 法 設 計 出 mcu0bm.v 之 後, 也 逐 漸 開 始 能 理 解 這 種 硬 體 導 向 的 設 計 方 式, 這 大 概 是 我 在 撰 寫 本 程 式 時 最 大 的 收 穫 了 MCU0 完 整 版 MCU0 的 架 構 MCU0 是 一 顆 16 位 元 的 CPU, 所 有 暫 存 器 都 是 16 位 元 的, 總 共 有 (IR, SP, LR, SW, PC, A) 等 暫 存 器, 如 下 所 示 : `define A R[0] // 累 積 器 `define LR R[1] // 狀 態 暫 存 器 `define SW R[2] // 狀 態 暫 存 器 `define SP R[3] // 堆 疊 暫 存 器
110 `define PC R[4] // 程 式 計 數 器 這 些 暫 存 器 的 功 能 與 說 明 如 下 : 暫 存 器 名 稱 IR 功 能 指 令 暫 存 器 說 明 用 來 儲 存 從 記 憶 體 載 入 的 機 器 碼 指 令 A =R[0] 累 積 器 用 來 儲 存 計 算 的 結 果, 像 是 加 減 法 的 結 果 LR=R[1] SW=R[2] SP=R[3] PC=R[4] 連 結 暫 存 器 狀 態 暫 存 器 堆 疊 暫 存 器 程 式 計 數 器 用 來 儲 存 函 數 呼 叫 的 返 回 位 址 用 來 儲 存 CMP 比 較 指 令 的 結 果 旗 標, 像 是 負 旗 標 N 與 零 旗 標 Z 等 作 為 條 件 跳 躍 JEQ 等 指 令 是 否 跳 躍 的 判 斷 依 據 堆 疊 指 標,PUSH, POP 指 令 會 用 到 用 來 儲 存 指 令 的 位 址 ( 也 就 是 目 前 執 行 到 哪 個 指 令 的 記 憶 體 位 址 ) MCU0 的 指 令 表 指 令 暫 存 器 IR 的 前 4 個 位 元 是 指 令 代 碼 OP, 由 於 4 位 元 只 能 表 達 16 種 指 令, 這 數 量 太 少 不 敷 使 用, 因 此 當 OP=0xF 時, 我 們 繼 續 用 後 面 的 位 元 作 為 延 伸 代 碼, 以 便 有 更 多 的 指 令 可 以 使 用, 以 下 是 MCU0 微 控 制 器 的 完 整 指 令 表 代 碼 名 稱 格 式 說 明 語 意 0 LD LD C 載 入 A = [C] 1 ST ST C 儲 存 [C] = A 2 ADD ADD C 加 法 A = A + [C] 3 SUB SUB C 減 法 A = A - [C] 4 MUL MUL C 乘 法 A = A * [C] 5 DIV DIV C 除 法 A = A / [C] 6 AND AND C 位 元 AND 運 算 A = A & [C]
111 7 OR OR C 8 XOR XOR C 位 元 OR 運 算 位 元 XOR 運 算 A = A [C] A = A ^ [C] 9 CMP CMP C 比 較 SW = A CMP [C] ; N=(A<[C]), Z=(A==[C]) A JMP JMP C 跳 躍 PC = C B JEQ JEQ C C JLT JLT C D JLE JLE C E CALL CALL C 相 等 時 跳 躍 小 於 時 跳 躍 小 於 或 等 於 時 跳 躍 呼 叫 副 程 式 if Z then PC = C if N then PC = C if Z or N then PC = C LR=PC; PC = C F OP8 OP 為 8 位 元 的 運 算 F0 LDI LDI Ra,C4 載 入 常 數 Ra=C4 F2 MOV MOV Ra,Rb 暫 存 器 移 動 Ra=Rb F3 PUSH PUSH Ra 堆 疊 推 入 SP--; [SP] = Ra F4 POP POP Ra 堆 疊 取 出 Ra=[SP]; SP++; F5 SHL SHL Ra,C4 左 移 Ra = Ra << C4 F6 SHR SHL Ra,C4 右 移 Ra = Ra >> C4 F7 ADDI ADDI Ra,C4 常 數 加 法 Ra = Ra + C4 SUBI
112 F8 SUBI Ra,C4 常 數 減 法 Ra = Ra - C4 F9 NEG NEG Ra 反 相 Ra = ~Ra FA SWI SWI C 軟 體 中 斷 BIOS 中 斷 呼 叫 FD NSW NSW 狀 態 反 相 N=~N, Z=~Z; 由 於 沒 有 JGE, JGT, JNE, 因 此 可 用 此 指 令 將 SW 反 相, 再 用 JLE, JLT, JEQ 完 成 跳 躍 動 作 FE RET RET 返 回 PC = LR FF IRET IRET 從 中 斷 返 回 PC = LR; I=0; mcu0 程 式 碼 檔 案 :mcu0s.v `define OP IR[15:12] // 運 算 碼 `define C IR[11:0] // 常 數 欄 位 `define SC8 $signed(ir[7:0]) // 常 數 欄 位 `define C4 IR[3:0] // 常 數 欄 位 `define Ra IR[7:4] // Ra `define Rb IR[3:0] // Rb `define A R[0] // 累 積 器 `define LR R[1] // 狀 態 暫 存 器 `define SW R[2] // 狀 態 暫 存 器 `define SP R[3] // 堆 疊 暫 存 器 `define PC R[4] // 程 式 計 數 器 `define N `SW[15] // 負 號 旗 標 `define Z `SW[14] // 零 旗 標 `define I `SW[3] // 是 否 中 斷 中 `define M m[`c] // 存 取 記 憶 體 module cpu(input clock); // CPU0-Mini 的 快 取 版 :cpu0mc 模 組 parameter [3:0] LD=4'h0,ST=4'h1,ADD=4'h2,SUB=4'h3,MUL=4'h4,DIV=4'h5,AND =4'h6,OR=4'h7,XOR=4'h8,CMP=4'h9,JMP=4'hA,JEQ=4'hB, JLT=4'hC, JLE=4'hD, JS UB=4'hE, OP8=4'hF; parameter [3:0] LDI=4'h0, MOV=4'h2, PUSH=4'h3, POP=4'h4, SHL=4'h5, SHR= 4'h6, ADDI=4'h7, SUBI=4'h8, NEG=4'h9, SWI=4'hA, NSW=4'hD, RET=4'hE, IRET=
113 4'hF; reg [15:0] IR; // 指 令 暫 存 器 reg signed [15:0] R[0:4]; reg signed [15:0] pc0; reg signed [15:0] m [0:4096]; // 內 部 的 快 取 記 憶 體 integer i; initial // 初 始 化 begin `PC = 0; // 將 PC 設 為 起 動 位 址 0 `SW = 0; $readmemh("mcu0s.hex", m); clock) begin // 在 clock 時 脈 的 正 邊 緣 時 觸 發 IR = m[`pc]; // 指 令 擷 取 階 段 :IR=m[PC], 2 個 Byte 的 記 憶 體 pc0= `PC; // 儲 存 舊 的 PC 值 在 pc0 中 `PC = `PC+1; // 擷 取 完 成,PC 前 進 到 下 一 個 指 令 位 址 case (`OP) // 解 碼 根 據 OP 執 行 動 作 LD: `A = `M; // LD C ST: `M = `A; // ST C ADD: `A = `A + `M; // ADD C SUB: `A = `A - `M; // SUB C MUL: `A = `A * `M; // MUL C DIV: `A = `A / `M; // DIV C AND: `A = `A & `M; // AND C OR : `A = `A `M; // OR C XOR: `A = `A ^ `M; // XOR C CMP: begin `N=(`A < `M); `Z=(`A==`M); // CMP C JMP: `PC = `C; // JSUB C JEQ: if (`Z) `PC=`C; // JEQ C JLT: if (`N) `PC=`C; // JLT C JLE: if (`N `Z) `PC=`C;// JLE C JSUB:begin `LR = `PC; `PC = `C; // JSUB C OP8: case (IR[11:8]) // OP8: 加 長 運 算 碼 LDI: R[`Ra] = `C4; // LDI C ADDI: R[`Ra] = R[`Ra] + `C4; // ADDI C
114 SUBI: R[`Ra] = R[`Ra] - `C4; // ADDI C MOV: R[`Ra] = R[`Rb]; // MOV Ra, Rb PUSH: begin `SP=`SP-1; m[`sp] = R[`Ra]; // PUSH Ra POP: begin R[`Ra] = m[`sp]; `SP=`SP+1; // POP Ra SHL: R[`Ra] = R[`Ra] << `C4; // SHL C SHR: R[`Ra] = R[`Ra] >> `C4; // SHR C SWI: $display("swi C8=%d A=%d", `SC8, `A); // SWI C NEG: R[`Ra] = ~R[`Ra]; // NEG Ra NSW: begin `N=~`N; `Z=~`Z; // NSW (negate N, Z ) RET: `PC = `LR; // RET IRET: begin `PC = `LR; `I = 0; // IRET default: $display("op8=%d, not defined!", IR[11:8]); case case // 印 出 PC, IR, SW, A 等 暫 存 器 值 以 供 觀 察 $display("%4dns PC=%x IR=%x, SW=%x, A=%d SP=%x LR=%x", $stime, pc0, I R, `SW, `A, `SP, `LR); module module main; reg clock; // 測 試 程 式 開 始 // 時 脈 clock 變 數 cpu mcu0(clock); // 宣 告 mcu0 處 理 器 initial clock = 0; // 一 開 始 clock 設 定 為 0 always #10 clock=~clock; // 每 隔 10ns 反 相, 時 脈 週 期 為 20ns initial #1000 $finish; // 停 止 測 試 module 組 合 語 言 檔 案 :mcu0s.hex 0020 // 00 RESET: LD X 2021 // 01 ADD Y
115 3021 // 02 SUB Y 4021 // 03 MUL Y 5021 // 04 DIV Y 7021 // 05 OR Y 6021 // 06 AND Y 8021 // 07 XOR Y 0020 // 08 LD X F503 // 09 SHL A, 3 F603 // 0A SHR A, 3 F701 // 0B ADDI // 0C LD STACKEND F230 // 0D MOV SP, A E011 // 0E JSUB MIN 0022 // 0F LD Z A010 // 10 HALT: JMP HALT F301 // 11 MIN: PUSH LR 0020 // 12 LD X 9021 // 13 CMP Y FD00 // 14 NSW C018 // 15 JLT ELSE 1022 // 16 ST Z A019 // 17 JMP NEXT 0021 // 18 ELSE: LD Y 1022 // 19 NEXT: ST Z F401 // 1A POP LR FE00 // 1B RET 0000 // 1C 0000 // 1D 0000 // 1E 0000 // 1F 0003 // 20 X: WORD // 21 Y: WORD // 22 Z: WORD 0 007F // 23 STACKEND: WORD 127 執 行 結 果 D:\Dropbox\Public\web\oc\code\mcu0>iverilog -o mcu0s mcu0s.v
116 D:\Dropbox\Public\web\oc\code\mcu0>vvp mcu0s WARNING: mcu0s.v:29: $readmemh(mcu0s.hex): Not enough words in the file f or the requested range [0:4096]. 10ns PC=0000 IR=0020, SW=0000, A= 3 SP=xxxx LR=xxxx 30ns PC=0001 IR=2021, SW=0000, A= 8 SP=xxxx LR=xxxx 50ns PC=0002 IR=3021, SW=0000, A= 3 SP=xxxx LR=xxxx 70ns PC=0003 IR=4021, SW=0000, A= 15 SP=xxxx LR=xxxx 90ns PC=0004 IR=5021, SW=0000, A= 3 SP=xxxx LR=xxxx 110ns PC=0005 IR=7021, SW=0000, A= 7 SP=xxxx LR=xxxx 130ns PC=0006 IR=6021, SW=0000, A= 5 SP=xxxx LR=xxxx 150ns PC=0007 IR=8021, SW=0000, A= 0 SP=xxxx LR=xxxx 170ns PC=0008 IR=0020, SW=0000, A= 3 SP=xxxx LR=xxxx 190ns PC=0009 IR=f503, SW=0000, A= 24 SP=xxxx LR=xxxx 210ns PC=000a IR=f603, SW=0000, A= 3 SP=xxxx LR=xxxx 230ns PC=000b IR=f701, SW=0000, A= 4 SP=xxxx LR=xxxx 250ns PC=000c IR=0023, SW=0000, A= 127 SP=xxxx LR=xxxx 270ns PC=000d IR=f230, SW=0000, A= 127 SP=007f LR=xxxx 290ns PC=000e IR=e011, SW=0000, A= 127 SP=007f LR=000f 310ns PC=0011 IR=f301, SW=0000, A= 127 SP=007e LR=000f 330ns PC=0012 IR=0020, SW=0000, A= 3 SP=007e LR=000f 350ns PC=0013 IR=9021, SW=8000, A= 3 SP=007e LR=000f 370ns PC=0014 IR=fd00, SW=4000, A= 3 SP=007e LR=000f 390ns PC=0015 IR=c018, SW=4000, A= 3 SP=007e LR=000f 410ns PC=0016 IR=1022, SW=4000, A= 3 SP=007e LR=000f 430ns PC=0017 IR=a019, SW=4000, A= 3 SP=007e LR=000f 450ns PC=0019 IR=1022, SW=4000, A= 3 SP=007e LR=000f 470ns PC=001a IR=f401, SW=4000, A= 127 SP=007f LR=000f 490ns PC=001b IR=fe00, SW=4000, A= 127 SP=007f LR=000f 510ns PC=000f IR=0022, SW=4000, A= 3 SP=007f LR=000f 530ns PC=0010 IR=a010, SW=4000, A= 3 SP=007f LR=000f 550ns PC=0010 IR=a010, SW=4000, A= 3 SP=007f LR=000f 570ns PC=0010 IR=a010, SW=4000, A= 3 SP=007f LR=000f 590ns PC=0010 IR=a010, SW=4000, A= 3 SP=007f LR=000f 610ns PC=0010 IR=a010, SW=4000, A= 3 SP=007f LR=000f 630ns PC=0010 IR=a010, SW=4000, A= 3 SP=007f LR=000f
117 650ns PC=0010 IR=a010, SW=4000, A= 670ns PC=0010 IR=a010, SW=4000, A= 690ns PC=0010 IR=a010, SW=4000, A= 710ns PC=0010 IR=a010, SW=4000, A= 730ns PC=0010 IR=a010, SW=4000, A= 750ns PC=0010 IR=a010, SW=4000, A= 770ns PC=0010 IR=a010, SW=4000, A= 790ns PC=0010 IR=a010, SW=4000, A= 810ns PC=0010 IR=a010, SW=4000, A= 830ns PC=0010 IR=a010, SW=4000, A= 850ns PC=0010 IR=a010, SW=4000, A= 870ns PC=0010 IR=a010, SW=4000, A= 890ns PC=0010 IR=a010, SW=4000, A= 910ns PC=0010 IR=a010, SW=4000, A= 930ns PC=0010 IR=a010, SW=4000, A= 950ns PC=0010 IR=a010, SW=4000, A= 970ns PC=0010 IR=a010, SW=4000, A= 990ns PC=0010 IR=a010, SW=4000, A= 3 SP=007f LR=000f 3 SP=007f LR=000f 3 SP=007f LR=000f 3 SP=007f LR=000f 3 SP=007f LR=000f 3 SP=007f LR=000f 3 SP=007f LR=000f 3 SP=007f LR=000f 3 SP=007f LR=000f 3 SP=007f LR=000f 3 SP=007f LR=000f 3 SP=007f LR=000f 3 SP=007f LR=000f 3 SP=007f LR=000f 3 SP=007f LR=000f 3 SP=007f LR=000f 3 SP=007f LR=000f 3 SP=007f LR=000f 結 語 由 於 16 位 元 處 理 器 的 指 令 長 度 很 短, 因 此 空 間 必 須 有 效 利 用, 所 以 我 們 將 一 些 不 包 含 記 憶 體 位 址 的 指 令, 編 到 最 後 的 0xF 的 OP 代 碼 當 中, 這 樣 就 可 以 再 度 延 伸 出 一 大 群 指 令 空 間, 於 是 讓 指 令 數 可 以 不 受 限 於 4 位 元 OP 碼 的 16 個 指 令, 而 能 延 伸 為 30 個 左 右 的 指 令 在 使 用 Verilog 這 種 硬 體 描 述 語 言 設 計 處 理 器 時, 位 元 數 越 少, 往 往 處 理 器 的 指 令 長 度 越 少, 這 時 處 理 器 不 見 得 會 更 好 設 計, 往 往 反 而 會 更 難 設 計, 指 令 集 的 編 碼 相 對 會 困 難 一 些
118 輸 出 入 單 元 (I/O) 前 言 圖 PC 匯 流 排 的 連 接 結 構 BUS ( 總 線, 匯 流 排 ) 由 於 線 路 多 的 話 會 很 混 亂, 而 且 成 本 很 高 舉 例 而 言, 假 如 有 n 個 節 點 ( 裝 置 ), 所 有 節 點 之 間 都 要 互 相 直 接 相 連, 那 麼 就 需 要 n*(n-1)2/ 這 個 多 組 線 路, 這 將 會 是 個 密 密 麻 麻 的 災 難 如 果 我 們 讓 所 有 的 節 點 都 連 接 到 一 組 共 用 的 線 路, 這 套 線 路 就 稱 為 BUS 只 要 大 家 都 遵 循 一 套 固 定 的 傳 送 規 則, 我 們 就 可 以 用 BUS 作 為 所 有 人 的 通 訊 橋 梁 以 下 是 用 Verilog 宣 告 BUS 線 路 的 三 種 方 法, 分 別 是 wire, wand 與 wor wire [n-1:0] BUS; wand [n-1:0] andbus; wor [n-1:0] orbus; 下 列 是 採 用 wire 方 式 宣 告 BUS 的 一 個 範 例, 當 某 個 seli 選 擇 線 為 1 時, 就 會 將 對 應 的 來 源 資 料 sourcei 放 到 BUS 上 而 那 些 沒 被 選 到 的 來 源, 由 於 是 放 高 阻 抗 Z, 所 以 會 處 於 斷 線 的 狀 態 wire [n-1:0] BUS; parameter [n-1:0] disable = n'bz; assign BUS = sel1?source1:disable;
119 assign BUS = sel2?source2:disable;... assign BUS = selk?sourcek:disable; 另 外 兩 種 宣 告 BUS 的 方 法, 也 就 是 wand 與 wor, 與 wire 其 實 很 像, 差 別 只 在 於 wand 的 disable 是 用 n'b1, 而 wor 的 disable 是 用 n'b0 同 步 匯 流 排 (Synchronous BUS) module master(input clock, w, output [15:0] address, inout [15:0] data); reg [15:0] ar, dr; assign address = ar; assign data = (w)?dr : 16'hzzzz; begin if (!w) dr=#1 data; module module rdevice(input clock, w, input [15:0] address, output [15:0] data) ; reg [15:0] dr; assign data=(!w)?dr:16'hzzzz; or w or address) begin if (!w && address == 16'hFFF0) dr = #1 16'he3e3; module module wdevice(input clock, w, input [15:0] address, input [15:0] data); reg [15:0] dr; or w or address) begin if (w && address == 16'hFFF8) dr = #1 data;
120 module module main; reg clock, w; wire [15:0] abus, dbus; master m(clock, w, abus, dbus); rdevice rd(clock, w, abus, dbus); wdevice wd(clock, w, abus, dbus); initial begin $monitor("%4dns abus=%x dbus=%x w=%x m.ar=%x m.dr=%x rd.dr=%x wd.dr=%x", $stime, abus, dbus, w, m.ar, m.dr, rd.dr, wd.dr); clock = 0; #10; m.ar=16'h0000; w=0; #50; m.ar=16'hfff0; #50; m.ar=16'hfff8; m.dr=16'h71f0; w=1; #300; $finish; always #5 clock=~clock; // 每 隔 5ns 反 相, 時 脈 週 期 為 10ns module 執 行 結 果 D:\Dropbox\Public\web\co\code>iverilog syncbus.v -o syncbus D:\Dropbox\Public\web\co\code>vvp syncbus 0ns abus=xxxx dbus=xxxx w=x m.ar=xxxx m.dr=xxxx rd.dr=xxxx wd.dr=xxxx 10ns abus=0000 dbus=xxxx w=0 m.ar=0000 m.dr=xxxx rd.dr=xxxx wd.dr=xxxx 60ns abus=fff0 dbus=xxxx w=0 m.ar=fff0 m.dr=xxxx rd.dr=xxxx wd.dr=xxxx 61ns abus=fff0 dbus=e3e3 w=0 m.ar=fff0 m.dr=xxxx rd.dr=e3e3 wd.dr=xxxx 62ns abus=fff0 dbus=e3e3 w=0 m.ar=fff0 m.dr=e3e3 rd.dr=e3e3 wd.dr=xxxx 110ns abus=fff8 dbus=71f0 w=1 m.ar=fff8 m.dr=71f0 rd.dr=e3e3 wd.dr=xxxx 111ns abus=fff8 dbus=71f0 w=1 m.ar=fff8 m.dr=71f0 rd.dr=e3e3 wd.dr=e3e3 116ns abus=fff8 dbus=71f0 w=1 m.ar=fff8 m.dr=71f0 rd.dr=e3e3 wd.dr=71f0
121 圖 上 述 同 步 BUS 的 波 形 圖 異 步 匯 流 排 (Asynchronous BUS) 異 步 匯 流 排 是 指 沒 有 共 同 Clock 訊 號 的 匯 流 排, 因 此 無 法 依 賴 Clock 進 行 同 步, 所 以 必 須 依 靠 主 控 就 緒 (Master Ready), 從 動 就 緒 (Slave Ready) 等 訊 號, 來 進 行 握 手 (Handshaking) 的 協 調 程 序 匯 流 排 仲 裁 (BUS arbitery) 當 有 很 多 個 主 控 裝 置 都 有 可 能 請 求 使 用 BUS 的 時 候, 就 必 須 要 加 入 一 個 仲 裁 機 制, 通 常 是 由 一 個 仲 裁 者 (arbiter) 進 行 仲 裁 循 序 與 平 行 輸 出 入 (Serial vs. Parallel) 常 見 的 輸 出 入 協 定 MCU0 的 輸 出 入 -- 輪 詢 篇 在 本 文 中, 我 們 利 用 輪 詢 的 方 式 實 作 了 MCU0 的 鍵 盤 與 文 字 輸 出 的 函 數
122 MCU0 的 中 斷 位 元 在 電 腦 中, 進 行 輸 出 入 所 採 用 的 方 式, 在 指 令 上 可 分 為 專 用 輸 出 入 指 令 與 記 憶 體 映 射 輸 出 入 兩 種, 在 本 文 中 我 們 將 用 記 憶 體 映 射 輸 出 入 進 行 輸 出 入 另 外 進 行 輸 出 入 的 驅 動 方 式, 可 分 為 輪 詢 與 中 斷 兩 種 方 式, 本 文 將 採 用 輪 詢 的 方 式 實 作 MCU0 的 輸 出 入 實 作 方 式 `define OP IR[15:12] // 運 算 碼 `define C IR[11:0] // 常 數 欄 位 `define SC8 $signed(ir[7:0]) // 常 數 欄 位 `define C4 IR[3:0] // 常 數 欄 位 `define Ra IR[7:4] // Ra `define Rb IR[3:0] // Rb `define A R[0] // 累 積 器 `define LR R[1] // 狀 態 暫 存 器 `define SW R[2] // 狀 態 暫 存 器 `define SP R[3] // 堆 疊 暫 存 器 `define PC R[4] // 程 式 計 數 器 `define N `SW[15] // 負 號 旗 標 `define Z `SW[14] // 零 旗 標 `define I `SW[3] // 是 否 中 斷 中 `define M m[`c] // 存 取 記 憶 體 module mcu(input clock, input interrupt, input[2:0] irq); parameter [3:0] LD=4'h0,ST=4'h1,ADD=4'h2,SUB=4'h3,MUL=4'h4,DIV=4'h5,AND =4'h6,OR=4'h7,XOR=4'h8,CMP=4'h9,JMP=4'hA,JEQ=4'hB, JLT=4'hC, JLE=4'hD, CA LL=4'hE, OP8=4'hF; parameter [3:0] LDI=4'h0, MOV=4'h2, PUSH=4'h3, POP=4'h4, SHL=4'h5, SHR= 4'h6, ADDI=4'h7, SUBI=4'h8, NEG=4'h9, SWI=4'hA, NSW=4'hD, RET=4'hE, IRET= 4'hF; reg [15:0] IR; // 指 令 暫 存 器 reg signed [15:0] R[0:4]; reg signed [15:0] pc0; reg signed [15:0] m [0:4095]; // 內 部 的 快 取 記 憶 體 integer i; initial // 初 始 化 begin
123 `PC = 0; // 將 PC 設 為 起 動 位 址 0 `SW = 0; $readmemh("mcu0io.hex", m); for (i=0; i < 32; i=i+1) begin $display("%x %x", i, m[i]); clock) begin // 在 clock 時 脈 的 正 邊 緣 時 觸 發 IR = m[`pc]; // 指 令 擷 取 階 段 :IR=m[PC], 2 個 Byte 的 記 憶 體 pc0= `PC; // 儲 存 舊 的 PC 值 在 pc0 中 `PC = `PC+1; // 擷 取 完 成,PC 前 進 到 下 一 個 指 令 位 址 case (`OP) // 解 碼 根 據 OP 執 行 動 作 LD: `A = `M; // LD C ST: `M = `A; // ST C ADD: `A = `A + `M; // ADD C SUB: `A = `A - `M; // SUB C MUL: `A = `A * `M; // MUL C DIV: `A = `A / `M; // DIV C AND: `A = `A & `M; // AND C OR : `A = `A `M; // OR C XOR: `A = `A ^ `M; // XOR C CMP: begin `N=(`A < `M); `Z=(`A==`M); // CMP C JMP: `PC = `C; // JSUB C JEQ: if (`Z) `PC=`C; // JEQ C JLT: if (`N) `PC=`C; // JLT C JLE: if (`N `Z) `PC=`C;// JLE C CALL:begin `LR = `PC; `PC = `C; // CALL C OP8: case (IR[11:8]) // OP8: 加 長 運 算 碼 LDI: R[`Ra] = `C4; // LDI C ADDI: R[`Ra] = R[`Ra] + `C4; // ADDI C SUBI: R[`Ra] = R[`Ra] - `C4; // ADDI C MOV: R[`Ra] = R[`Rb]; // MOV Ra, Rb PUSH: begin `SP=`SP-1; m[`sp] = R[`Ra]; // PUSH Ra POP: begin R[`Ra] = m[`sp]; `SP=`SP+1; // POP Ra SHL: R[`Ra] = R[`Ra] << `C4; // SHL C
124 SHR: R[`Ra] = R[`Ra] >> `C4; // SHR C SWI: $display("swi C8=%d A=%d", `SC8, `A); // SWI C NEG: R[`Ra] = ~R[`Ra]; // NEG Ra NSW: begin `N=~`N; `Z=~`Z; // NSW (negate N, Z ) RET: `PC = `LR; // RET IRET: begin `PC = `LR; `I = 0; // IRET default: $display("op8=%d, not defined!", IR[11:8]); case case // 印 出 PC, IR, SW, A 等 暫 存 器 值 以 供 觀 察 $display("%4dns PC=%x IR=%x, SW=%x, A=%d SP=%x LR=%x", $stime, pc0, I R, `SW, `A, `SP, `LR); if (!`I && interrupt) begin `I = 1; `LR = `PC; `PC = irq; module module keyboard; reg [7:0] ch[0:20]; reg [7:0] i; initial begin i=0; {ch[0],ch[1],ch[2],ch[3],ch[4],ch[5],ch[6],ch[7],ch[8],ch[9],ch[10],ch[ 11],ch[12],ch[13]} = "hello verilog!"; main.mcu0.m[16'h07f0] = 0; main.mcu0.m[16'h07f1] = 0; always #20 begin if (main.mcu0.m[16'h07f0] == 0) begin main.mcu0.m[16'h07f1] = {8'h0, ch[i]}; main.mcu0.m[16'h07f0] = 1; $display("key = %c", ch[i]);
125 i = i+1; module module screen; reg [7:0] ch; initial begin main.mcu0.m[16'h07f2] = 0; main.mcu0.m[16'h07f3] = 0; always #10 begin if (main.mcu0.m[16'h07f2] == 1) begin ch = main.mcu0.m[16'h07f3][7:0]; $display("screen %c", ch); main.mcu0.m[16'h07f2] = 0; module module main; reg clock; reg interrupt; reg [2:0] irq; // 測 試 程 式 開 始 // 時 脈 clock 變 數 mcu mcu0(clock, interrupt, irq); // 宣 告 cpu0mc 處 理 器 keyboard kb0(); screen sc0(); initial begin clock = 0; // 一 開 始 clock 設 定 為 0 interrupt = 0; irq = 2; always #10 clock=~clock; // 每 隔 10ns 反 相, 時 脈 週 期 為 20ns
126 initial #4000 $finish; // 停 止 測 試 module 輸 入 機 器 碼 與 組 合 語 言 07F0 // 00 WAITK: LD 0x7F0 ; wait keyboard 9010 // 01 CMP K0 B000 // 02 JEQ WAIT 07F1 // 03 LD 0x7F1 ; read key 1011 // 04 ST KEY 0010 // 05 LD K0 17F0 // 06 ST 0x7F0 ; release keyboard 07F2 // 07 WAITS: LD 0x7F2 ; wait screen 0010 // 08 CMP K0 B007 // 09 JEQ WAITS 0011 // 0A LD KEY ; print key 17F3 // 0B ST 0x7F3 F001 // 0C LDI 1 17F2 // 0D ST 0x7F2 ; eanble screen A000 // 0E JMP WAIT 0000 // 0F 0000 // 10 K0: WORD // 11 KEY: WORD 0 執 行 結 果 D:\Dropbox\Public\web\oc\code\mcu0>iverilog -o mcu0io mcu0io.v D:\Dropbox\Public\web\oc\code\mcu0>vvp mcu0io WARNING: mcu0io.v:29: $readmemh(mcu0io.hex): Not enough words in the file for th e requested range [0:4095] f b f
127 f f b a b 17f c f d 17f e a f xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx a xxxx b xxxx c xxxx d xxxx e xxxx f xxxx 10ns PC=0000 IR=07f0, SW=0000, A= 0 SP=xxxx LR=xxxx key = h 30ns PC=0001 IR=9010, SW=4000, A= 0 SP=xxxx LR=xxxx 50ns PC=0002 IR=b000, SW=4000, A= 0 SP=xxxx LR=xxxx 70ns PC=0000 IR=07f0, SW=4000, A= 1 SP=xxxx LR=xxxx 90ns PC=0001 IR=9010, SW=0000, A= 1 SP=xxxx LR=xxxx 110ns PC=0002 IR=b000, SW=0000, A= 1 SP=xxxx LR=xxxx 130ns PC=0003 IR=07f1, SW=0000, A= 104 SP=xxxx LR=xxxx 150ns PC=0004 IR=1011, SW=0000, A= 104 SP=xxxx LR=xxxx 170ns PC=0005 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx
128 190ns PC=0006 IR=17f0, SW=0000, A= 0 SP=xxxx LR=xxxx key = e 210ns PC=0007 IR=07f2, SW=0000, A= 0 SP=xxxx LR=xxxx 230ns PC=0008 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 250ns PC=0009 IR=b007, SW=0000, A= 0 SP=xxxx LR=xxxx 270ns PC=000a IR=0011, SW=0000, A= 104 SP=xxxx LR=xxxx 290ns PC=000b IR=17f3, SW=0000, A= 104 SP=xxxx LR=xxxx 310ns PC=000c IR=f001, SW=0000, A= 1 SP=xxxx LR=xxxx 330ns PC=000d IR=17f2, SW=0000, A= 1 SP=xxxx LR=xxxx screen h 350ns PC=000e IR=a000, SW=0000, A= 1 SP=xxxx LR=xxxx 370ns PC=0000 IR=07f0, SW=0000, A= 1 SP=xxxx LR=xxxx 390ns PC=0001 IR=9010, SW=0000, A= 1 SP=xxxx LR=xxxx 410ns PC=0002 IR=b000, SW=0000, A= 1 SP=xxxx LR=xxxx 430ns PC=0003 IR=07f1, SW=0000, A= 101 SP=xxxx LR=xxxx 450ns PC=0004 IR=1011, SW=0000, A= 101 SP=xxxx LR=xxxx 470ns PC=0005 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 490ns PC=0006 IR=17f0, SW=0000, A= 0 SP=xxxx LR=xxxx key = l 510ns PC=0007 IR=07f2, SW=0000, A= 0 SP=xxxx LR=xxxx 530ns PC=0008 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 550ns PC=0009 IR=b007, SW=0000, A= 0 SP=xxxx LR=xxxx 570ns PC=000a IR=0011, SW=0000, A= 101 SP=xxxx LR=xxxx 590ns PC=000b IR=17f3, SW=0000, A= 101 SP=xxxx LR=xxxx 610ns PC=000c IR=f001, SW=0000, A= 1 SP=xxxx LR=xxxx 630ns PC=000d IR=17f2, SW=0000, A= 1 SP=xxxx LR=xxxx screen e 650ns PC=000e IR=a000, SW=0000, A= 1 SP=xxxx LR=xxxx 670ns PC=0000 IR=07f0, SW=0000, A= 1 SP=xxxx LR=xxxx 690ns PC=0001 IR=9010, SW=0000, A= 1 SP=xxxx LR=xxxx 710ns PC=0002 IR=b000, SW=0000, A= 1 SP=xxxx LR=xxxx 730ns PC=0003 IR=07f1, SW=0000, A= 108 SP=xxxx LR=xxxx 750ns PC=0004 IR=1011, SW=0000, A= 108 SP=xxxx LR=xxxx 770ns PC=0005 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 790ns PC=0006 IR=17f0, SW=0000, A= 0 SP=xxxx LR=xxxx key = l 810ns PC=0007 IR=07f2, SW=0000, A= 0 SP=xxxx LR=xxxx
129 830ns PC=0008 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 850ns PC=0009 IR=b007, SW=0000, A= 0 SP=xxxx LR=xxxx 870ns PC=000a IR=0011, SW=0000, A= 108 SP=xxxx LR=xxxx 890ns PC=000b IR=17f3, SW=0000, A= 108 SP=xxxx LR=xxxx 910ns PC=000c IR=f001, SW=0000, A= 1 SP=xxxx LR=xxxx 930ns PC=000d IR=17f2, SW=0000, A= 1 SP=xxxx LR=xxxx screen l 950ns PC=000e IR=a000, SW=0000, A= 1 SP=xxxx LR=xxxx 970ns PC=0000 IR=07f0, SW=0000, A= 1 SP=xxxx LR=xxxx 990ns PC=0001 IR=9010, SW=0000, A= 1 SP=xxxx LR=xxxx 1010ns PC=0002 IR=b000, SW=0000, A= 1 SP=xxxx LR=xxxx 1030ns PC=0003 IR=07f1, SW=0000, A= 108 SP=xxxx LR=xxxx 1050ns PC=0004 IR=1011, SW=0000, A= 108 SP=xxxx LR=xxxx 1070ns PC=0005 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 1090ns PC=0006 IR=17f0, SW=0000, A= 0 SP=xxxx LR=xxxx key = o 1110ns PC=0007 IR=07f2, SW=0000, A= 0 SP=xxxx LR=xxxx 1130ns PC=0008 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 1150ns PC=0009 IR=b007, SW=0000, A= 0 SP=xxxx LR=xxxx 1170ns PC=000a IR=0011, SW=0000, A= 108 SP=xxxx LR=xxxx 1190ns PC=000b IR=17f3, SW=0000, A= 108 SP=xxxx LR=xxxx 1210ns PC=000c IR=f001, SW=0000, A= 1 SP=xxxx LR=xxxx 1230ns PC=000d IR=17f2, SW=0000, A= 1 SP=xxxx LR=xxxx screen l 1250ns PC=000e IR=a000, SW=0000, A= 1 SP=xxxx LR=xxxx 1270ns PC=0000 IR=07f0, SW=0000, A= 1 SP=xxxx LR=xxxx 1290ns PC=0001 IR=9010, SW=0000, A= 1 SP=xxxx LR=xxxx 1310ns PC=0002 IR=b000, SW=0000, A= 1 SP=xxxx LR=xxxx 1330ns PC=0003 IR=07f1, SW=0000, A= 111 SP=xxxx LR=xxxx 1350ns PC=0004 IR=1011, SW=0000, A= 111 SP=xxxx LR=xxxx 1370ns PC=0005 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 1390ns PC=0006 IR=17f0, SW=0000, A= 0 SP=xxxx LR=xxxx key = 1410ns PC=0007 IR=07f2, SW=0000, A= 0 SP=xxxx LR=xxxx 1430ns PC=0008 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 1450ns PC=0009 IR=b007, SW=0000, A= 0 SP=xxxx LR=xxxx 1470ns PC=000a IR=0011, SW=0000, A= 111 SP=xxxx LR=xxxx
130 1490ns PC=000b IR=17f3, SW=0000, A= 111 SP=xxxx LR=xxxx 1510ns PC=000c IR=f001, SW=0000, A= 1 SP=xxxx LR=xxxx 1530ns PC=000d IR=17f2, SW=0000, A= 1 SP=xxxx LR=xxxx screen o 1550ns PC=000e IR=a000, SW=0000, A= 1 SP=xxxx LR=xxxx 1570ns PC=0000 IR=07f0, SW=0000, A= 1 SP=xxxx LR=xxxx 1590ns PC=0001 IR=9010, SW=0000, A= 1 SP=xxxx LR=xxxx 1610ns PC=0002 IR=b000, SW=0000, A= 1 SP=xxxx LR=xxxx 1630ns PC=0003 IR=07f1, SW=0000, A= 32 SP=xxxx LR=xxxx 1650ns PC=0004 IR=1011, SW=0000, A= 32 SP=xxxx LR=xxxx 1670ns PC=0005 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 1690ns PC=0006 IR=17f0, SW=0000, A= 0 SP=xxxx LR=xxxx key = v 1710ns PC=0007 IR=07f2, SW=0000, A= 0 SP=xxxx LR=xxxx 1730ns PC=0008 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 1750ns PC=0009 IR=b007, SW=0000, A= 0 SP=xxxx LR=xxxx 1770ns PC=000a IR=0011, SW=0000, A= 32 SP=xxxx LR=xxxx 1790ns PC=000b IR=17f3, SW=0000, A= 32 SP=xxxx LR=xxxx 1810ns PC=000c IR=f001, SW=0000, A= 1 SP=xxxx LR=xxxx 1830ns PC=000d IR=17f2, SW=0000, A= 1 SP=xxxx LR=xxxx screen 1850ns PC=000e IR=a000, SW=0000, A= 1 SP=xxxx LR=xxxx 1870ns PC=0000 IR=07f0, SW=0000, A= 1 SP=xxxx LR=xxxx 1890ns PC=0001 IR=9010, SW=0000, A= 1 SP=xxxx LR=xxxx 1910ns PC=0002 IR=b000, SW=0000, A= 1 SP=xxxx LR=xxxx 1930ns PC=0003 IR=07f1, SW=0000, A= 118 SP=xxxx LR=xxxx 1950ns PC=0004 IR=1011, SW=0000, A= 118 SP=xxxx LR=xxxx 1970ns PC=0005 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 1990ns PC=0006 IR=17f0, SW=0000, A= 0 SP=xxxx LR=xxxx key = e 2010ns PC=0007 IR=07f2, SW=0000, A= 0 SP=xxxx LR=xxxx 2030ns PC=0008 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 2050ns PC=0009 IR=b007, SW=0000, A= 0 SP=xxxx LR=xxxx 2070ns PC=000a IR=0011, SW=0000, A= 118 SP=xxxx LR=xxxx 2090ns PC=000b IR=17f3, SW=0000, A= 118 SP=xxxx LR=xxxx 2110ns PC=000c IR=f001, SW=0000, A= 1 SP=xxxx LR=xxxx 2130ns PC=000d IR=17f2, SW=0000, A= 1 SP=xxxx LR=xxxx
131 screen v 2150ns PC=000e IR=a000, SW=0000, A= 1 SP=xxxx LR=xxxx 2170ns PC=0000 IR=07f0, SW=0000, A= 1 SP=xxxx LR=xxxx 2190ns PC=0001 IR=9010, SW=0000, A= 1 SP=xxxx LR=xxxx 2210ns PC=0002 IR=b000, SW=0000, A= 1 SP=xxxx LR=xxxx 2230ns PC=0003 IR=07f1, SW=0000, A= 101 SP=xxxx LR=xxxx 2250ns PC=0004 IR=1011, SW=0000, A= 101 SP=xxxx LR=xxxx 2270ns PC=0005 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 2290ns PC=0006 IR=17f0, SW=0000, A= 0 SP=xxxx LR=xxxx key = r 2310ns PC=0007 IR=07f2, SW=0000, A= 0 SP=xxxx LR=xxxx 2330ns PC=0008 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 2350ns PC=0009 IR=b007, SW=0000, A= 0 SP=xxxx LR=xxxx 2370ns PC=000a IR=0011, SW=0000, A= 101 SP=xxxx LR=xxxx 2390ns PC=000b IR=17f3, SW=0000, A= 101 SP=xxxx LR=xxxx 2410ns PC=000c IR=f001, SW=0000, A= 1 SP=xxxx LR=xxxx 2430ns PC=000d IR=17f2, SW=0000, A= 1 SP=xxxx LR=xxxx screen e 2450ns PC=000e IR=a000, SW=0000, A= 1 SP=xxxx LR=xxxx 2470ns PC=0000 IR=07f0, SW=0000, A= 1 SP=xxxx LR=xxxx 2490ns PC=0001 IR=9010, SW=0000, A= 1 SP=xxxx LR=xxxx 2510ns PC=0002 IR=b000, SW=0000, A= 1 SP=xxxx LR=xxxx 2530ns PC=0003 IR=07f1, SW=0000, A= 114 SP=xxxx LR=xxxx 2550ns PC=0004 IR=1011, SW=0000, A= 114 SP=xxxx LR=xxxx 2570ns PC=0005 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 2590ns PC=0006 IR=17f0, SW=0000, A= 0 SP=xxxx LR=xxxx key = i 2610ns PC=0007 IR=07f2, SW=0000, A= 0 SP=xxxx LR=xxxx 2630ns PC=0008 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 2650ns PC=0009 IR=b007, SW=0000, A= 0 SP=xxxx LR=xxxx 2670ns PC=000a IR=0011, SW=0000, A= 114 SP=xxxx LR=xxxx 2690ns PC=000b IR=17f3, SW=0000, A= 114 SP=xxxx LR=xxxx 2710ns PC=000c IR=f001, SW=0000, A= 1 SP=xxxx LR=xxxx 2730ns PC=000d IR=17f2, SW=0000, A= 1 SP=xxxx LR=xxxx screen r 2750ns PC=000e IR=a000, SW=0000, A= 1 SP=xxxx LR=xxxx 2770ns PC=0000 IR=07f0, SW=0000, A= 1 SP=xxxx LR=xxxx
132 2790ns PC=0001 IR=9010, SW=0000, A= 1 SP=xxxx LR=xxxx 2810ns PC=0002 IR=b000, SW=0000, A= 1 SP=xxxx LR=xxxx 2830ns PC=0003 IR=07f1, SW=0000, A= 105 SP=xxxx LR=xxxx 2850ns PC=0004 IR=1011, SW=0000, A= 105 SP=xxxx LR=xxxx 2870ns PC=0005 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 2890ns PC=0006 IR=17f0, SW=0000, A= 0 SP=xxxx LR=xxxx key = l 2910ns PC=0007 IR=07f2, SW=0000, A= 0 SP=xxxx LR=xxxx 2930ns PC=0008 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 2950ns PC=0009 IR=b007, SW=0000, A= 0 SP=xxxx LR=xxxx 2970ns PC=000a IR=0011, SW=0000, A= 105 SP=xxxx LR=xxxx 2990ns PC=000b IR=17f3, SW=0000, A= 105 SP=xxxx LR=xxxx 3010ns PC=000c IR=f001, SW=0000, A= 1 SP=xxxx LR=xxxx 3030ns PC=000d IR=17f2, SW=0000, A= 1 SP=xxxx LR=xxxx screen i 3050ns PC=000e IR=a000, SW=0000, A= 1 SP=xxxx LR=xxxx 3070ns PC=0000 IR=07f0, SW=0000, A= 1 SP=xxxx LR=xxxx 3090ns PC=0001 IR=9010, SW=0000, A= 1 SP=xxxx LR=xxxx 3110ns PC=0002 IR=b000, SW=0000, A= 1 SP=xxxx LR=xxxx 3130ns PC=0003 IR=07f1, SW=0000, A= 108 SP=xxxx LR=xxxx 3150ns PC=0004 IR=1011, SW=0000, A= 108 SP=xxxx LR=xxxx 3170ns PC=0005 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 3190ns PC=0006 IR=17f0, SW=0000, A= 0 SP=xxxx LR=xxxx key = o 3210ns PC=0007 IR=07f2, SW=0000, A= 0 SP=xxxx LR=xxxx 3230ns PC=0008 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 3250ns PC=0009 IR=b007, SW=0000, A= 0 SP=xxxx LR=xxxx 3270ns PC=000a IR=0011, SW=0000, A= 108 SP=xxxx LR=xxxx 3290ns PC=000b IR=17f3, SW=0000, A= 108 SP=xxxx LR=xxxx 3310ns PC=000c IR=f001, SW=0000, A= 1 SP=xxxx LR=xxxx 3330ns PC=000d IR=17f2, SW=0000, A= 1 SP=xxxx LR=xxxx screen l 3350ns PC=000e IR=a000, SW=0000, A= 1 SP=xxxx LR=xxxx 3370ns PC=0000 IR=07f0, SW=0000, A= 1 SP=xxxx LR=xxxx 3390ns PC=0001 IR=9010, SW=0000, A= 1 SP=xxxx LR=xxxx 3410ns PC=0002 IR=b000, SW=0000, A= 1 SP=xxxx LR=xxxx 3430ns PC=0003 IR=07f1, SW=0000, A= 111 SP=xxxx LR=xxxx
133 3450ns PC=0004 IR=1011, SW=0000, A= 111 SP=xxxx LR=xxxx 3470ns PC=0005 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 3490ns PC=0006 IR=17f0, SW=0000, A= 0 SP=xxxx LR=xxxx key = g 3510ns PC=0007 IR=07f2, SW=0000, A= 0 SP=xxxx LR=xxxx 3530ns PC=0008 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 3550ns PC=0009 IR=b007, SW=0000, A= 0 SP=xxxx LR=xxxx 3570ns PC=000a IR=0011, SW=0000, A= 111 SP=xxxx LR=xxxx 3590ns PC=000b IR=17f3, SW=0000, A= 111 SP=xxxx LR=xxxx 3610ns PC=000c IR=f001, SW=0000, A= 1 SP=xxxx LR=xxxx 3630ns PC=000d IR=17f2, SW=0000, A= 1 SP=xxxx LR=xxxx screen o 3650ns PC=000e IR=a000, SW=0000, A= 1 SP=xxxx LR=xxxx 3670ns PC=0000 IR=07f0, SW=0000, A= 1 SP=xxxx LR=xxxx 3690ns PC=0001 IR=9010, SW=0000, A= 1 SP=xxxx LR=xxxx 3710ns PC=0002 IR=b000, SW=0000, A= 1 SP=xxxx LR=xxxx 3730ns PC=0003 IR=07f1, SW=0000, A= 103 SP=xxxx LR=xxxx 3750ns PC=0004 IR=1011, SW=0000, A= 103 SP=xxxx LR=xxxx 3770ns PC=0005 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 3790ns PC=0006 IR=17f0, SW=0000, A= 0 SP=xxxx LR=xxxx key =! 3810ns PC=0007 IR=07f2, SW=0000, A= 0 SP=xxxx LR=xxxx 3830ns PC=0008 IR=0010, SW=0000, A= 0 SP=xxxx LR=xxxx 3850ns PC=0009 IR=b007, SW=0000, A= 0 SP=xxxx LR=xxxx 3870ns PC=000a IR=0011, SW=0000, A= 103 SP=xxxx LR=xxxx 3890ns PC=000b IR=17f3, SW=0000, A= 103 SP=xxxx LR=xxxx 3910ns PC=000c IR=f001, SW=0000, A= 1 SP=xxxx LR=xxxx 3930ns PC=000d IR=17f2, SW=0000, A= 1 SP=xxxx LR=xxxx screen g 3950ns PC=000e IR=a000, SW=0000, A= 1 SP=xxxx LR=xxxx 3970ns PC=0000 IR=07f0, SW=0000, A= 1 SP=xxxx LR=xxxx 3990ns PC=0001 IR=9010, SW=0000, A= 1 SP=xxxx LR=xxxx 結 語 以 上 的 輸 出 入 方 式, 並 非 典 型 的 設 計, 而 是 屬 於 系 統 單 晶 片 (SOC) 的 設 計 方 式, 因 此 直 接 將 鍵 盤 與 螢 幕 的 輸 出 入 暫 存 器 直 接 內 建 在 MCU0 的 記 憶 體 之 內, 這 樣 的 設 計 會 比 將 輸 出 入 控 制 卡 與 CPU 分 開 的 方 式 更 容 易 一 些, 但 是 由 於 這 種 ASIC 的 量 產 費 用 昂 貴, 所 以 目 前 還 很 少 有 這 種 設 計 方 式
134 不 過 就 簡 單 性 而 言, 這 樣 的 設 計 確 實 非 常 簡 單, 因 此 符 合 開 放 電 腦 計 畫 的 Keep it Simple and Stupid (KISS) 原 則, 所 以 我 們 先 介 紹 這 樣 一 個 簡 易 的 輸 出 入 設 計 方 式, 以 便 讓 讀 者 能 從 最 簡 單 的 架 構 入 手
135 記 憶 系 統 (Storage) 除 了 記 憶 體 之 外, 電 腦 裏 還 有 隨 身 碟 記 憶 卡 硬 碟 光 碟 磁 帶 等 儲 存 裝 置, 這 些 裝 置 構 成 一 整 個 儲 存 體 系, 只 有 充 分 考 慮 這 些 儲 存 體 的 速 度 問 題, 才 能 讓 電 腦 得 到 最 好 的 效 能 事 實 上 記 憶 體 也 有 很 多 種, 而 且 速 度 不 一, 像 是 靜 態 記 憶 體 SRAM 動 態 記 憶 體 DRAM 唯 讀 記 憶 體 ROM 等 等, 而 且 靜 態 記 憶 體 的 速 度 又 可 以 分 為 很 多 種 等 級, 因 此 整 個 儲 存 體 會 形 成 一 個 多 層 次 不 同 速 度 的 記 憶 體 階 層 高 階 處 理 器 與 微 處 理 器 之 間 最 大 的 差 別, 是 高 階 處 理 器 會 利 用 各 種 記 憶 單 元 的 速 度 差 異, 有 效 的 安 排 並 平 衡 既 快 又 大 的 這 種 速 度 與 大 小 的 考 量 因 此 高 階 處 理 器 通 常 有 快 取 (cache) 記 憶 體 管 理 單 元 (Memory Management Unit, MMU) 等 機 制, 以 便 能 讓 電 腦 能 夠 容 量 又 大 速 度 又 快 要 能 夠 讓 高 階 處 理 器 充 分 利 用 這 種 記 憶 體 階 層 特 性, 首 先 讓 我 們 來 看 看 一 個 經 典 的 三 階 層 情 況, 那 就 是 (cache/memory/disk), 如 下 圖 所 示 記 憶 體 階 層 (Memory Hierarchy) 圖 常 見 的 三 層 式 記 憶 體 階 層 在 上 圖 中,cache 是 直 接 封 裝 在 CPU 內 部 的 靜 態 記 憶 體, 其 運 作 速 度 與 CPU 的 內 部 電 路 一 樣 快, 因 此 可 以 在 1 個 Clock Cycle 之 內 完 成 存 取 而 身 為 主 記 憶 體 的 DRAM, 速 度 比 靜 態 記 憶 體 慢 上 數 十 倍, 因 此 必 須 耗 費 幾 十 個 Cycle 才 能 完 成 存 取 最 下 層 的 硬 碟 (hard disk) 速 度 更 慢, 由 於 依 賴 讀 寫 頭 與 硬 盤 轉 動 的 機 械 性 動 作, 因 此 又 比 DRAM 慢 上 數 百 倍 ( 雖 然 轉 到 了 之 後 讀 取 還 算 快 速, 但 是 仍 然 相 對 緩 慢, 而 且 每 次 必 須 讀 一 大 塊, 否 則 轉 了 好 久 才 讀 1 個 byte 將 會 慢 如 蝸 牛 ) 當 然 有 些 電 腦 包 含 更 多 種 類 的 記 憶 單 元, 這 些 記 憶 裝 置 的 速 度 與 容 量 不 一, 以 下 是 一 個 更 多 層 次 的 記 憶 階 層 範 例
136 圖 更 多 層 次 的 記 憶 體 階 層 為 了 要 讓 電 腦 能 夠 又 快 又 大, 高 階 處 理 器 通 常 採 用 了 快 取 (cache) 與 記 憶 體 管 理 單 元 (MMU) 等 兩 個 技 術, 其 中 的 cache 位 於 CPU 內 部, 用 來 儲 存 常 用 的 指 令 與 資 料, 而 MMU 則 是 利 用 分 段 或 分 頁 等 機 制, 讓 記 憶 體 管 理 更 有 效 率, 甚 至 可 以 用 虛 擬 記 憶 體 技 術 把 硬 碟 拿 來 當 備 援 記 憶 體 使 用, 讓 容 量 可 以 進 一 步 提 升 當 然 要 使 用 這 些 快 取 與 暫 存 技 術, 都 必 須 付 出 相 對 應 的 代 價, 那 就 是 讓 你 的 CPU 設 計 更 加 複 雜, 而 且 有 時 也 會 快 不 起 來 ( 套 句 俗 話 說, 出 來 混 的, 總 有 一 天 是 要 還 的,CPU 的 設 計 也 是 如 此 ) 快 取 記 憶 體 (Cache) 傳 統 的 處 理 器 通 常 採 用 單 一 匯 流 排 馮 紐 曼 架 構 設 計, 這 種 架 構 非 常 簡 單 且 易 懂, 如 下 圖 所 示 : 圖 單 一 匯 流 排 的 馮 紐 曼 架 構 但 是 以 當 今 的 技 術, 上 圖 中 的 記 憶 體 通 常 採 用 DRAM 為 主 這 是 因 為 快 速 的 靜 態 記 憶 體 (SRAM) 仍 然 相 當 昂 貴, 而 速 度 慢 上 數 十 倍 的 動 態 記 憶 體 (DRAM) 則 相 對 便
137 宜, 因 此 電 腦 的 主 記 憶 體 通 常 仍 然 採 用 DRAM 為 主 如 果 要 讓 CPU 的 執 行 速 度 更 快, 就 不 能 讓 CPU 遷 就 於 DRAM 的 速 度 跟 著 變 慢, 此 時 我 們 可 以 在 CPU 內 部 加 入 一 個 快 取 記 憶 體 (cache), 讓 位 於 DRAM 中 常 用 到 的 指 令 與 資 料 放 入 快 取 當 中, 如 下 圖 所 示 : 圖 單 一 匯 流 排 的 馮 紐 曼 架 構 當 CPU 想 要 執 行 一 個 指 令 時, 如 果 該 指 令 已 經 在 cache 當 中, 就 不 需 要 讀 取 DRAM, 因 此 指 令 擷 取 階 段 就 可 以 快 上 數 十 倍 當 然 如 果 該 指 令 需 要 存 取 資 料, 而 該 資 料 已 經 在 cache 當 中 了, 那 麼 CPU 就 不 需 要 從 DRAM 中 讀 取 資 料, 因 此 資 料 讀 取 階 段 就 可 以 快 上 數 十 倍 當 需 要 寫 入 資 料 時, 如 果 暫 時 先 寫 到 cache 當 中, 而 不 是 直 接 寫 回 DRAM, 那 麼 資 料 寫 入 的 動 作 就 可 以 快 上 數 十 倍 當 然 上 述 的 美 好 情 況 不 會 永 遠 都 成 立, 假 如 想 存 取 的 指 令 或 資 料 不 存 在 cache 當 中, 那 麼 就 必 須 從 DRAM 讀 取 資 料, 這 時 CPU 的 速 度 就 會 被 打 回 原 形, 變 成 與 DRAM 的 速 度 一 樣 而 且 當 資 料 被 放 入 cache 之 後, 由 於 DRAM 當 中 還 有 一 份 同 樣 的 資 料, 要 又 如 何 才 能 快 速 的 查 出 資 料 是 否 在 cache 當 中, 就 是 一 個 不 容 易 的 問 題 了 這 個 問 題 的 解 決, 必 須 依 靠 某 種 記 憶 體 位 址 的 標 籤 (tag), 透 過 這 種 標 籤 我 們 可 以 查 出 某 個 位 址 的 內 容 到 底 是 在 cache 當 中 的 那 一 格 而 標 籤 的 設 計 方 法, 大 致 可 分 為 直 接 映 射 (direct-mapping), 關 連 映 射 (associate-mapping) 與 組 關 連 映 射 (set associative-mapping) 等 幾 種 方 法 其 中 最 常 採 用 的 是 後 者 對 這 些 cache 作 法 的 細 節 有 興 趣 的 讀 者, 可 以 參 考 下 列 文 件 維 基 百 科 :CPU 快 取
138 高 階 處 理 器 (Processor) 在 前 一 章 當 中, 我 們 說 明 了 微 處 理 器 的 設 計 方 式, 在 本 章 中 我 們 將 說 明 高 階 處 理 器 的 設 計 方 式 與 微 處 理 器 比 起 來, 高 階 處 理 器 除 了 指 令 寬 度 較 大 之 外, 能 定 址 的 記 憶 體 空 間 通 常 也 很 大, 而 且 會 內 建 記 憶 體 管 理 單 元 (Memory Management Unit, MMU) 與 多 層 快 取 機 制 (cache) 等 等, 這 些 都 是 為 了 充 分 發 揮 處 理 器 的 效 能 的 設 計, 這 也 正 是 為 何 稱 為 高 階 處 理 器 的 原 因 在 本 章 當 中, 我 們 將 透 過 cpu0 這 個 架 構, 給 出 一 個 處 理 器 的 簡 易 範 例 之 後, 就 開 始 針 對 現 今 的 高 階 處 理 器 之 結 構 進 行 探 討, 以 便 讓 讀 者 在 能 清 楚 的 理 解 現 代 高 階 處 理 器 的 設 計 原 理 與 特 性 哈 佛 架 構 (Harvard Architecture) 在 單 一 匯 流 排 馮 紐 曼 架 構 之 下, 由 於 指 令 與 資 料 放 在 同 一 個 記 憶 體 當 中, 而 且 只 有 一 套 匯 流 排, 因 此 指 令 與 資 料 勢 必 無 法 同 時 存 取 如 果 我 們 希 望 同 時 進 行 指 令 與 資 料 的 存 取, 那 麼 就 可 以 將 指 令 與 資 料 分 別 放 在 兩 塊 不 同 的 記 憶 體 當 中, 並 且 各 用 一 套 內 部 匯 流 排 連 接 到 CPU, 這 樣 就 有 可 能 同 時 存 取 指 令 和 資 料, 也 就 有 可 能 將 指 令 擷 取 (instruction fetch) 與 資 料 存 取 (data access) 階 段 重 疊 執 行 了 圖 指 令 與 資 料 分 開 為 兩 套 記 憶 體 的 哈 佛 架 構 採 用 指 令 與 資 料 分 開 的 兩 套 記 憶 體 模 式, 如 果 都 是 DRAM 的 話, 那 麼 該 處 理 器 仍 然 會 式 非 常 緩 慢 的, 因 為 受 限 於 DRAM 的 速 度 限 制, 因 此 這 種 方 式 根 本 就 是 花 了 兩 倍 力 氣 卻 得 不 到 太 多 好 處, 可 以 說 是 一 種 很 爛 的 設 計 但 是 假 如 我 們 不 是 將 主 記 憶 體 分 為 兩 套, 而 是 將 cache 分 為 指 令 快 取 (i-cache) 與 資 料 快 取 (dcache) 的 變 種 哈 佛 架 構 話, 那 麼 速 度 就 真 的 是 會 變 快 了
139 圖 採 用 兩 套 快 取 的 單 一 匯 流 排 哈 佛 架 構 不 過 其 實 還 可 以 變 得 更 快, 只 要 我 們 能 夠 用 流 水 線 的 模 式, 就 能 讓 CPU 快 上 五 倍, 這 必 須 讓 指 令 的 每 個 階 段 都 能 重 疊 起 來 才 行 ( 包 含 指 令 擷 取 與 資 料 存 取 階 段 的 重 疊, 這 也 正 是 為 何 要 討 論 哈 佛 架 構 的 原 因 ) 流 水 線 架 構 (Pipeline) Pipeline 是 一 種 讓 指 令 分 成 幾 個 步 驟, 然 後 兩 個 指 令 的 不 同 步 驟 可 以 瀑 布 式 重 疊 的 方 法 舉 例 而 言 假 如 我 們 將 一 個 指 令 的 執 行 分 為 五 個 步 驟 如 下 : 1. 擷 取 F (Fatch) 2. 解 碼 D (Decode) 3. 計 算 C (Compute) 4. 存 取 M (Memory Access) 5. 寫 回 W (Write Back) 那 麼 在 理 想 的 情 況 下, 我 們 就 能 夠 讓 這 些 指 令 充 分 的 重 疊 執 行, 如 下 圖 所 示
140 圖 理 想 的 Pipeline 執 行 情 況 如 此 只 要 讓 每 個 步 驟 所 需 的 時 間 幾 乎 一 樣, 然 後 將 Clock 調 快 五 倍, 就 能 讓 速 度 整 整 加 快 五 倍 這 就 是 所 謂 的 Pipeline 流 水 線 架 構 的 原 理 然 而 流 水 線 架 構 的 處 理 器 設 計 比 較 困 難, 因 為 上 圖 的 理 想 情 況 畢 竟 只 是 理 想, 現 實 生 活 中 有 很 多 因 素 會 干 擾 流 水 線 的 運 行, 造 成 流 水 線 某 個 階 段 受 到 阻 礙 無 法 完 成, 必 須 暫 停 等 後 某 個 步 驟 完 成, 這 種 暫 停 會 形 成 流 水 線 當 中 的 氣 泡 (bubble), 這 種 情 況 統 稱 為 指 令 圍 障 (instruction hazard) Hazard 有 好 幾 種, 像 是 資 料 圍 障 (data hazard) 快 取 失 敗 (cache miss) 分 支 延 遲 (branch penalty) 等 等 流 水 線 架 構 的 設 計, 通 常 必 須 用 暫 存 器 圍 牆 (Register wall) 將 每 個 步 驟 之 間 相 互 隔 開, 以 避 免 線 路 之 間 的 干 擾, 如 下 所 示 :
141 圖 以 暫 存 器 圍 牆 分 隔 流 水 線 架 構 的 每 個 階 段 Pipeline 處 理 器 最 困 難 的 地 方, 就 是 要 盡 可 能 的 減 少 這 些 hazard 然 而 有 些 hazard 是 可 以 用 硬 體 方 式 消 除 的, 但 是 很 多 hazard 的 消 除 卻 是 需 要 編 譯 器 的 配 合 才 能 夠 做 得 到 透 過 編 譯 器 的 協 助 減 少 hazard 的 方 法, 包 括 指 令 重 排 插 入 NOP 指 令 分 支 預 測 等 等 想 要 進 一 步 瞭 解 流 水 線 架 構 細 節 的 讀 者, 可 以 參 考 下 列 文 件 維 基 百 科 : 流 水 線 維 基 百 科 : 指 令 管 線 化 維 基 百 科 : 分 支 預 測 器 CPU0 迷 你 版 - CPU0m 在 本 章 中, 我 們 將 透 過 設 計 一 顆 只 支 援 4 個 指 令 的 超 微 小 處 理 器 CPU0m (CPU0-Mini) 開 始, 來 解 說 處 理 器 的 設 計 方 式 只 有 4 個 指 令 的 處 理 器 - CPU0m 在 此 我 們 將 用 最 簡 單 的 方 式, 在 完 全 不 考 慮 成 本 與 實 用 性 的 情 況 之 下, 設 計 一 個 將 記 憶 體 嵌 入 處 理 器 內 部 的 CPU, 也 就 是 整 個 記 憶 體 都 用 Verilog 內 嵌 在 CPU 理 面 我 們 從 CPU0 的 指 令 集 當 中, 挑 出 了 以 下 的 四 個 指 令, 以 便 寫 出 一 個 可 以 計 算 n+... 的 組 合 語 言 程
142 式 ( 喔! 不 應 該 說 是 機 器 語 言 程 式 ), 然 後 用 Verilog 實 作 一 個 可 以 執 行 這 些 指 令 的 CPU0m 處 理 器 格 式 指 令 OP 說 明 語 法 語 意 L LD 00 載 入 word LD Ra, [Rb+Cx] Ra=[Rb+Cx] L ST 01 儲 存 word ST Ra, [Rb+Cx] Ra=[Rb+Cx] A ADD 13 加 法 ADD Ra, Rb, Rc Ra=Rb+Rc J JMP 26 跳 躍 ( 無 條 件 ) JMP Cx PC=PC+Cx 然 後, 我 們 就 可 以 用 這 幾 個 指 令 寫 出 以 下 的 程 式 : 位 址 機 器 碼 標 記 組 合 語 言 對 照 的 C 語 言 F0018 LD R1, K1 R1 = K F0010 LD R2, K0 R2 = K F0014 LD R3, SUM R3 = SUM 000C LOOP: ADD R2, R2, R1 R2 = R2 + R ADD R3, R3, R2 R3 = R3 + R FFFFF4 JMP LOOP goto LOOP K0: WORD 0 int K0=0 001C K1: WORD 1 int K1= SUM: WORD 0 int SUM=0 這 個 程 式 的 行 為 模 式, 是 會 讓 暫 存 器 R3 ( 對 應 到 SUM) 從 0, 1, 1+2, 1+2+3,... 一 路 向 上 跑, 而 且 是 永 無 止 境 的 無 窮 迴 圈 因 此 我 們 會 看 到 R3 的 內 容 會 是 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55..., 的 情 況 透 過 CPU0m, 讀 者 將 可 以 開 始 瞭 解 一 顆 CPU 的 結 構 與 設 計 方 式, 並 且 更 清 楚 的 理 解 CPU 的 控 制 單 元 之 功 能 指 令 提 取 解 碼 與 執 行 CPU0 在 執 行 一 個 指 令 時, 必 須 經 過 提 取 解 碼 與 執 行 等 三 大 階 段, 以 下 是 這 三 個 階 段 的 詳 細 步 驟 階 段 (a): 提 取 階 段 動 作 1 提 取 指 令 :IR = m[pc] 動 作 2 更 新 計 數 器 :PC = PC + 4 階 段 (b): 解 碼 階 段
143 動 作 3 解 碼 : 將 IR 分 解 為 ( 運 算 代 碼 op, 暫 存 器 代 號 ra, rb, r c, 常 數 c5, c16, c24 等 欄 位 ) 階 段 (c): 執 行 階 段 動 作 4 執 行 : 根 據 運 算 代 碼 op, 執 行 對 應 的 動 作 執 行 階 段 的 動 作 根 據 指 令 的 類 型 而 有 所 不 同 舉 例 而 言, 假 如 執 行 的 指 令 是 ADD R1, R2, R1, 那 麼 執 行 階 段 所 進 行 的 動 作 如 下 : 格 式 指 令 OP 說 明 語 法 執 行 動 作 L LD 00 載 入 word LD Ra, [Rb+Cx] R[ra] = m[rb+c16] (4byte) L ST 01 儲 存 word ST Ra, [Rb+Cx] m[rb+c16] = R[ra] (4byte) A ADD 13 加 法 ADD Ra, Rb, Rc R[ra] = R[rb]+R[rc] J JMP 26 跳 躍 ( 無 條 件 ) JMP Cx PC = PC+c24 CPU0m 模 組 以 下 就 是 我 們 所 設 計 的 CPU0m 模 組, 以 及 測 試 的 主 程 式, 我 們 在 程 式 中 寫 了 詳 細 的 說 明, 請 讀 者 對 照 閱 讀 檔 案 :CPU0m `define PC R[15] // 程 式 計 數 器 PC 其 實 是 R[15] 的 別 名 module CPU(input clock); // CPU0-Mini 的 快 取 版 :cpu0m 模 組 parameter [7:0] LD = 8'h00, ST=8'h01, ADD=8'h13, JMP=8'h26; // 支 援 4 個 指 令 reg signed [31:0] R [0:15]; // 宣 告 暫 存 器 R[0..15] 等 16 個 32 位 元 暫 存 器 reg signed [31:0] IR; // 指 令 暫 存 器 IR reg [7:0] m [0:128]; // 內 部 的 快 取 記 憶 體 reg [7:0] op; // 變 數 : 運 算 代 碼 op reg [3:0] ra, rb, rc; // 變 數 : 暫 存 器 代 號 ra, rb, rc reg signed [11:0] cx12; // 變 數 :12 位 元 常 數 cx12 reg signed [15:0] cx16; // 變 數 :16 位 元 常 數 cx16 reg signed [23:0] cx24; // 變 數 :24 位 元 常 數 cx24 reg signed [31:0] addr; // 變 數 : 暫 存 記 憶 體 位 址 initial // 初 始 化
144 1 2 begin `PC = 0; // 將 PC 設 為 起 動 位 址 0 R[0] = 0; // 將 R[0] 暫 存 器 強 制 設 定 為 0 {m[0],m[1],m[2],m[3]} = 32'h001F0018; // 0000 LD R1, K1 {m[4],m[5],m[6],m[7]} = 32'h002F0010; // 0004 LD R2, K0 {m[8],m[9],m[10],m[11]} = 32'h003F0014; // 0008 LD R3, SUM {m[12],m[13],m[14],m[15]}= 32'h ; // 000C LOOP: ADD R2, R2, R {m[16],m[17],m[18],m[19]}= 32'h ; // 0010 ADD R3, R3, R {m[20],m[21],m[22],m[23]}= 32'h26FFFFF4; // 0014 JMP LOOP {m[24],m[25],m[26],m[27]}= 32'h ; // 0018 K0: WORD 0 {m[28],m[29],m[30],m[31]}= 32'h ; // 001C K1: WORD 1 {m[32],m[33],m[34],m[35]}= 32'h ; // 0020 SUM: WORD 0 clock) begin // 在 clock 時 脈 的 正 邊 緣 時 觸 發 IR = {m[`pc], m[`pc+1], m[`pc+2], m[`pc+3]}; // 指 令 擷 取 階 段 :IR=m [PC], 4 個 Byte 的 記 憶 體 `PC = `PC+4; // 擷 取 完 成,PC 前 進 到 下 一 個 指 令 位 址 {op,ra,rb,rc,cx12} = IR; // 解 碼 階 段 : 將 IR 解 為 {op, ra, rb, rc, cx12} cx24 = IR[23:0]; // 解 出 IR[ 23:0] 放 入 cx24 cx16 = IR[15:0]; // 解 出 IR[ 15:0] 放 入 cx16 addr = R[rb]+cx16; // 記 憶 體 存 取 位 址 = PC+cx16 case (op) // 根 據 OP 執 行 對 應 的 動 作 LD: begin // 載 入 指 令 : R[ra] = m[addr] R[ra] = {m[addr], m[addr+1], m[addr+2], m[addr+3]}; $write("%4dns %8x : LD %x,%x,%-4x", $stime, `PC, ra, rb, cx16) ; ST: begin // 儲 存 指 令 : m[addr] = R[ra] {m[addr], m[addr+1], m[addr+2], m[addr+3]} = R[ra];
145 $write("%4dns %8x : ST %x,%x,%-4x", $stime, `PC, ra, rb, cx16) ; ADD: begin // 加 法 指 令 : R[ra] = R[rb]+R[rc] R[ra] = R[rb]+R[rc]; $write("%4dns %8x : ADD %x,%x,%-4x", $stime, `PC, ra, rb, rc); JMP:begin // 跳 躍 指 令 : PC = PC + cx24 `PC = `PC + cx24; // 跳 躍 目 標 位 址 =PC+cx $write("%4dns %8x : JMP %-8x", $stime, `PC, cx24); case $display(" R[%2d]=%4d", ra, R[ra]); // 顯 示 目 標 暫 存 器 的 值 module module main; reg clock; // 測 試 程 式 開 始 // 時 脈 clock 變 數 cpu cpu0m(clock); // 宣 告 cpu0m 處 理 器 initial clock = 0; // 一 開 始 clock 設 定 為 0 always #10 clock=~clock; // 每 隔 10 奈 秒 將 clock 反 相, 產 生 週 期 為 20 奈 秒 的 時 脈 initial #640 $finish; // 在 640 奈 秒 的 時 候 停 止 測 試 ( 因 為 這 時 的 R[1 ] 恰 好 是 =55 的 結 果 ) module 測 試 結 果 上 述 程 式 使 用 icarus 測 試 與 執 行 的 結 果 如 下 所 示 D:\Dropbox\Public\web\oc\code>iverilog -o cpu0m cpu0m.v D:\Dropbox\Public\web\oc\code>vvp cpu0m 10ns : LD 1,f,0018 R[ 1]= 1 30ns : LD 2,f,0010 R[ 2]= 0 50ns c : LD 3,f,0014 R[ 3]= 0
146 70ns : ADD 2,2,1 R[ 2]= 1 90ns : ADD 3,3,2 R[ 3]= 1 110ns c : JMP fffff4 R[15]= ns : ADD 2,2,1 R[ 2]= 2 150ns : ADD 3,3,2 R[ 3]= 3 170ns c : JMP fffff4 R[15]= ns : ADD 2,2,1 R[ 2]= 3 210ns : ADD 3,3,2 R[ 3]= 6 230ns c : JMP fffff4 R[15]= ns : ADD 2,2,1 R[ 2]= 4 270ns : ADD 3,3,2 R[ 3]= ns c : JMP fffff4 R[15]= ns : ADD 2,2,1 R[ 2]= 5 330ns : ADD 3,3,2 R[ 3]= ns c : JMP fffff4 R[15]= ns : ADD 2,2,1 R[ 2]= 6 390ns : ADD 3,3,2 R[ 3]= ns c : JMP fffff4 R[15]= ns : ADD 2,2,1 R[ 2]= 7 450ns : ADD 3,3,2 R[ 3]= ns c : JMP fffff4 R[15]= ns : ADD 2,2,1 R[ 2]= 8 510ns : ADD 3,3,2 R[ 3]= ns c : JMP fffff4 R[15]= ns : ADD 2,2,1 R[ 2]= 9 570ns : ADD 3,3,2 R[ 3]= ns c : JMP fffff4 R[15]= ns : ADD 2,2,1 R[ 2]= ns : ADD 3,3,2 R[ 3]= 55 從 上 述 輸 出 訊 息 當 中, 您 可 以 看 到 程 式 的 執 行 是 正 確 的, 其 中 R[2] 從 0, 1, 2,... 一 路 上 數, 而 R[3] 則 從 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55 一 路 累 加 上 來, 完 成 了 我 們 想 要 的 程 式 功 能 結 語 其 實 CPU0m 這 樣 的 設 計 應 該 還 不 能 稱 之 為 快 取, 而 是 在 程 式 不 大 的 情 況 之 下, 將 SRAM 直 接 包 入 在 CPU 當 中 的 一 種 作 法, 這 種 作 法 的 好 處 是 記 憶 體 存 取 速 度 很 快, 但 相 對 的 記 憶 體 成 本 也 很 貴, 因 為 這 些 記 憶 體 是 直 接 用 靜 態 記 憶 體 的 方 式 內 建 在 CPU 當 中 的 這 種 方 式 比 較 像 SOC 系 統 單 晶 片 的 做 法, 在 程 式 很 小 的 情 況 之 下, 直 接 將 記 憶 體 包 入 SOC 當 中, 會 得 到
147 比 較 高 速 的 電 路, 可 惜 的 是 這 種 做 法 不 像 目 前 的 電 腦 架 構 一 樣, 是 採 用 外 掛 DRAM 的 方 式, 可 以 大 幅 降 低 記 憶 體 的 成 本, 增 大 記 憶 體 的 容 量 就 是 了 CPU0 完 整 版 -- cpu0s CPU0 是 一 個 簡 易 的 32 位 元 單 匯 流 排 處 理 器, 其 架 構 如 下 圖 所 示, 包 含 R0..R15, IR, MAR, MDR 等 暫 存 器, 其 中 IR 是 指 令 暫 存 器, R0 是 一 個 永 遠 為 常 數 0 的 唯 讀 暫 存 器,R15 是 程 式 計 數 器 (Program Counter : PC),R14 是 連 結 暫 存 器 (Link Register : LR), R13 是 堆 疊 指 標 暫 存 器 (Stack Pointer : SP), 而 R12 是 狀 態 暫 存 器 (Status Word : SW) 圖 CPU0 的 架 構 圖 CPU0 的 指 令 集 CPU0 包 含 載 入 儲 存 運 算 指 令 跳 躍 指 令 堆 疊 指 令 等 四 大 類 指 令, 以 下 表 格 是 CPU0 的 指 令 編 碼 表, 記 載 了 CPU0 的 指 令 集 與 每 個 指 令 的 編 碼 格 式 指 令 OP 說 明 語 法 語 意 L LD 00 載 入 word LD Ra, [Rb+Cx] Ra=[Rb+Cx] L ST 01 儲 存 word ST Ra, [Rb+Cx] Ra=[Rb+Cx] L LDB 02 載 入 byte LDB Ra, [Rb+Cx] Ra=(byte)[Rb+Cx] L STB 03 儲 存 byte STB Ra, [Rb+Cx] Ra=(byte)[Rb+Cx] A LDR 04 LD 的 暫 存 器 版 LDR Ra, [Rb+Rc] Ra=[Rb+Rc] A STR 05 ST 的 暫 存 器 版 STR Ra, [Rb+Rc] Ra=[Rb+Rc] A LBR 06 LDB 的 暫 存 器 版 LBR Ra, [Rb+Rc] Ra=(byte)[Rb+Rc]
148 A SBR 07 STB 的 暫 存 器 版 SBR Ra, [Rb+Rc] Ra=(byte)[Rb+Rc] L LDI 08 載 入 常 數 LDI Ra, Cx Ra=Cx A CMP 10 比 較 CMP Ra, Rb SW=Ra >=< Rb A MOV 12 移 動 MOV Ra, Rb Ra=Rb A ADD 13 加 法 ADD Ra, Rb, Rc Ra=Rb+Rc A SUB 14 減 法 SUB Ra, Rb, Rc Ra=Rb-Rc A MUL 15 乘 法 MUL Ra, Rb, Rc Ra=Rb*Rc A DIV 16 除 法 DIV Ra, Rb, Rc Ra=Rb/Rc A AND 18 邏 輯 AND AND Ra, Rb, Rc Ra=Rb and Rc A OR 19 邏 輯 OR OR Ra, Rb, Rc Ra=Rb or Rc A XOR 1A 邏 輯 XOR XOR Ra, Rb, Rc Ra=Rb xor Rc A ADDI 1B 常 數 加 法 ADDI Ra, Rb, Cx Ra=Rb + Cx A ROL 1C 向 左 旋 轉 ROL Ra, Rb, Cx Ra=Rb rol Cx A ROR 1D 向 右 旋 轉 ROR Ra, Rb, Cx Ra=Rb ror Cx A SHL 1E 向 左 移 位 SHL Ra, Rb, Cx Ra=Rb << Cx A SHR 1F 向 右 移 位 SHR Ra, Rb, Cx Ra=Rb >> Cx J JEQ 20 跳 躍 ( 相 等 ) JEQ Cx if SW(=) PC=PC+Cx J JNE 21 跳 躍 ( 不 相 等 ) JNE Cx if SW(!=) PC=PC+Cx J JLT 22 跳 躍 (<) JLT Cx if SW(<) PC=PC+Cx J JGT 23 跳 躍 (>) JGT Cx if SW(>) PC=PC+Cx J JLE 24 跳 躍 (<=) JLE Cx if SW(<=) PC=PC+Cx J JGE 25 跳 躍 (>=) JGE Cx if SW(>=) PC=PC+Cx J JMP 26 跳 躍 ( 無 條 件 ) JMP Cx PC=PC+Cx J SWI 2A 軟 體 中 斷 SWI Cx LR=PC; PC=Cx; INT=1 J CALL 2B 跳 到 副 程 式 CALL Cx LR=PC; PC=PC+Cx J RET 2C 返 回 RET PC=LR
149 J IRET 2D 中 斷 返 回 IRET PC=LR; INT=0 A PUSH 30 推 入 word PUSH Ra SP-=4; [SP]=Ra; A POP 31 彈 出 word POP Ra Ra=[SP]; SP+=4; A PUSHB 32 推 入 byte PUSHB Ra SP--; [SP]=Ra; (byte) A POPB 33 彈 出 byte POPB Ra Ra=[SP]; SP++; (byte) CPU0 指 令 格 式 CPU0 所 有 指 令 長 度 均 為 32 位 元, 這 些 指 令 也 可 根 據 編 碼 方 式 分 成 三 種 不 同 的 格 式, 分 別 是 A 型 J 型 與 L 型 大 部 分 的 運 算 指 令 屬 於 A (Arithmatic) 型, 而 載 入 儲 存 指 令 通 常 屬 於 L (Load & Store) 型, 跳 躍 指 令 則 通 常 屬 於 J (Jump) 型, 這 三 種 型 態 的 指 令 格 式 如 下 圖 所 示 圖 CPU0 的 指 令 格 式 狀 態 暫 存 器 R12 狀 態 暫 存 器 (Status Word : SW) 是 用 來 儲 存 CPU 的 狀 態 值, 這 些 狀 態 是 許 多 旗 標 的 組 合 例 如, 零 旗 標 (Zero, 簡 寫 為 Z) 代 表 比 較 的 結 果 為 0, 負 旗 標 (Negative, 簡 寫 為 N) 代 表 比 較 的 結 果 為 負 值, 另 外 常 見 的 旗 標 還 有 進 位 旗 標 (Carry, 簡 寫 為 C), 溢 位 旗 標 (Overflow, 簡 寫 為 V) 等 等 下 圖 顯 示 了 CPU0 的 狀 態 暫 存 器 格 式, 最 前 面 的 四 個 位 元 N Z C V 所 代 表 的, 正 是 上 述 的 幾 個 旗 標 值 圖 CPU0 中 狀 態 暫 存 器 SW 的 結 構 條 件 旗 標 的 N Z 旗 標 值 可 以 用 來 代 表 比 較 結 果 是 大 於 (>) 等 於 (=) 還 是 小 於 (<), 當 執 行 CMP Ra, Rb 動 作 後, 會 有 下 列 三 種 可 能 的 情 形 1. 若 Ra > Rb, 則 N=0, Z=0 2. 若 Ra < Rb, 則 N=1, Z=0
150 3. 若 Ra = Rb, 則 N=0, Z=1 如 此, 用 來 進 行 條 件 跳 躍 的 JGT JGE JLT JLE JEQ JNE 指 令, 就 可 以 根 據 SW 暫 存 器 當 中 的 N Z 等 旗 標 決 定 是 否 進 行 跳 躍 SW 中 還 包 含 中 斷 控 制 旗 標 I (Interrupt) 與 T (Trap), 用 以 控 制 中 斷 的 啟 動 與 禁 止 等 行 為, 假 如 將 I 旗 標 設 定 為 0, 則 CPU0 將 禁 止 所 有 種 類 的 中 斷, 也 就 是 對 任 何 中 斷 都 不 會 起 反 應 但 如 果 只 是 將 T 旗 標 設 定 為 0, 則 只 會 禁 止 軟 體 中 斷 指 令 SWI (Software Interrupt), 不 會 禁 止 由 硬 體 觸 發 的 中 斷 SW 中 還 儲 存 有 處 理 器 模 式 的 欄 位,M=0 時 為 使 用 者 模 式 (user mode) 與 M=1 時 為 特 權 模 式 (super mode) 等, 這 在 作 業 系 統 的 設 計 上 經 常 被 用 來 製 作 安 全 保 護 功 能 在 使 用 者 模 式 當 中, 任 何 設 定 狀 態 暫 存 器 R12 的 動 作 都 會 被 視 為 是 非 法 的, 這 是 為 了 進 行 保 護 功 能 的 緣 故 但 是 在 特 權 模 式 中, 允 許 進 行 任 何 動 作, 包 含 設 定 中 斷 旗 標 與 處 理 器 模 式 等 位 元, 通 常 作 業 系 統 會 使 用 特 權 模 式 (M=1), 而 一 般 程 式 只 能 處 於 使 用 者 模 式 (M=0) CPU0 處 理 器 的 Verilog 實 作 -- CPU0sc.v 檔 案 :cpu0sc.v `define PC R[15] // 程 式 計 數 器 `define LR R[14] // 連 結 暫 存 器 `define SP R[13] // 堆 疊 暫 存 器 `define SW R[12] // 狀 態 暫 存 器 // 狀 態 暫 存 器 旗 標 位 元 `define N `SW[31] // 負 號 旗 標 `define Z `SW[30] // 零 旗 標 `define C `SW[29] // 進 位 旗 標 `define V `SW[28] // 溢 位 旗 標 `define I `SW[7] // 硬 體 中 斷 許 可 `define T `SW[6] // 軟 體 中 斷 許 可 `define M `SW[0] // 模 式 位 元 module cpu0c(input clock); // CPU0-Mini 的 快 取 版 :cpu0mc 模 組 parameter [7:0] LD=8'h00,ST=8'h01,LDB=8'h02,STB=8'h03,LDR=8'h04,STR=8'h 05, LBR=8'h06,SBR=8'h07,ADDI=8'h08,CMP=8'h10,MOV=8'h12,ADD=8'h13,SUB=8'h1 4, MUL=8'h15,DIV=8'h16,AND=8'h18,OR=8'h19,XOR=8'h1A,ROL=8'h1C,ROR=8'h1D, SHL=8'h1E,SHR=8'h1F,JEQ=8'h20,JNE=8'h21,JLT=8'h22,JGT=8'h23,JLE=8'h24, JGE=8'h25,JMP=8'h26,SWI=8'h2A,CALL=8'h2B,RET=8'h2C,IRET=8'h2D,
151 PUSH=8'h30,POP=8'h31,PUSHB=8'h32,POPB=8'h33; reg signed [31:0] R [0:15]; // 宣 告 暫 存 器 R[0..15] 等 16 個 32 位 元 暫 存 器 reg signed [31:0] IR; // 指 令 暫 存 器 IR reg [7:0] m [0:256]; // 內 部 的 快 取 記 憶 體 reg [7:0] op; // 變 數 : 運 算 代 碼 op reg [3:0] ra, rb, rc; // 變 數 : 暫 存 器 代 號 ra, rb, rc reg [4:0] c5; // 變 數 :5 位 元 常 數 c5 reg signed [11:0] c12; // 變 數 :12 位 元 常 數 c12 reg signed [15:0] c16; // 變 數 :16 位 元 常 數 c16 reg signed [23:0] c24; // 變 數 :24 位 元 常 數 c24 reg signed [31:0] sp, jaddr, laddr, raddr; reg signed [31:0] temp; reg signed [31:0] pc; integer i; initial // 初 始 化 begin `PC = 0; // 將 PC 設 為 起 動 位 址 0 `SW = 0; R[0] = 0; // 將 R[0] 暫 存 器 強 制 設 定 為 0 $readmemh("cpu0s.hex", m); for (i=0; i < 255; i=i+4) begin $display("%8x: %8x", i, {m[i], m[i+1], m[i+2], m[i+3]}); clock) begin // 在 clock 時 脈 的 正 邊 緣 時 觸 發 pc = `PC; IR = {m[`pc], m[`pc+1], m[`pc+2], m[`pc+3]}; // 指 令 擷 取 階 段 :IR=m [PC], 4 個 Byte 的 記 憶 體 `PC = `PC+4; // 擷 取 完 成,PC 前 進 到 下 一 個 指 令 位 址 {op,ra,rb,rc,c12} = IR; // 解 碼 階 段 : 將 IR 解 為 {op, ra, rb, rc, c12} c5 = IR[4:0]; c24 = IR[23:0];
152 c16 = IR[15:0]; jaddr = `PC+c16; laddr = R[rb]+c16; raddr = R[rb]+R[rc]; case (op) // 根 據 OP 執 行 對 應 的 動 作 LD: begin // 載 入 指 令 : R[ra] = m[addr] R[ra] = {m[laddr], m[laddr+1], m[laddr+2], m[laddr+3]}; $display("%4dns %8x : LD R%-d R%-d 0x%x ; R%-2d=0x%8x=%-d", $stime, pc, ra, rb, c16, ra, R[ra], R[ra]); ST: begin // 儲 存 指 令 : m[addr] = R[ra] {m[laddr], m[laddr+1], m[laddr+2], m[laddr+3]} = R[ra]; $display("%4dns %8x : ST R%-d R%-d 0x%x ; R%-2d=0x%8x=%-d", $stime, pc, ra, rb, c16, ra, R[ra], R[ra]); LDB:begin // 載 入 byte; LDB Ra, [Rb+ Cx]; Ra<=(byte)[Rb+ Cx] R[ra] = { 24'b0, m[laddr] }; $display("%4dns %8x : LDB R%-d R%-d 0x%x ; R%-2d=0x%8x=%-d", $stime, pc, ra, rb, c16, ra, R[ra], R[ra]); STB:begin // 儲 存 byte; STB Ra, [Rb+ Cx]; Ra=>(byte)[Rb+ Cx] m[laddr] = R[ra][7:0]; $display("%4dns %8x : STB R%-d R%-d 0x%x ; R%-2d=0x%8x=%-d", $stime, pc, ra, rb, c16, ra, R[ra], R[ra]); LDR:begin // LD 的 Rc 版 ; LDR Ra, [Rb+Rc]; Ra<=[Rb+ Rc] R[ra] = {m[raddr], m[raddr+1], m[raddr+2], m[raddr+3]}; $display("%4dns %8x : LDR R%-d R%-d R%-d ; R%-2d=0x%8x=%-d ", $stime, pc, ra, rb, rc, ra, R[ra], R[ra]); STR:begin // ST 的 Rc 版 ; STR Ra, [Rb+Rc]; Ra=>[Rb+ Rc] {m[raddr], m[raddr+1], m[raddr+2], m[raddr+3]} = R[ra]; $display("%4dns %8x : STR R%-d R%-d R%-d ; R%-2d=0x%8x=%-d ", $stime, pc, ra, rb, rc, ra, R[ra], R[ra]);
153 LBR:begin // LDB 的 Rc 版 ; LBR Ra, [Rb+Rc]; Ra<=(byte)[Rb+ Rc] R[ra] = { 24'b0, m[raddr] }; $display("%4dns %8x : LBR R%-d R%-d R%-d ; R%-2d=0x%8x=%-d ", $stime, pc, ra, rb, rc, ra, R[ra], R[ra]); SBR:begin // STB 的 Rc 版 ; SBR Ra, [Rb+Rc]; Ra=>(byte)[Rb+ Rc] m[raddr] = R[ra][7:0]; $display("%4dns %8x : SBR R%-d R%-d R%-d ; R%-2d=0x%8x=%-d ", $stime, pc, ra, rb, rc, ra, R[ra], R[ra]); MOV:begin // 移 動 ; MOV Ra, Rb; Ra<=Rb R[ra] = R[rb]; $display("%4dns %8x : MOV R%-d R%-d ; R%-2d=0x%8x=%-d", $stime, pc, ra, rb, ra, R[ra], R[ra]); CMP:begin // 比 較 ; CMP Ra, Rb; SW=(Ra >=< Rb) temp = R[ra]-R[rb]; `N=(temp<0);`Z=(temp==0); $display("%4dns %8x : CMP R%-d R%-d ; SW=0x%x", $stime, pc, ra, rb, `SW); ADDI:begin // R[a] = Rb+c16; // 立 即 值 加 法 ; LDI Ra, Rb+Cx; Ra <=Rb + Cx R[ra] = R[rb]+c16; $display("%4dns %8x : ADDI R%-d R%-d %-d ; R%-2d=0x%8x=%-d", $ stime, pc, ra, rb, c16, ra, R[ra], R[ra]); ADD: begin // 加 法 指 令 : R[ra] = R[rb]+R[rc] R[ra] = R[rb]+R[rc]; $display("%4dns %8x : ADD R%-d R%-d R%-d ; R%-2d=0x%8x=%-d ", $stime, pc, ra, rb, rc, ra, R[ra], R[ra]); SUB:begin // 減 法 ; SUB Ra, Rb, Rc; Ra<=Rb-Rc R[ra] = R[rb]-R[rc]; $display("%4dns %8x : SUB R%-d R%-d R%-d ; R%-2d=0x%8x=%-d
154 ", $stime, pc, ra, rb, rc, ra, R[ra], R[ra]); MUL:begin // 乘 法 ; MUL Ra, Rb, Rc; Ra<=Rb*Rc R[ra] = R[rb]*R[rc]; $display("%4dns %8x : MUL R%-d R%-d R%-d ; R%-2d=0x%8x=%-d ", $stime, pc, ra, rb, rc, ra, R[ra], R[ra]); DIV:begin // 除 法 ; DIV Ra, Rb, Rc; Ra<=Rb/Rc R[ra] = R[rb]/R[rc]; $display("%4dns %8x : DIV R%-d R%-d R%-d ; R%-2d=0x%8x=%-d ", $stime, pc, ra, rb, rc, ra, R[ra], R[ra]); AND:begin // 位 元 AND; AND Ra, Rb, Rc; Ra<=Rb and Rc R[ra] = R[rb]&R[rc]; $display("%4dns %8x : AND R%-d R%-d R%-d ; R%-2d=0x%8x=%-d ", $stime, pc, ra, rb, rc, ra, R[ra], R[ra]); OR:begin // 位 元 OR; OR Ra, Rb, Rc; Ra<=Rb or Rc R[ra] = R[rb] R[rc]; $display("%4dns %8x : OR R%-d R%-d R%-d ; R%-2d=0x%8x=%-d ", $stime, pc, ra, rb, rc, ra, R[ra], R[ra]); XOR:begin // 位 元 XOR; XOR Ra, Rb, Rc; Ra<=Rb xor Rc R[ra] = R[rb]^R[rc]; $display("%4dns %8x : XOR R%-d R%-d R%-d ; R%-2d=0x%8x=%-d ", $stime, pc, ra, rb, rc, ra, R[ra], R[ra]); SHL:begin // 向 左 移 位 ; SHL Ra, Rb, Cx; Ra<=Rb << Cx R[ra] = R[rb]<<c5; $display("%4dns %8x : SHL R%-d R%-d %-d ; R%-2d=0x%8x=%-d ", $stime, pc, ra, rb, c5, ra, R[ra], R[ra]); SHR:begin // 向 右 移 位 ; SHR Ra, Rb, Cx; Ra<=Rb >> Cx R[ra] = R[rb]>>c5; $display("%4dns %8x : SHR R%-d R%-d %-d ; R%-2d=0x%8x=%-d ", $stime, pc, ra, rb, c5, ra, R[ra], R[ra]);
155 JMP:begin // 跳 躍 指 令 : PC = PC + cx24 `PC = `PC + c24; $display("%4dns %8x : JMP 0x%x ; PC=0x%x", $stime, pc, c24, `PC); JEQ:begin // 跳 躍 ( 相 等 ); JEQ Cx; if SW(=) PC PC +Cx if (`Z) `PC=`PC+c24; $display("%4dns %8x : JEQ 0x%08x ; PC=0x%x", $stime, pc, c24, `PC); JNE:begin // 跳 躍 ( 不 相 等 ); JNE Cx; if SW(!=) PC PC+Cx if (!`Z) `PC=`PC+c24; $display("%4dns %8x : JNE 0x%08x ; PC=0x%x", $stime, pc, c24, `PC); JLT:begin // 跳 躍 ( < ); JLT Cx; if SW(<) PC PC+Cx if (`N) `PC=`PC+c24; $display("%4dns %8x : JLT 0x%08x ; PC=0x%x", $stime, pc, c24, `PC); JGT:begin // 跳 躍 ( > ); JGT Cx; if SW(>) PC PC+Cx if (!`N&&!`Z) `PC=`PC+c24; $display("%4dns %8x : JGT 0x%08x ; PC=0x%x", $stime, pc, c24, `PC); JLE:begin // 跳 躍 ( <= ); JLE Cx; if SW(<=) PC PC+ Cx if (`N `Z) `PC=`PC+c24; $display("%4dns %8x : JLE 0x%08x ; PC=0x%x", $stime, pc, c24, `PC); JGE:begin // 跳 躍 ( >= ); JGE Cx; if SW(>=) PC PC+ Cx if (!`N `Z) `PC=`PC+c24; $display("%4dns %8x : JGE 0x%08x ; PC=0x%x", $stime, pc, c24, `PC);
156 SWI:begin // 軟 中 斷 ; SWI Cx; LR <= PC; PC <= Cx; INT <=1 `LR=`PC;`PC= c24; `I = 1'b1; $display("%4dns %8x : SWI 0x%08x ; PC=0x%x", $stime, pc, c24, `PC); CALL:begin // 跳 到 副 程 式 ; CALL Cx; LR<=PC; PC<=PC+Cx `LR=`PC;`PC=`PC + c24; $display("%4dns %8x : CALL 0x%08x ; PC=0x%x", $stime, pc, c24, `PC); RET:begin // 返 回 ; RET; PC <= LR `PC=`LR; $display("%4dns %8x : RET ; PC=0x%x", $stime, pc, `PC); if (`PC<0) $finish; IRET:begin // 中 斷 返 回 ; IRET; PC <= LR; INT<=0 `PC=`LR;`I = 1'b0; $display("%4dns %8x : IRET ; PC=0x%x", $stime, pc, `PC); PUSH:begin // 推 入 word; PUSH Ra; SP-=4;[SP]<=Ra; sp = `SP-4; `SP = sp; {m[sp], m[sp+1], m[sp+2], m[sp+3]} = R[ra ]; $display("%4dns %8x : PUSH R%-d ; R%-2d=0x%8x, SP=0 x%x", $stime, pc, ra, ra, R[ra], `SP); POP:begin // 彈 出 word; POP Ra; Ra=[SP];SP+=4; sp = `SP; R[ra]={m[sp], m[sp+1], m[sp+2], m[sp+3]}; `SP = sp+4; $display("%4dns %8x : POP R%-d ; R%-2d=0x%8x, SP=0 x%x", $stime, pc, ra, ra, R[ra], `SP); PUSHB:begin // 推 入 byte; PUSHB Ra; SP--;[SP]<=Ra;(byte) sp = `SP-1; `SP = sp; m[sp] = R[ra];
157 $display("%4dns %8x : PUSHB R%-d ; R[%-d]=0x%8x, SP= 0x%x", $stime, pc, ra, ra, R[ra], `SP); POPB:begin // 彈 出 byte; POPB Ra; Ra<=[SP];SP++;(byte) sp = `SP+1; `SP = sp; R[ra]=m[sp]; $display("%4dns %8x : POPB R%-d ; R[%-d]=0x%8x, SP= 0x%x", $stime, pc, ra, ra, R[ra], `SP); case module module main; reg clock; // 測 試 程 式 開 始 // 時 脈 clock 變 數 cpu0c cpu(clock); // 宣 告 cpu0mc 處 理 器 initial clock = 0; // 一 開 始 clock 設 定 為 0 always #10 clock=~clock; // 每 隔 10 奈 秒 將 clock 反 相, 產 生 週 期 為 20 奈 秒 的 時 脈 initial #2000 $finish; // 在 640 奈 秒 的 時 候 停 止 測 試 ( 因 為 這 時 的 R[1 ] 恰 好 是 =55 的 結 果 ) module 程 式 碼 解 析 與 執 行 在 上 一 章 的 CPU0mc.v 當 中, 我 們 直 接 使 用 下 列 程 式 將 機 器 碼 塞 入 到 記 憶 體 當 中, 但 是 這 樣 做 顯 然 彈 性 不 太 夠 1 2 {m[0],m[1],m[2],m[3]} = 32'h001F0018; // 0000 LD R1, K1 {m[4],m[5],m[6],m[7]} = 32'h002F0010; // 0004 LD R2, K0 {m[8],m[9],m[10],m[11]} = 32'h003F0014; // 0008 LD R3, SUM {m[12],m[13],m[14],m[15]}= 32'h ; // 000C LOOP: ADD R2, R2, R {m[16],m[17],m[18],m[19]}= 32'h ; // 0010 ADD R3, R3, R {m[20],m[21],m[22],m[23]}= 32'h26FFFFF4; // 0014 JMP LOOP {m[24],m[25],m[26],m[27]}= 32'h ; // 0018 K0: WORD 0 {m[28],m[29],m[30],m[31]}= 32'h ; // 001C K1: WORD 1
158 {m[32],m[33],m[34],m[35]}= 32'h ; // 0020 SUM: WORD 0 因 此, 在 本 章 的 CPU0sc.v 這 個 程 式 中, 我 們 採 用 讀 取 外 部 檔 案 的 方 式, 將 機 器 碼 寫 在 cpu0s.hex 這 個 檔 案 中, 然 後 再 用 下 列 指 令 將 該 16 進 位 的 機 器 碼 檔 案 讀 入 $readmemh("cpu0s.hex", m); 其 中 的 readmemh 是 一 個 可 以 讀 取 16 進 位 的 文 字 檔 的 函 數, 上 述 指 令 會 將 cpu0s.hex 這 個 檔 案 內 的 16 進 位 字 串 讀 入 到 記 憶 體 變 數 m 當 中 以 下 是 cpu0s.hex 的 完 整 內 容 輸 入 檔 :cpu0s.hex 00 DF 00 B6 // 0 LD R13, StackEnd // 4 ADDI R4, // 8 ADDI R5, D // c STR R4, [R13+R5] 04 6D // 10 LDR R6, [R13+R5] 07 5D // 14 SBR R5, [R13+R4] 06 6D // 18 LBR R6, [R13+R4] 08 E0 FF FF // 1C ADDI R14,R0,-1 30 E // 20 PUSH R // 24 ADD R8, R5, R // 28 SUB R8, R5, R // 2c MUL R8, R5, R // 30 DIV R8, R5, R // 34 AND R8, R5, R // 38 OR R8, R5, R4 1A // 3c XOR R8, R5, R4 1E // 40 SHL R8, R5, 3 1F // 44 SHR R8, R5, // 48 CMP R4, R // 4c JEQ L // 50 JGT L // 54 JGE L C // 58 JLT L // 5c JLE L // 60 JNE L // 64 JMP L1
159 A // 68 L1: ADDI R1, R0, 10 2B // 6c CALL SUM 31 E // 70 POP R14 2C // 74 RET 30 E // 78 SUM: PUSH R // 7c MOV R3, R0 // R3 = i = F // 80 LDB R4, k1 // R4 = // 84 ADDI R2, 0 // SUM = R2 = // 88 LOOP: ADD R2, R2, R3 // SUM = SUM + i // 8c ADD R3, R3, R4 // i = i // 90 CMP R3, R1 // if (i < R1) 24 FF FF F0 // 94 JLE LOOP // goto LOOP 01 2F 00 0D // 98 ST R2, s 03 3F 00 0D // 9c STB R3, i 31 E // a0 POP R14 2C // a4 RET // return 01 // a8 k1: BYTE 1 // char K1= // a9 s: WORD 0 // int s 00 // ad i: BYTE 0 // char i= // ae Stack: BYTE 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // b A 0B // b BA // ba StackEnd: WORD StackEnd // be Data: BYTE 0, 1, 2, 3, 4, 5, 6, 7, // c2 上 述 程 式 的 內 容, 大 致 是 先 準 備 好 堆 疊, 然 後 就 開 始 測 試 ADDI, STR, LDR, ADD, SUB,... 等 指 令 接 著 在 呼 叫 CMP R4, R5 之 後 進 行 跳 躍 測 試 動 作, 由 於 R4=4, R5=8, 所 以 CMP 的 結 果 會 是 小 於, 因 此 在 後 面 的 JEQ, JGT, JGE 等 指 令 都 不 會 真 的 跳 躍, 直 到 執 行 JLT L1 時 就 會 真 的 跳 到 L1 去 接 著 用 ADDI R1, R0, 10 將 R1 設 為 10, 然 後 就 用 CALL SUM 這 個 指 令 呼 叫 SUM 這 個 副 程 式, 於 是 跳 到 位 於 0x78 的 SUM: PUSH R14 這 一 行, 並 開 始 執 行 副 程 式, 該 副 程 式 會 計 算 R1 的 結 果, 放 在 R2 當 中, 並 在 最 後 用 STB R2, s 這 個 指 令 存 入 變 數 s 當 中, 然 後 在 執 行 完 RET 指 令 後 返 回 上 一 層, 也 就 是 0x70 行 的 POP R14 指 令, 接 著 在 執 行 RET 指 令 時, 由 於 此 時 R14 為 -1, 因 此 Verilog 程 式 就 在 完 成 RET 指 令 時 發 現 PC 已 經 小 於 0 了, 因 此 執 行 $finish` 指 令 停 止 整 個 程 式 RET:begin // 返 回 ; RET; PC <= LR `PC=`LR; $display("%4dns %8x : RET ; PC=0x%x", $stime, pc, `PC);
160 if (`PC<0) $finish; 執 行 結 果 有 了 上 述 的 程 式 cpu0sc.v 與 輸 入 的 機 器 碼 cpu0s.hex 檔 案 之 後, 我 們 就 可 以 用 下 列 指 令 進 行 編 譯 與 執 行, 以 下 是 該 程 式 編 譯 與 執 行 的 結 果 D:\verilog>iverilog -o cpu0sc cpu0sc.v D:\verilog>vvp cpu0sc WARNING: cpu0sc.v:40: $readmemh(cpu0s.hex): Not enough words in the file for the requested range [0:256] : 00df00b : : c: 054d : 046d : 075d : 066d c: 08e0ffff : 30e : : c: : : : c: 1a : 1e : 1f : c: : : : c c:
161 : : : a c: 2b : 31e : 2c : 30e c: : 024f : : c: : : 24fffff : 012f000d c: 033f000d a0: 31e a4: 2c a8: ac: b0: b4: b8: 0a0b bc: 00ba c0: c4: 0708xxxx c8: xxxxxxxx cc: xxxxxxxx d0: xxxxxxxx d4: xxxxxxxx d8: xxxxxxxx dc: xxxxxxxx e0: xxxxxxxx e4: xxxxxxxx e8: xxxxxxxx ec: xxxxxxxx f0: xxxxxxxx
162 000000f4: xxxxxxxx f8: xxxxxxxx fc: xxxxxxxx 10ns : LD R13 R15 0x00b6 ; R13=0x000000ba=186 30ns : ADDI R4 R0 4 ; R4 =0x =4 50ns : ADDI R5 R0 8 ; R5 =0x =8 70ns c : STR R4 R13 R5 ; R4 =0x =4 90ns : LDR R6 R13 R5 ; R6 =0x =4 110ns : SBR R5 R13 R4 ; R5 =0x =8 130ns : LBR R6 R13 R4 ; R6 =0x =8 150ns c : ADDI R14 R0-1 ; R14=0xffffffff=-1 170ns : PUSH R14 ; R14=0xffffffff, SP=0x000000b6 190ns : ADD R8 R5 R4 ; R8 =0x c=12 210ns : SUB R8 R5 R4 ; R8 =0x =4 230ns c : MUL R8 R5 R4 ; R8 =0x =32 250ns : DIV R8 R5 R4 ; R8 =0x =2 270ns : AND R8 R5 R4 ; R8 =0x =0 290ns : OR R8 R5 R4 ; R8 =0x c=12 310ns c : XOR R8 R5 R4 ; R8 =0x c=12 330ns : SHL R8 R5 3 ; R8 =0x =64 350ns : SHR R8 R5 2 ; R8 =0x =2 370ns : CMP R4 R5 ; SW=0x ns c : JEQ 0x ; PC=0x ns : JGT 0x ; PC=0x ns : JGE 0x ; PC=0x ns : JLT 0x c ; PC=0x ns : ADDI R1 R0 10 ; R1 =0x a=10 490ns c : CALL 0x ; PC=0x ns : PUSH R14 ; R14=0x , SP=0x000000b2 530ns c : MOV R3 R0 ; R3 =0x =0 550ns : LDB R4 R15 0x0024 ; R4 =0x =1 570ns : ADDI R2 R0 0 ; R2 =0x =0 590ns : ADD R2 R2 R3 ; R2 =0x =0 610ns c : ADD R3 R3 R4 ; R3 =0x =1 630ns : CMP R3 R1 ; SW=0x ns : JLE 0x00fffff0 ; PC=0x ns : ADD R2 R2 R3 ; R2 =0x =1
163 690ns c : ADD R3 R3 R4 ; R3 =0x =2 710ns : CMP R3 R1 ; SW=0x ns : JLE 0x00fffff0 ; PC=0x ns : ADD R2 R2 R3 ; R2 =0x =3 770ns c : ADD R3 R3 R4 ; R3 =0x =3 790ns : CMP R3 R1 ; SW=0x ns : JLE 0x00fffff0 ; PC=0x ns : ADD R2 R2 R3 ; R2 =0x =6 850ns c : ADD R3 R3 R4 ; R3 =0x =4 870ns : CMP R3 R1 ; SW=0x ns : JLE 0x00fffff0 ; PC=0x ns : ADD R2 R2 R3 ; R2 =0x a=10 930ns c : ADD R3 R3 R4 ; R3 =0x =5 950ns : CMP R3 R1 ; SW=0x ns : JLE 0x00fffff0 ; PC=0x ns : ADD R2 R2 R3 ; R2 =0x f= ns c : ADD R3 R3 R4 ; R3 =0x =6 1030ns : CMP R3 R1 ; SW=0x ns : JLE 0x00fffff0 ; PC=0x ns : ADD R2 R2 R3 ; R2 =0x = ns c : ADD R3 R3 R4 ; R3 =0x =7 1110ns : CMP R3 R1 ; SW=0x ns : JLE 0x00fffff0 ; PC=0x ns : ADD R2 R2 R3 ; R2 =0x c= ns c : ADD R3 R3 R4 ; R3 =0x =8 1190ns : CMP R3 R1 ; SW=0x ns : JLE 0x00fffff0 ; PC=0x ns : ADD R2 R2 R3 ; R2 =0x = ns c : ADD R3 R3 R4 ; R3 =0x =9 1270ns : CMP R3 R1 ; SW=0x ns : JLE 0x00fffff0 ; PC=0x ns : ADD R2 R2 R3 ; R2 =0x d= ns c : ADD R3 R3 R4 ; R3 =0x a= ns : CMP R3 R1 ; SW=0x ns : JLE 0x00fffff0 ; PC=0x ns : ADD R2 R2 R3 ; R2 =0x = ns c : ADD R3 R3 R4 ; R3 =0x b=11
164 1430ns : CMP R3 R1 ; SW=0x ns : JLE 0x00fffff0 ; PC=0x ns : ST R2 R15 0x000d ; R2 =0x = ns c : STB R3 R15 0x000d ; R3 =0x b= ns a0 : POP R14 ; R14=0x , SP=0x000000b6 1530ns a4 : RET ; PC=0x ns : POP R14 ; R14=0xffffffff, SP=0x000000ba 1570ns : RET ; PC=0xffffffff 結 語 從 本 章 的 內 容 中, 您 應 該 可 以 瞭 解 到 直 接 使 用 高 階 的 Verilog 流 程 式 語 法 來 設 計 處 理 器, 像 是 cpu0mc.v 與 cpu0sc.v, 都 是 相 當 容 易 的 事, 這 完 全 是 因 為 verilog 支 援 了 相 當 高 階 的 運 算, 像 是 +, -, *, /, &,, ^, <<, >> 等 運 算 的 原 故 不 過 在 上 述 程 式 當 中, 我 們 並 沒 有 支 援 硬 體 中 斷 的 功 能, 也 沒 有 實 作 軟 體 中 斷 SWI 的 函 數 呼 叫, 這 樣 CPU0sc.v 就 只 能 是 一 顆 單 工 (Single Task) 的 處 理 器, 而 無 法 支 援 多 工 (Multi Task) 的 功 能 了 在 下 一 章 當 中, 我 們 將 繼 續 擴 充 CPU0sc.v 這 個 程 式, 加 入 支 援 軟 硬 體 中 斷 的 功 能, 以 及 支 援 浮 點 運 算 的 功 能, 該 程 式 稱 為 CPU0ic.v (i 代 表 Interrupt, c 代 表 cache memory) 然 後 我 們 將 再 度 用 16 進 位 的 方 式, 寫 出 一 個 機 器 語 言 的 程 式, 可 以 同 時 執 行 兩 個 行 程 (Task), 並 且 每 隔 一 小 段 時 間 就 利 用 硬 體 中 斷 進 行 行 程 切 換, 以 示 範 如 何 設 計 一 個 可 以 支 援 多 工 能 力 的 CPU 處 理 器 參 考 文 獻 陳 鍾 誠 的 網 站 : 使 用 Verilog 設 計 CPU0 處 理 器 陳 鍾 誠 的 網 站 :CPU0-Mini 處 理 器 設 計
165 速 度 議 題 乘 法 與 除 法 for 迴 圈 的 實 作 方 法 最 簡 單 的 乘 法 器 是 移 位 乘 法 器, 這 種 乘 法 器 基 本 上 只 用 了 一 個 加 法 器 和 一 個 移 位 器 所 組 成, 電 路 上 而 言 相 當 簡 單, 但 缺 點 是 執 行 速 度 不 快, 以 下 是 一 個 32 位 元 的 移 位 乘 法 器 之 程 式 碼 參 考 : 檔 案 :shift_mult.v module multiplier(output reg [63:0] z, input [31:0] x, y); reg [31:0] a; integer i; y) begin a=x; z=0; // 初 始 化 為 0 for(i=0;i<31;i=i+1) begin if (y[i]) z = z + a; // 請 注 意, 這 是 block assignment =, 所 以 會 造 成 延 遲, 長 度 越 長 延 遲 越 久 a=a << 1; module module main; reg [31:0] a, b; wire [63:0] c; multiplier m(c, a, b); initial begin a = 17; b = 7; #10;
166 $display("a=%d b=%d c=%d", a, b, c); module 其 編 譯 執 行 結 果 如 下 : D:\Dropbox\Public\web\oc\code>iverilog -o mul32a mul32a.v D:\Dropbox\Public\web\oc\code>vvp mul32a a= 17 b= 7 c= 119 但 是 以 上 的 這 個 程 式, 採 用 了 for 迴 圈, 而 且 使 用 = 這 種 阻 隔 式 的 方 式, 應 該 會 相 當 耗 費 電 路 資 源, 筆 者 認 為 上 述 電 路 應 該 會 用 到 32 組 32 位 元 的 加 法 器, 這 樣 實 在 是 難 以 接 受 的 一 種 情 況, 所 以 我 們 接 下 來 將 採 用 只 有 一 組 加 法 器, 然 後 用 多 個 時 脈 的 方 式 來 設 計 乘 法 器 參 考 : 1. for loop verilog synthesis It is synthesizable but it is always advised that for loops are not to be used in RTL coding. This is because it consumes lot of resources (like area etc.etc). However u can use it in behavioral coding becuse we do not synthesize behavioral codes. 2. verilog for loop syntax In verilog,synthesizable of for loop and while loop deps on which tools you are using. But it is better dont use it in RTL because it reflects replica of hardware. 32 個 時 脈 的 實 作 方 法 module multiplier(output reg [63:0] z, output ready, input [31:0] x, y, input start, clk); reg [5:0] bit; reg [31:0] a; wire ready =!bit; initial bit = 0; posedge clk ) begin
167 if( ready && start ) begin bit = 32; z = 0; a = x; else begin bit = bit - 1; z = z << 1; if (y[bit]) z = z + a; stime, x, y, z, ready, bit); module module main; reg [31:0] a, b; wire [63:0] c; reg clk, start; wire ready; multiplier m(c, ready, a, b, start, clk); initial begin a = 17; b = 7; start = 1; clk = 0; #200; start = 0; #200; $finish; always #5 clk =!clk; // clk) stime, a, b, c, r eady);
168 module 執 行 結 果 D:\Dropbox\Public\web\oc\code>iverilog -o mul32b mul32b.v D:\Dropbox\Public\web\oc\code>vvp mul32b 5ns : x= 17 y= 7 z= 0 ready=0 b it=32 15ns : x= 17 y= 7 z= 0 ready=0 b it=31 25ns : x= 17 y= 7 z= 0 ready=0 b it=30 35ns : x= 17 y= 7 z= 0 ready=0 b it=29 45ns : x= 17 y= 7 z= 0 ready=0 b it=28 55ns : x= 17 y= 7 z= 0 ready=0 b it=27 65ns : x= 17 y= 7 z= 0 ready=0 b it=26 75ns : x= 17 y= 7 z= 0 ready=0 b it=25 85ns : x= 17 y= 7 z= 0 ready=0 b it=24 95ns : x= 17 y= 7 z= 0 ready=0 b it=23 105ns : x= 17 y= 7 z= 0 ready=0 b it=22 115ns : x= 17 y= 7 z= 0 ready=0 b it=21 125ns : x= 17 y= 7 z= 0 ready=0 b it=20 135ns : x= 17 y= 7 z= 0 ready=0 b it=19 145ns : x= 17 y= 7 z= 0 ready=0 b it=18 155ns : x= 17 y= 7 z= 0 ready=0 b
169 it=17 it=16 it=15 it=14 it=13 it=12 it=11 it=10 it= 9 it= 8 it= 7 it= 6 it= 5 it= 4 it= 3 it= 2 it= 1 it= 0 it=63 165ns : x= 17 y= 7 z= 0 ready=0 b 175ns : x= 17 y= 7 z= 0 ready=0 b 185ns : x= 17 y= 7 z= 0 ready=0 b 195ns : x= 17 y= 7 z= 0 ready=0 b 205ns : x= 17 y= 7 z= 0 ready=0 b 215ns : x= 17 y= 7 z= 0 ready=0 b 225ns : x= 17 y= 7 z= 0 ready=0 b 235ns : x= 17 y= 7 z= 0 ready=0 b 245ns : x= 17 y= 7 z= 0 ready=0 b 255ns : x= 17 y= 7 z= 0 ready=0 b 265ns : x= 17 y= 7 z= 0 ready=0 b 275ns : x= 17 y= 7 z= 0 ready=0 b 285ns : x= 17 y= 7 z= 0 ready=0 b 295ns : x= 17 y= 7 z= 0 ready=0 b 305ns : x= 17 y= 7 z= 17 ready=0 b 315ns : x= 17 y= 7 z= 51 ready=0 b 325ns : x= 17 y= 7 z= 119 ready=1 b 335ns : x= 17 y= 7 z= 238 ready=0 b
170 it=62 it=61 it=60 it=59 345ns : x= 17 y= 7 z= 476 ready=0 b 355ns : x= 17 y= 7 z= 952 ready=0 b 365ns : x= 17 y= 7 z= 1904 ready=0 b 375ns : x= 17 y= 7 z= 3808 ready=0 b 除 法 器 檔 案 : div32.v // 參 考 : // 參 考 : // a/b = q ; a%b = r; module divider(output reg [31:0] q, output [31:0] r, output ready, input [31:0] a,b, input start, clk); reg [63:0] ta, tb, diff; reg [5:0] bit; wire ready =!bit; initial bit = 0; assign r = ta[31:0]; posedge clk ) if( ready && start ) begin bit = 32; q = 0; ta = {32'd0, a}; tb = {1'b0, b,31'd0}; else begin diff = ta - tb; q = q << 1; if(!diff[63] ) begin ta = diff; q[0] = 1'd1;
171 tb = tb >> 1; bit = bit - 1; module module main; reg clk, start; reg [31:0] a, b; wire [31:0] q, r; wire ready; divider div(q,r,ready,a,b,start,clk); initial begin clk = 0; a = 90; b = 13; start = 1; #200; start = 0; #200; $finish; always #5 clk =!clk; clk) stime, a, b, q, r, ready); module 執 行 結 果 D:\Dropbox\Public\web\oc\code>iverilog -o div32 div32.v D:\Dropbox\Public\web\oc\code>vvp div32 5ns : a= 90 b= 13 q= 0 r= 90 ready= 0 15ns : a= 90 b= 13 q= 0 r= 90 ready= 0
172 ns : a= 90 b= 13 q= 0 r= 90 ready= 35ns : a= 90 b= 13 q= 0 r= 90 ready= 45ns : a= 90 b= 13 q= 0 r= 90 ready= 55ns : a= 90 b= 13 q= 0 r= 90 ready= 65ns : a= 90 b= 13 q= 0 r= 90 ready= 75ns : a= 90 b= 13 q= 0 r= 90 ready= 85ns : a= 90 b= 13 q= 0 r= 90 ready= 95ns : a= 90 b= 13 q= 0 r= 90 ready= 105ns : a= 90 b= 13 q= 0 r= 90 ready= 115ns : a= 90 b= 13 q= 0 r= 90 ready= 125ns : a= 90 b= 13 q= 0 r= 90 ready= 135ns : a= 90 b= 13 q= 0 r= 90 ready= 145ns : a= 90 b= 13 q= 0 r= 90 ready= 155ns : a= 90 b= 13 q= 0 r= 90 ready= 165ns : a= 90 b= 13 q= 0 r= 90 ready= 175ns : a= 90 b= 13 q= 0 r= 90 ready= 185ns : a= 90 b= 13 q= 0 r= 90 ready= 195ns : a= 90 b= 13 q= 0 r= 90 ready= 205ns : a= 90 b= 13 q= 0 r= 90 ready=
173 ns : a= 90 b= 13 q= 0 r= 90 ready= 225ns : a= 90 b= 13 q= 0 r= 90 ready= 235ns : a= 90 b= 13 q= 0 r= 90 ready= 245ns : a= 90 b= 13 q= 0 r= 90 ready= 255ns : a= 90 b= 13 q= 0 r= 90 ready= 265ns : a= 90 b= 13 q= 0 r= 90 ready= 275ns : a= 90 b= 13 q= 0 r= 90 ready= 285ns : a= 90 b= 13 q= 0 r= 90 ready= 295ns : a= 90 b= 13 q= 0 r= 90 ready= 305ns : a= 90 b= 13 q= 1 r= 38 ready= 315ns : a= 90 b= 13 q= 3 r= 12 ready= 325ns : a= 90 b= 13 q= 6 r= 12 ready= 335ns : a= 90 b= 13 q= 13 r= 6 ready= 345ns : a= 90 b= 13 q= 27 r= 3 ready= 355ns : a= 90 b= 13 q= 55 r= 2 ready= 365ns : a= 90 b= 13 q= 111 r= 2 ready= 375ns : a= 90 b= 13 q= 223 r= 2 ready= 385ns : a= 90 b= 13 q= 447 r= 2 ready=
174 0 395ns : a= 90 b= 13 q= 895 r= 2 ready= Booth 乘 法 器 參 考 : 維 基 百 科 : 布 斯 乘 法 演 算 法 以 下 範 例 來 自 維 基 百 科 Booth 算 法 範 例 : 考 慮 一 個 由 若 干 個 0 包 圍 著 若 干 個 1 的 正 的 [[ 二 進 制 ]] 乘 數, 比 如 , 積 可 以 表 達 為 : 其 中,M 代 表 被 乘 數 變 形 為 下 式 可 以 使 運 算 次 數 可 以 減 為 兩 次 : 事 實 上, 任 何 二 進 制 數 中 連 續 的 1 可 以 被 分 解 為 兩 個 二 進 制 數 之 差 :. 因 此, 我 們 可 以 用 更 簡 單 的 運 算 來 替 換 原 數 中 連 續 為 1 的 數 字 的 乘 法, 通 過 加 上 乘 數, 對 部 分 積 進 行 移 位 運 算, 最 後 再 將 之 從 乘 數 中 減 去 它 利 用 了 我 們 在 針 對 為 零 的 位 做 乘 法 時, 不 需 要 做 其 他 運 算, 只 需 移 位 這 一 特 點, 這 很 像 我 們 在 做 和 99 的 乘 法 時 利 用 99=100-1 這 一 性 質 這 種 模 式 可 以 擴 展 應 用 於 任 何 一 串 數 字 中 連 續 為 1 的 部 分 ( 包 括 只 有 一 個 1 的 情 況 ) 那 麼, 布 斯 算 法 遵 從 這 種 模 式, 它 在 遇 到 一 串 數 字 中 的 第 一 組 從 0 到 1 的 變 化 時 ( 即 遇 到 01 時 ) 執 行 加 法, 在 遇 到 這 一 串 連 續 1 的 尾 部 時 ( 即 遇 到 10 時 ) 執 行 減 法 這 在 乘 數 為 負 時 同 樣 有 效 當 乘 數 中 的 連 續 1 比 較 多 時 ( 形 成 比 較 長 的 1 串 時 ), 布 斯 算 法 較 一 般 的 乘 法 算 法 執 行 的 加 減 法 運 算 少 浮 點 數 運 算 浮 點 運 算 單 元 FALU // 輸 入 a, b 後 會 執 行 op 所 指 定 的 運 算, 然 後 將 結 果 放 在 暫 存 器 y 當 中 module falu(input [63:0] ia, input [63:0] ib, input [1:0] op, output reg [63:0] oy); real a, b, y;
175 or b or op) begin a = $bitstoreal(ia); b = $bitstoreal(ib); case (op) 2'b00: y = a + b; 2'b01: y = a - b; 2'b10: y = a * b; 2'b11: y = a / b; case $display("falu32:op=%d a=%f b=%f y=%f", op, a, b, y); oy = $realtobits(y); module module main; reg [63:0] a64, b64; wire [63:0] y64; reg [1:0] op; real a, b; // 測 試 程 式 開 始 falu falu1(a64, b64, op, y64); // 建 立 一 個 alu 單 元, 名 稱 為 alu1 initial begin // 測 試 程 式 的 初 始 化 動 作 a = ; a64 = $realtobits(a); b = ; b64 = $realtobits(b); op = 0; always #50 begin // 每 個 50 奈 秒 就 作 下 列 動 作 op = op + 1; // 讓 op 的 值 加 1 initial #1000 $finish; // 時 間 到 1000 奈 秒 就 結 束 module 執 行 結 果
176 D:\Dropbox\Public\web\oc\code>iverilog -o flu64 flu64.v D:\Dropbox\Public\web\oc\code>vvp flu64 falu32:op=0 a= b= y= falu32:op=1 a= b= y= falu32:op=2 a= b= y= falu32:op=3 a= b= y= falu32:op=0 a= b= y= falu32:op=1 a= b= y= falu32:op=2 a= b= y= falu32:op=3 a= b= y= falu32:op=0 a= b= y= falu32:op=1 a= b= y= falu32:op=2 a= b= y= falu32:op=3 a= b= y= falu32:op=0 a= b= y= falu32:op=1 a= b= y= falu32:op=2 a= b= y= falu32:op=3 a= b= y= falu32:op=0 a= b= y= falu32:op=1 a= b= y= falu32:op=2 a= b= y= falu32:op=3 a= b= y= 使 用 Verilog 預 設 的 浮 點 數 運 算 檔 案 : float.v module main; real x, y, x2, y2, xyadd, xysub, xymul, xydiv; reg [63:0] x1, y1; initial begin x= ; y=-2.3e4; x1 = $realtobits(x); x2 = $bitstoreal(x1);
177 y1 = $realtobits(y); y2 = $bitstoreal(y1); xyadd = x+y; xysub = x-y; xymul = x*y; xydiv = x/y; $display("x=%f x1=%b x2=%f", x, x1, x2); $display("y=%f y1=%b y2=%f", y, y1, y2); $display("x+y=%f xyadd=%f", x+y, xyadd); $display("x-y=%f xysub=%f", x-y, xysub); $display("x*y=%f xymul=%f", x*y, xymul); $display("x/y=%f xydiv=%f", x/y, xydiv); module 執 行 結 果 : D:\Dropbox\Public\web\oc\code>iverilog -o float float.v D:\Dropbox\Public\web\oc\code>vvp float x= x1= x 2= y= y1= y2= x+y= xyadd= x-y= xysub= x*y= xymul= x/y= xydiv= 自 行 設 計 浮 點 運 算 器 // Reg27FP/FpMul.v // Reg27FP/FpAdd.v //
178 tml#schneider_fp `define F_SIGN 63 `define F_EXP 62:52 `define F_FRAC 51:0 // a = (-1)^a.s (1+a.f) * 2 ^ {a.e-1023} // b = (-1)^b.s (1+b.f) * 2 ^ {b.e-1023} // a*b = (-1)^(a.s xor b.s) (1+a.f) (1+b.f) * 2^{ (a.e+b.e-1023) } // z.s = a.s xor b.s z.f = tail(...) z.e = a.e+b.e-1023 module fmul(input [63:0] a, input [63:0] b, output [63:0] z); wire a_s = a[`f_sign]; wire [10:0] a_e = a[`f_exp]; wire [51:0] a_f = a[`f_frac]; wire b_s = b[`f_sign]; wire [10:0] b_e = b[`f_exp]; wire [51:0] b_f = b[`f_frac]; wire z_s = a_s ^ b_s;// 正 負 號 z.s = a.s xor b.s wire [105:0] f = {1'b1, a_f} * {1'b1, b_f}; // 小 數 部 分 : f = {1, a.f } * {1, b.f} wire [11:0] e = a_e + b_e - 12'd1023; // 指 數 部 份 : e = a.e + b.e wire [51:0] z_f = f[105]? f[104:53] : f[103:52]; // 若 最 高 位 f[105] == 1, 則 取 z.f[104:53], 否 則 取 z.f[103:52] wire [10:0] z_e = f[105]? e[10:0]+1 : e[10:0]; // 若 最 高 位 f[105] = = 1, 則 取 z.e 要 上 升 1 (???), 否 則 不 變 wire underflow = a_e[10] & b_e[10] & ~z_e[10]; // underflow assign z = underflow? 64'b0 : {z_s, z_e, z_f}; // 若 underflow, 則 傳 回 零, 否 則 傳 回 z={z.s, z.e, z.f} module module main; real x, y, z; reg [63:0] x1, y1; wire [63:0] z1;
179 fmul f1(x1, y1, z1); initial begin // x=7.00; y=-9.00; // x=6.00; y=8.00; // x=301.00; y=200.00; x=1.75; y=1.75; x1 = $realtobits(x); y1 = $realtobits(y); #100; $display("a.s=%b a.e=%b a.f=%b", f1.a_s, f1.a_e, f1.a_f); $display("a.s=%b b.e=%b b.f=%b", f1.b_s, f1.b_e, f1.b_f); $display("e=%b \nf=%b \nunderflow=%b", f1.e, f1.f, f1.underflow); $display("z.s=%b z.e=%b z.f=%b", f1.z_s, f1.z_e, f1.z_f); z = $bitstoreal(z1); $display("x=%f y=%f z=%f", x, y, z); $display("x1=%b \ny1=%b \nz1=%b", x1, y1, z1); module 執 行 結 果 D:\Dropbox\Public\web\oc\code>iverilog -o fpu64 fpu64.v D:\Dropbox\Public\web\oc\code>vvp fpu64 a.s=0 a.e= a.f= a.s=0 b.e= b.f= e= f= underflow=0 z.s=0 z.e= z.f=
180 00000 x= y= z= x1= y1= z1= 參 考 文 獻 繪 圖 加 速 功 能 (Graphics) 在 3D 的 遊 戲 或 動 畫 的 運 算 當 中, 經 常 要 計 算 向 量 的 加 法 內 積 的 浮 點 數 運 算, 而 且 這 些 運 算 通 常 獨 立 性 很 高, 可 以 採 用 平 行 的 方 式 計 算, 所 以 就 需 要 在 繪 圖 處 理 器 GPU 當 中 內 建 很 多 平 行 的 向 量 式 浮 點 運 算 器 來 加 速 此 一 計 算 過 程 舉 例 而 言, 當 我 們 想 計 算 下 列 的 N 維 向 量 加 法 時, 如 果 採 用 GPU 就 會 快 上 很 多 : for (i=0; i<n; i++) C[i] = A[i]+B[i]; 當 這 樣 的 程 式 被 放 到 GPU 去 執 行 時, 可 能 會 翻 譯 出 如 下 的 組 合 語 言 LOOP: LD R1, N LD R2, A LD R3, B LD R4, C VectorLoad V2, [R2] VectorLoad V3, [R3] VectorAdd V4, V2, V3 VectorStore V4, [R4] ADD R2, R2, 4*L ADD R3, R3, 4*L ADDd R4, R4, 4*L SUB R5, R5, L CMP R5, R0 JGE LOOP 如 果 上 述 GPU 的 一 次 可 以 計 算 的 浮 點 長 度 為 L 個, 那 麼 整 個 計 算 幾 乎 就 可 以 快 上 L 倍 了 GPU 通 常 有 著 與 CPU 不 同 的 指 令 集, 像 是 GPU 大 廠 NVIDIA 的 CUDA 就 是 一 種 GPU 指 令 集, NVIDIA
181 甚 至 還 為 CUDA 設 計 了 一 種 擴 充 式 的 C 語 言 -- 稱 為 CUDA C, 這 種 C 語 言 可 以 用 標 記 指 定 哪 些 部 份 應 該 展 開 到 CPU 當 中, 哪 些 應 該 展 開 到 GPU 當 中, 以 及 如 何 有 效 的 運 用 GPU 進 行 向 量 計 算 等 等 甚 至 CUDA 還 提 供 了 專 用 的 函 式 庫, 以 便 讓 CUDA C 能 夠 方 便 的 呼 叫 這 些 常 用 的 繪 圖 函 數 另 外 為 了 讓 各 家 廠 商 的 CPU 與 GPU 可 以 更 有 效 的 合 作, 甚 至 有 組 織 制 定 了 一 種 稱 為 OpenCL 的 標 準, 可 以 讓 各 家 廠 商 的 CPU 與 GPU 可 以 在 一 個 標 準 架 構 下 進 行 協 同 運 算, 以 便 有 效 的 運 用 這 些 異 質 處 理 器 的 效 能 平 行 處 理 (Parallel) 由 於 散 熱 等 因 素 無 法 克 服, 目 前 的 處 理 器 頻 率 已 經 不 容 易 再 快 速 往 上 調 整, 但 是 晶 片 的 密 度 與 容 量 還 再 持 續 增 加, 於 是 處 理 器 內 的 平 行, 也 就 是 多 核 心 的 情 況 就 愈 來 愈 普 遍 了 目 前 雙 核 心 四 核 心 八 核 心 甚 至 16 核 心 的 處 理 器 已 經 很 常 見 了, 在 可 見 的 未 來, 或 許 成 百 上 千 核 心 的 處 理 器 也 會 被 開 發 出 來, 因 此 如 何 運 用 平 行 技 術 充 份 利 用 這 麼 多 核 心 將 會 是 一 個 重 要 的 課 題 另 外 網 路 雲 端 運 算 的 需 求 不 斷 增 強, 也 會 進 一 步 增 加 多 處 理 器 技 術 的 重 要 性, 像 是 Google 提 出 的 MapReduce 就 在 大 數 據 的 潮 流 下 愈 來 愈 形 重 要, 而 MPI 與 Hadoop 等 分 散 式 平 行 處 理 技 術 也 就 在 這 種 情 況 下 逐 漸 普 及 了 對 於 平 行 計 算 的 架 構, 有 一 種 相 當 好 的 分 類 方 式, 是 根 據 指 令 與 資 料 是 單 數 還 複 數 所 進 行 的 分 類, 這 種 分 類 法 將 平 行 架 構 分 為 單 指 令 多 資 料 (SIMD), 多 指 令 單 資 料 (MISD), 多 指 令 多 資 料 (MIMD) 等 架 構, 在 加 上 傳 統 非 平 行 化 的 單 指 令 單 資 料 (SISD) 等 形 成 一 個 2*2 的 矩 陣 舉 例 而 言, 像 是 上 述 的 GPU 向 量 架 構, 是 屬 於 SIMD 的 平 行 架 構, 而 下 圖 中 的 UMA 與 NUMA 架 構, 則 是 屬 於 MIMD 的 平 行 架 構 當 然 在 上 述 架 構 下, 每 個 處 理 器 理 又 有 自 己 的 cache, 如 何 保 持 這 些 cache 的 一 至 性 就 會 是 個 問 題, 而 解 決 這 些 問 題 所 依 賴 的 方 法 仍 然 是 與 快 取 一 至 性 中 的 所 使 用 的 寫 穿 (write-through) 和 寫 回 (write-back) 等 方 法 類 似, 只 是 規 模 要 放 大 到 整 個 網 路 上 的 快 取 而 已 結 語 目 前 在 本 書 當 中, 我 們 對 於 高 階 處 理 器 的 實 作 還 很 缺 乏, 像 是 快 取 MMU 與 pipeline 等 部 份 的 實 作 都 還 沒 有 完 成, 因 此 還 無 法 完 全 實 現 開 放 電 腦 計 畫 硬 體 部 份 的 目 標
182 不 過 在 探 索 過 程 當 中, 筆 者 對 硬 體 領 域 開 始 有 了 更 深 一 層 的 瞭 解, 希 望 未 來 能 夠 將 這 些 部 份 實 作 好 之 後, 盡 快 加 入 到 本 書 裏 面 到 時 隨 著 本 書 進 化 成 第 二 版 第 三 版..., 相 信 讀 者 與 我 對 電 腦 硬 體 的 理 解 也 會 變 得 愈 來 愈 深 入 了
183 附 錄 本 書 內 容 與 相 關 資 源 主 題 投 影 片 實 作 程 式 教 學 影 片 第 1 章. 開 放 電 腦 計 畫 第 2 章. 電 腦 硬 體 架 構 co01_overview.pdf 計 算 機 結 構 : 簡 介 1 計 算 機 結 構 : 簡 介 第 3 章. 硬 體 描 述 語 言 -- Verilog - 區 塊 式 設 計 - 流 程 式 設 計 Icarus Verilog xor3.v Quartus II DE 第 4 章. 組 合 邏 輯 多 工 器 mux.v 全 加 器 4 位 元 加 法 器 [adder4.v] 4 位 元 加 減 器 [addsub4.v] 4 位 元 快 速 加 法 器 N 位 元 加 法 器 乘 法 器 移 位 乘 法 器 mult4.v shift_mult.v 除 法 器 浮 點 乘 法 器 [fmult4.v]
184 第 5 章. 算 術 邏 輯 單 元 算 術 邏 輯 單 元 ALU [alu.v] 第 6 章. 記 憶 單 元 正 反 器 栓 鎖 器 latch.v 計 數 器 counter.v 狀 態 機 多 工 器 mux.v 暫 存 器 暫 存 器 群 regbank.v 8 位 元 記 憶 體 memory8.v 32 位 元 記 憶 體 memory32.v 第 7 章. 控 制 單 元 第 8 章. 微 處 理 器 - MCU0 指 令 集 - MCU0 迷 你 版 - MCU0 迷 你 版 ( 區 塊 設 計 ) - MCU0 完 整 版 第 9 章. 中 斷 與 輸 出 入 - MCU0 中 斷 處 理 - MCU0 的 輸 出 入 第 10 章. 記 憶 系 統 - 記 憶 體 階 層 快 取 記 憶 體 第 11 章. 高 階 處 理 器
185 哈 佛 架 構 流 水 線 - CPU0 指 令 集 - CPU0 迷 你 版 - CPU0 完 整 版 第 12 章. 速 度 議 題 乘 法 與 除 法 浮 點 運 算 單 元 FPU 繪 圖 加 速 功 能 平 行 處 理 結 語
6-1-1極限的概念
選 修 數 學 (I-4 多 項 式 函 數 的 極 限 與 導 數 - 導 數 與 切 線 斜 率 定 義. f ( 在 的 導 數 : f ( h 對 實 函 數 f ( 若 極 限 存 在 h h 則 稱 f ( 在 點 可 微 分 而 此 極 限 值 稱 為 f ( 在 的 導 數 以 f ( 表 示 f ( f ( 函 數 f ( 在 的 導 數 也 可 以 表 成 f ( 註 : 為 了
Microsoft Word - 10100000191.doc
臺 灣 集 中 保 管 結 算 所 股 份 有 限 公 司 辦 理 認 購 ( 售 ) 權 證 帳 簿 劃 撥 作 業 配 合 事 項 部 分 條 文 修 正 條 文 對 照 表 附 件 1 修 正 條 文 現 行 條 文 說 明 第 五 章 認 購 ( 售 ) 權 證 之 權 利 行 使 第 一 節 認 購 權 證 採 證 券 給 付 或 以 證 券 給 付 之 認 購 權 證 發 行 人 得 選
所 3 學 分 課 程, 及 兩 門 跨 領 域 課 程 共 6 學 分 以 上 課 程 學 生 在 修 課 前, 必 須 填 寫 課 程 修 課 認 定 表, 經 班 主 任 或 指 導 教 授 簽 名 後 始 認 定 此 課 程 學 分 ) 10. 本 規 章 未 盡 事 宜, 悉 依 學 位
95 年 訂 定 96 年 11 月 修 正 97 年 10 月 修 正 100 年 2 月 修 正 101 年 4 月 修 正 102 年 1 月 修 正 103 年 4 月 修 正 103 學 年 度 入 學 新 生 適 用, 舊 生 可 比 照 適 用 1. 研 究 生 須 於 入 學 後 第 二 學 期 開 學 前 選 定 指 導 教 授, 經 課 程 委 員 會 認 定 後 方 得 繼 續
Microsoft Word - 第四章.doc
第 四 章 - 試 分 別 說 明 組 合 邏 輯 電 路 與 序 向 邏 輯 電 路 之 定 義 解 : 組 合 邏 輯 電 路 由 基 本 邏 輯 閘 所 組 成 的 此 種 邏 輯 電 路 之 輸 出 為 電 路 所 有 輸 入 的 組 合 因 此 輸 出 狀 態 可 完 全 由 目 前 之 輸 入 來 決 定 而 組 合 邏 輯 電 路 之 示 意 圖 如 圖 所 a 示 ; 而 序 向 邏
寫 作 背 景 導 讀 [98] L Lyman Frank Baum 1856-1919 1882 1886 1900 1939
綠 野 仙 蹤 繪 本 創 意 教 案 教 案 設 計 / 朱 秀 芳 老 師 28 寫 作 背 景 導 讀 [98] L Lyman Frank Baum 1856-1919 1882 1886 1900 1939 故 事 簡 介 綠 野 仙 蹤 心 得 分 享 [99] 處 處 有 仙 蹤 繪 本 創 意 教 案 設 計 者 : 朱 秀 芳 適 用 年 級 : 授 課 時 間 :200 教 學
第 6. 節 不 定 積 分 的 基 本 公 式 我 們 可 以 把 已 經 知 道 反 導 函 數 之 所 有 函 數 都 視 為 不 定 積 分 的 基 本 公 式 基 本 公 式 涵 蓋 的 範 圍 愈 大, 我 們 求 解 積 分 就 愈 容 易, 但 有 記 憶 不 易 的 情 事 研 讀
第 6. 節 反 導 函 數 與 不 定 積 分 定 義 6.. 反 導 函 數 說 明 : 第 六 章 求 積 分 的 方 法 若 F( ) f ( ), Df, 則 F ( ) 為 f( ) 之 反 導 函 數 (antierivative) () 當 F ( ) 為 f( ) 之 反 導 函 數 時, 則 F( ) C,C 為 常 數, 亦 為 f( ) 之 反 導 函 數 故 若 反 導 函
Microsoft Word - ch07
五 本 要 點 補 助 款 之 請 撥 及 核 結, 依 下 列 規 定 辦 理 : ( 一 ) 補 助 經 費 由 本 署 直 接 撥 付 至 地 方 政 府 經 費 代 管 學 校 及 其 他 學 校 ( 二 ) 聯 絡 處 及 校 外 會 應 檢 附 收 據, 向 經 費 代 管 學 校 或 地 方 政 府 辦 理 核 銷, 原 始 支 出 憑 證 由 經 費 核 銷 單 位 留 存 備 查
章節
試 題 阿 財 每 年 年 初 存 入 銀 行 0000 元, 年 利 率 %, 每 年 計 息 一 次, () 若 依 單 利 計 息, 則 第 0 年 年 底 的 本 利 和 多 少? () 若 依 複 利 計 息, 則 第 0 年 年 底 的 本 利 和 約 為 多 少?( 近 似 值 :0 0 計 ) 編 碼 0044 難 易 中 出 處 高 雄 中 學 段 考 題 解 答 ()000 元
證 券 簡 易 下 單 :2121 證 券 簡 易 下 單 1. 主 工 具 列 的 視 窗 搜 尋 器 直 接 輸 入 2121 2. 點 擊 主 選 單 證 券 專 區 下 單 特 殊 下 單 2121 證 券 簡 易 下 單 畫 面 說 明 1. 下 單 區 2. 個 股 行 情 資 訊 與
下 單 :2111 證 券 快 速 下 單 1. 主 工 具 列 的 視 窗 搜 尋 器 直 接 輸 入 2111 2. 點 擊 主 選 單 證 券 專 區 下 單 一 般 下 單 2111 證 券 快 速 下 單 1. 點 擊 後, 可 選 擇 群 組 帳 號 或 單 一 帳 號, 選 擇 後 快 速 點 擊 滑 鼠 左 鍵 兩 下, 可 將 帳 號 完 成 登 錄 並 帶 入 視 窗 2. 點
<4D6963726F736F667420576F7264202D20B3E6A4B830312D2D2DBCC6BD75BB50BEE3BCC6AABAA55BB4EEB942BAE22E646F6378>
國 中 數 學 基 本 學 習 內 容 補 救 教 材 第 一 冊 一 -1 單 元 一 數 線 與 整 數 的 加 減 運 算 主 題 一 正 數 負 數 的 意 義 一 正 數 和 負 數 : 尋 找 寶 藏 北 西 東 小 明 南 小 明 無 意 間 得 到 了 一 張 藏 寶 圖, 圖 上 的 黑 點 代 表 小 明 現 在 站 的 地 方, 每 個 腳 印 都 代 表 1 步 若 要 在
目 錄 壹 題 目 1: 新 增 商 品 ( 商 品 名 稱 為 玉 井 芒 果 乾 禮 盒 )... 3 貳 題 目 2: 新 增 商 品 ( 商 品 名 稱 為 紅 磚 布 丁 精 選 禮 盒 )... 5 參 題 目 3: 新 增 商 品 ( 商 品 名 稱 為 晶 鑽 XO 醬 禮 盒 ).
行 動 電 子 商 務 管 理 師 行 動 電 子 商 務 規 劃 師 術 科 考 試 題 解 製 作 單 位 :TMCA 台 灣 行 動 商 務 運 籌 管 理 協 會 證 照 評 測 試 務 中 心 1 目 錄 壹 題 目 1: 新 增 商 品 ( 商 品 名 稱 為 玉 井 芒 果 乾 禮 盒 )... 3 貳 題 目 2: 新 增 商 品 ( 商 品 名 稱 為 紅 磚 布 丁 精 選 禮
目 錄 項 目 內 容 頁 數 1 手 機 要 求 3 2 登 記 程 序 3 3 登 入 程 序 4 4 輸 入 買 賣 指 示 6 5 更 改 指 示 14 6 取 消 指 示 18 7 查 詢 股 票 結 存 21 8 查 詢 買 賣 指 示 23 9 更 改 密 碼 24 10 查 詢 股
流 動 股 票 買 賣 服 務 操 作 指 引 目 錄 項 目 內 容 頁 數 1 手 機 要 求 3 2 登 記 程 序 3 3 登 入 程 序 4 4 輸 入 買 賣 指 示 6 5 更 改 指 示 14 6 取 消 指 示 18 7 查 詢 股 票 結 存 21 8 查 詢 買 賣 指 示 23 9 更 改 密 碼 24 10 查 詢 股 價 及 指 數 26 11 切 換 語 言 及 登 出
CONTENTS 訓 練 內 容 設 計 法 056 淡 季 期 的 訓 練 058 旺 季 期 的 訓 練 060 針 對 爬 坡 賽 的 訓 練 內 容 062 賽 後 的 資 料 分 析 064 067 PART4/ 鏑 木 毅 先 生 的 建 言 活 用 於 越 野 路 跑 的 心 跳 訓
BOOK 山 與 溪 谷 社 編 堀 內 一 雄 執 筆 蕭 雲 菁 譯 CONTENTS 訓 練 內 容 設 計 法 056 淡 季 期 的 訓 練 058 旺 季 期 的 訓 練 060 針 對 爬 坡 賽 的 訓 練 內 容 062 賽 後 的 資 料 分 析 064 067 PART4/ 鏑 木 毅 先 生 的 建 言 活 用 於 越 野 路 跑 的 心 跳 訓 練 068 心 率 計 為
Microsoft Word - Draft circular on Sub Leg - 11 Apr (chi)_Traditional
檔 號 : (20) in EDB(SCR) 25/58/11 Pt.4 教 育 局 通 告 第 3/2012 號 2012 年 教 育 ( 修 訂 ) 規 例 2012 年 教 育 ( 豁 免 )( 提 供 非 正 規 課 程 的 私 立 學 校 )( 修 訂 ) 令 2012 年 香 港 考 試 及 評 核 局 條 例 ( 修 訂 附 表 1) 令 [ 注 意 : 本 通 告 應 交 ( a )
授 課 老 師 章 節 第 一 章 教 學 教 具 間 3 分 鐘 粉 筆 CNC 銑 床 教 學 內 容 CNC 銑 床 之 基 本 操 作 教 材 來 源 數 值 控 制 機 械 實 習 Ⅰ 1. 了 解 CNC 銑 床 的 發 展 2. 了 解 CNC 銑 床 刀 具 的 選 用 3. 了 解
台 中 市 財 團 法 人 光 華 高 級 工 業 職 業 學 校 專 業 科 目 - 數 值 控 制 機 械 教 案 本 適 用 科 別 : 機 械 科 製 圖 科 編 寫 單 位 : 光 華 高 工 機 械 製 圖 科 授 課 老 師 章 節 第 一 章 教 學 教 具 間 3 分 鐘 粉 筆 CNC 銑 床 教 學 內 容 CNC 銑 床 之 基 本 操 作 教 材 來 源 數 值 控 制 機
研究一:n人以『剪刀、石頭、布』猜拳法猜拳一次,決定一人勝
嘉 義 市 第 三 十 屆 中 小 學 科 學 展 覽 會 作 品 說 明 書 猜 拳 決 勝 負 的 最 佳 策 略 探 討 科 別 : 數 學 科 組 別 : 國 小 組 關 鍵 詞 : 剪 刀 石 頭 布 黑 白 猜 編 號 : 壹 摘 要 在 玩 遊 戲 時 往 往 需 要 運 用 猜 拳 剪 刀 石 頭 布 或 黑 白 猜 來 決 勝 負 或 是 分 組, 但 人 數 一 多, 便 無 法
(Microsoft Word - MOODLE990201\266i\266\245\244\342\245U1000804)
(2011.08.04 修 訂 ) 目 錄 壹 舊 課 程 複 製 到 新 課 程 的 方 法... 1 一 將 舊 課 程 的 課 程 文 件 匯 入 新 課 程... 1 二 編 輯 新 課 程... 5 三 備 份 舊 課 程 資 料 還 原 至 新 課 程... 6 貳 元 課 程 (META COURSE) 說 明 與 應 用... 12 一 元 課 程 說 明... 12 二 利 用 元
四 修 正 幼 兒 園 師 資 類 科 應 修 學 分 數 為 四 十 八 學 分, 並 明 定 學 分 數 抵 免 之 相 關 規 定 及 規 範 修 習 幼 兒 園 教 育 專 業 課 程 之 最 低 年 限 ( 修 正 條 文 第 五 條 ) 五 發 給 修 畢 師 資 職 前 教 育 證 明
公 告 及 送 達 教 育 部 公 告 中 華 民 國 103 年 11 月 21 日 臺 教 師 ( 二 ) 字 第 1030167058A 號 主 旨 : 預 告 修 正 幼 稚 園 及 托 兒 所 在 職 人 員 修 習 幼 稚 園 教 師 師 資 職 前 教 育 課 程 辦 法 草 案 依 據 : 行 政 程 序 法 第 一 百 五 十 一 條 第 二 項 準 用 第 一 百 五 十 四 條
內 政 統 計 通 報
內 政 統 通 報 一 一 年 第 四 週 100 年 居 家 服 務 使 用 者 度 調 查 結 果 內 政 部 統 處 8 成 5 的 居 家 服 務 使 用 者 對 居 家 服 務 所 提 供 的 各 項 服 務 表 示 有 7 成 5 表 示 會 介 紹 他 人 使 用 有 接 受 居 家 服 務 所 提 供 的 協 助 洗 澡 協 助 換 穿 衣 服 協 助 吃 飯 協 助 起 床 站 立
五 四 五 說 ( 代 序 ) 李 澤 厚 劉 再 復 I I II IV V VII 第 一 篇 五 四 新 文 化 運 動 批 評 提 綱 001 003 006 009 011 014 019 附 論 一 中 國 貴 族 精 神 的 命 運 ( 提 綱 ) 021 021 022 026 02
劉 再 復 著 與 李 澤 厚 李 歐 梵 等 共 論 五 四 共 鑒 五 四 五 四 五 說 ( 代 序 ) 李 澤 厚 劉 再 復 I I II IV V VII 第 一 篇 五 四 新 文 化 運 動 批 評 提 綱 001 003 006 009 011 014 019 附 論 一 中 國 貴 族 精 神 的 命 運 ( 提 綱 ) 021 021 022 026 028 附 論 二 誰 是
二 兒 歌 選 用 情 形 ( ) 2 ( ) ( ) 1. 158 2.
兒 歌 內 容 分 析 ~ 以 台 灣 省 教 育 廳 發 行 之 大 單 元 活 動 設 計 內 之 兒 歌 為 例 ~ 摘 要 82 76 158 一 兒 歌 類 目 的 分 布 情 形 ( ) 26 23 22 16 61 38.6 16.5 ( ) 二 兒 歌 選 用 情 形 ( ) 2 ( ) ( ) 1. 158 2. 第 一 章 緒 論 第 一 節 研 究 動 機 79 第 二 節 研
實德證券網上交易系統示範
實 德 證 券 網 上 交 易 系 統 示 範 實 德 證 券 網 上 交 易 系 統 分 別 提 供 增 強 版 及 標 準 版, 使 用 標 準 版 必 須 安 裝 JAVA, 標 準 版 自 動 更 新 戶 口 資 料, 而 使 用 增 強 版 則 不 必 安 裝 JAVA, 但 必 須 按 更 新 鍵 才 能 更 新 戶 口 資 料, 請 用 戶 根 據 實 際 需 要 選 擇 使 用 標
NCKU elearning Manual
成 績 一 簡 介... 3 二 成 績 彙 總... 4 三 瀏 覽 成 績... 7 1. 成 績 分 析 長 條 圖... 7 2. 成 績 單... 7 3. 用 戶 報 告... 11 四 類 別 和 項 目... 12 1. 簡 單 檢 視... 12 2. 完 整 檢 視... 15 五 成 績 匯 入... 16 六 成 績 匯 出... 19 1. 成 績 登 錄 檔... 19
16
序 1 16 序 2 KK KK KK KK KK KK 溫 溫 KK KK 周 婉 芬 博 士 2016 年 5 月 前 言 平 安 健 康 便 好 了 16 10 ICU ICU 26 300 26 10 ICU ICU 曾 錦 強 2016 年 5 月 目 錄 Chapter 1 家 庭 親 子 關 係 1.1 多 存 款 入 關 係 戶 口 2 1.2 不 傷 關 係 管 學 業 12 1.5
Microsoft PowerPoint - 資料庫正規化(ccchen).ppt
資 料 庫 正 規 化 正 規 化 的 概 念 何 謂 正 規 化 (Normalization)?? 就 是 結 構 化 分 析 與 設 計 中, 建 構 資 料 模 式 所 運 用 的 一 個 技 術, 其 目 的 是 為 了 降 低 資 料 的 重 覆 性 與 避 免 更 新 異 常 的 情 況 發 生 因 此, 就 必 須 將 整 個 資 料 表 中 重 複 性 的 資 料 剔 除, 否 則
第二組掃描器規範書
第 二 組 掃 描 器 規 範 書 1. A4 規 格 2400 DPI( 含 ) 以 上 掃 描 器 第 1 項 ) 1-1. 機 型 : 平 台 式 掃 瞄 器 1-2. 光 學 解 析 度 :2400x2400DPI( 含 ) 以 上 1-3. 最 大 輸 出 解 析 度 :9600DPI( 含 ) 以 上 1-4. 介 面 :SCSI 介 面 ( 附 介 面 卡 及 傳 輸 線 ) 或 USB
肆 研 究 方 法 進 行 本 研 究 前, 我 們 首 先 對 研 究 中 所 用 到 名 詞 作 定 義 定 義 : 牌 數 : 玩 牌 時 所 使 用 到 撲 克 牌 數 次 數 : 進 行 猜 心 術 遊 戲 時, 重 複 分 牌 次 數 數 : 進 行 猜 心 術 遊 戲 時, 每 次 分
摘 要 魔 術 師 讀 心 術 背 後 到 底 藏 了 多 少 祕 密? 一 般 觀 眾 心 裡 常 有 著 這 句 話 本 研 究 我 們 破 解 了 魔 術 師 透 過 數 學 規 律 加 上 置 中 手 法 完 成 一 連 串 騙 人 撲 克 牌 遊 戲, 也 學 會 了 如 何 透 過 整 理 表 格 方 式, 來 找 出 數 學 規 律, 也 更 懂 得 如 何 把 簡 單 數 學 技 巧
簽 呈
台 新 證 券 投 資 信 託 股 份 有 限 公 司 公 告 中 華 民 國 105 年 5 月 4 日 台 新 投 (105) 總 發 文 字 第 00116 號 主 旨 : 本 公 司 經 理 之 台 新 亞 美 短 期 債 券 證 券 投 資 信 託 基 金 等 3 檔 基 金 ( 以 下 合 稱 本 基 金 ), 修 正 證 券 投 資 信 託 契 約 暨 配 合 修 正 公 開 說 明
校 長 遴 選 者 就 相 關 遴 選 事 項, 有 程 序 外 之 接 觸 遴 選 會 委 員 在 任 期 間 因 故 無 法 執 行 任 務 或 有 不 適 當 之 行 為 者, 由 各 該 主 管 機 關 解 聘 之 ; 其 缺 額, 依 第 一 項 至 第 五 項 規 定 聘 ( 派 ) 委
高 級 中 等 學 校 校 長 遴 選 聘 任 及 辦 學 績 效 考 評 辦 法 修 正 對 照 表 中 華 民 國 一 百 零 二 年 十 二 月 二 十 日 教 育 部 臺 教 授 國 部 字 第 1020118431A 號 令 修 正 高 級 中 等 學 校 校 長 遴 選 聘 任 及 任 期 考 評 辦 法, 名 稱 並 修 正 為 高 級 中 等 學 校 校 長 遴 選 聘 任 及 辦
前 項 第 三 款 所 定 有 機 農 產 品 及 有 機 農 產 加 工 品 驗 證 基 準, 如 附 件 一 第 七 條 驗 證 機 構 受 理 有 機 農 產 品 及 有 機 農 產 加 工 品 之 驗 證, 應 辦 理 書 面 審 查 實 地 查 驗 產 品 檢 驗 及 驗 證 決 定 之
有 機 農 產 品 及 有 機 農 產 加 工 品 驗 證 管 理 辦 法 (101.06.07 修 正 ) 第 一 條 本 辦 法 依 農 產 品 生 產 及 驗 證 管 理 法 ( 以 下 簡 稱 本 法 ) 第 五 條 第 二 項 規 定 訂 定 之 第 二 條 本 辦 法 用 詞, 定 義 如 下 : 一 生 產 廠 ( 場 ): 指 在 國 內 生 產 加 工 分 裝 或 流 通 有 機
一
Hot Potatoes 命 題 軟 體 操 作 說 明 一 註 冊 操 作 程 序 1. 進 入 Hot Potatoes 的 官 方 網 站 網 址 http://web.uvic.ca/hrd/hotpot/index.htm 並 點 選 Register 2. 點 選 read the licence terms. 閱 讀 使 用 說 明 3. 點 選 I have read the license
目 錄 一 系 統 登 入... 2 ( 一 ) 系 統 登 入 畫 面... 2 ( 二 ) 首 次 登 入 請 先 註 冊... 3 ( 三 ) 忘 記 單 位 帳 號... 8 ( 四 ) 忘 記 密 碼... 10 ( 五 ) 健 保 卡 更 換... 12 ( 六 ) 重 寄 確 認 信.
補 充 保 險 費 網 路 明 細 申 報 及 列 印 繳 款 書 系 統 操 作 手 冊 衛 生 福 利 部 中 央 健 康 保 險 署 中 華 民 國 104 年 04 月 目 錄 一 系 統 登 入... 2 ( 一 ) 系 統 登 入 畫 面... 2 ( 二 ) 首 次 登 入 請 先 註 冊... 3 ( 三 ) 忘 記 單 位 帳 號... 8 ( 四 ) 忘 記 密 碼... 10
PowerPoint 簡報
長 庚 科 大 雲 端 硬 碟 ( 進 階 ) 雲 端 硬 碟 ( 進 階 ) 1 招 我 的 雲 端 硬 碟 (1/3) 我 的 雲 端 硬 碟 Google Apps - 雲 端 硬 碟 查 看 使 用 者 自 己 雲 端 硬 碟 中 的 檔 案 注 意 : 離 線 版 雲 端 硬 碟 只 會 同 步 我 的 雲 端 硬 碟 資 料 夾 中 的 檔 案 1) 查 看 雲 端 硬 碟 已 使 用
教育實習問與答:
問 與 答 集 一 總 則 Q1: 本 校 開 設 的 教 育 學 程 的 類 別 有 那 幾 種? A1: 本 校 開 設 的 教 育 學 程 有 中 等 學 校 師 資 類 科 教 育 學 程 ( 取 得 國 中 高 中 高 職 等 教 師 資 格 ) 國 民 小 學 師 資 類 科 教 育 學 程 取 得 國 小 教 師 資 格 ) 二 修 習 對 象 與 資 格 Q1: 在 何 種 條 件
Microsoft Word - 全華Ch2-05.doc
得 分 : 101 學 年 度 第 2 學 期 Ch2-5 數 字 系 統 與 資 料 表 示 法 命 題 教 師 : 範 圍 : 年 班 號 姓 名 一 單 選 題 : ( 1 ) 1. 通 常 PC 上 採 用 2 的 補 數 法 表 示 負 整 數, 所 使 用 的 整 數 範 圍 為 -32768 到 +32767, 請 問 此 情 況 下, 一 個 整 數 佔 用 多 少 Bytes? (1)2
修 課 特 殊 規 定 : 一 法 律 系 學 生 最 低 畢 業 學 分 128;101 學 年 度 修 讀 法 律 系 雙 主 修 學 生 應 修 畢 法 律 專 業 目 64 學 分 ( 限 修 習 本 校 法 律 系 開 設 課 程, 不 得 以 原 學 系 或 外 校 課 程 抵 免 -
法 律 學 系 學 士 班 基 礎 科 目 一 覽 表 101 學 年 度 入 學 學 生 適 用 科 目 名 稱 必 規 定 第 一 學 年 第 二 學 年 第 三 學 年 第 四 學 年 群 學 分 上 下 上 下 上 下 上 下 備 註 ( 先 修 科 目 ) 刑 法 ( 一 ) 群 3 3 基 礎 科 目 刑 法 ( 二 ) 群 3 3 基 礎 科 目 / 先 修 刑 法 ( 一 ) 刑 事
行 政 院 衛 生 署 醫 事 人 員 繼 續 教 育 積 分 管 理 系 統 使 用 手 冊 ( 醫 事 人 員 版 ) 中 華 民 國 100 年 2 月 15 日 文 件 修 訂 歷 史 版 本 制 / 修 訂 人 員 變 更 內 容 摘 要 頁 數 提 供 日 期 V1.0 蕭 鳴 孙 初 版 制 訂 All 100.1.18 目 錄 壹 登 入 說 明... 3 貳 操 作 描 述...
(DP_MFP_Training
影 印 機 操 作 說 明 1 人 性 化 操 作 面 板 超 大 液 晶 觸 控 面 板 : 容 易 觀 看 及 了 解 (192 x 72mm) 直 覺 性 操 作 面 板 設 計 : 由 上 而 下 由 左 至 右 的 消 費 者 直 覺 操 作 設 計 圖 形 化 界 面 : 所 有 功 能 一 目 了 然, 使 用 方 便 啟 動 統 一 式 設 計 : 全 系 列 相 同 操 作 界 面
骨 折 別 日 數 表 1. 鼻 骨 眶 骨 ( 含 顴 骨 ) 14 天 11. 骨 盤 ( 包 括 腸 骨 恥 骨 坐 骨 薦 骨 ) 40 天 2. 掌 骨 指 骨 14 天 12. 臂 骨 40 天 3. 蹠 骨 趾 骨 14 天 13. 橈 骨 與 尺 骨 40 天 4. 下 顎 ( 齒
查 詢 本 公 司 資 訊 公 開 說 明 文 件, 請 上 本 公 司 網 站, 南 山 產 物 團 體 傷 害 保 險 傷 害 醫 療 保 險 給 付 ( 日 額 型 ) 附 加 條 款 ( 主 要 給 付 項 目 : 傷 害 醫 療 保 險 金 日 額 保 險 金 ) 100.05.27(100) 美 亞 保 精 字 第 0097 號 函 備 查 101.08.08(101) 美 亞 保 精
BSP 烤箱 - 封面-2
BSPO615 使 用 及 安 裝 說 明 書 總 代 理 優 氏 集 團 客 林 渥 股 份 有 限 公 司 台 北 市 內 湖 區 行 愛 路 69 號 2 樓 TEL 02-2794 2588 FAX 02-2794 3789 台 中 市 北 屯 區 后 庄 路 1080-12 號 TEL 04-2422 0958 FAX 04-2422 0938 高 雄 市 左 營 區 政 德 路 633
e-Submission System Quick Reference Guide for Publication Related Matters (Chinese version)
有 關 登 載 事 宜 的 電 子 呈 交 系 統 簡 易 參 考 指 南 2016 年 5 月 1.4 版 本 第 1 頁 目 錄 1 登 入 前 要 準 備 的 資 料... 4 2 登 入 電 子 呈 交 系 統... 5 2.1 輸 入 使 用 者 編 號 及 密 碼... 5 2.2 接 受 免 責 聲 明 的 版 頁... 5 2.3 從 主 項 目 單 中 選 擇... 5 3 一 次
投影片 1
文 件 的 格 式 化 本 章 重 點 文 字 的 格 式 設 定 段 落 格 式 的 處 理 使 用 定 位 點 讓 文 章 整 齊 排 列 美 化 條 列 項 目 為 文 字 及 段 落 加 上 框 線 與 網 底 複 製 文 字 與 段 落 的 格 式 設 定 文 字 的 方 向 與 亞 洲 方 式 配 置 將 段 落 首 字 放 大 調 整 英 文 字 的 大 小 寫 與 全 半 形 2 設
頁 1 / 8 法 規 名 稱 : 公 務 人 員 俸 給 法 修 正 時 間 :97.1.16 第 一 條 ( 本 法 內 容 ) 公 務 人 員 之 俸 給, 依 本 法 行 之 第 二 條 ( 名 詞 定 義 ) 本 法 所 用 名 詞 意 義 如 下 : 一 本 俸 : 係 指 各 職 等 人 員 依 法 應 領 取 之 基 本 給 與 二 年 功 俸 : 係 指 各 職 等 高 於 本 俸
Microsoft Word - 雲林區_免試平台_國中模擬選填_操作手冊.doc
104 學 年 度 雲 林 區 高 級 中 等 學 校 免 試 入 學 報 名 及 志 願 分 發 系 統 平 臺 國 中 學 校 操 作 說 明 政 高 有 限 公 司 104 年 12 月 25 日 免 試 入 學 報 名 及 志 願 分 發 系 統 平 臺 目 錄 宣 導 事 項... 1 國 中 端 ( 承 辦 人 員 ) 系 統 操 作 流 程 圖... 4 學 生 端 ( 模 擬 選
(Microsoft Word - \246\250\301Z\272\336\262z.doc)
模 組 名 稱 : 成 績 管 理 適 用 單 位 : 國 小 目 錄 第 一 章 模 組 簡 介... 5 一 模 組 架 構 圖... 5 二 模 組 權 限 說 明... 6 三 模 組 功 能 說 明... 6 第 二 章 操 作 流 程 - 成 績 管 理... 8 一 成 績 管 理 ( 管 理 權 ) 流 程 圖... 8 二 成 績 管 理 ( 級 任 權 限 ) 流 程 圖...
1010327
核 算 加 計 利 息 滯 納 金 滯 納 利 息 規 定 及 計 算 範 例 各 稅 法 對 納 稅 義 務 人 逾 期 繳 納 稅 款, 大 多 有 加 徵 滯 納 金 加 計 利 息 之 規 定, 而 逾 期 與 否, 應 以 繳 款 書 所 填 載 之 繳 納 期 間 繳 納 期 限 或 限 繳 日 期 為 準 認 定 之 各 代 收 稅 款 金 融 機 構 對 於 逾 期 繳 納 稅 款
101年度社會福利方案 網路線上操作手冊
104 年 度 社 會 福 利 服 務 方 案 網 路 申 請 線 上 操 作 手 冊 中 華 社 會 福 利 聯 合 勸 募 協 會 103 年 8 月 編 製 中 華 社 會 福 利 聯 合 勸 募 協 會 方 案 線 上 申 請 操 作 1 2 4 0-12 104 年 度 社 會 福 利 服 務 方 案 網 路 申 請 線 上 操 作 手 冊 一 方 案 線 上 申 請 流 程 方 案 線
Microsoft Word - 立法會十四題附件.doc
附 件 一 公 務 員 資 歷 組 別 I. 資 歷 組 別 及 名 稱 資 歷 組 別 名 稱 1 無 需 中 學 會 考 五 科 及 格 2 中 學 會 考 證 書 第 一 組 : 需 要 香 港 中 學 會 考 五 科 及 格 的 第 二 組 : 需 要 香 港 中 學 會 考 五 科 及 格 並 具 相 當 經 驗 的 3 高 級 文 憑 及 文 憑 第 一 組 : 高 級 文 憑 第 二
<30332EAAFEA5F3A440A142A447A142A454A142A57CA147BEC7A5CDB14DB77EC3D2B7D3BEC7B2DFA661B9CF2E786C73>
嶺 東 科 技 大 學 財 務 金 融 系 日 四 技 學 生 專 業 學 習 地 圖 02 年 6 月 28 日 0 學 年 度 第 二 學 期 財 務 金 融 系 課 程 委 會 議 通 過 名 稱 微 積 分 ( 一 ) 微 積 分 ( 二 ) 個 體 經 濟 學 商 業 套 裝 軟 體 ( 二 ) 應 用 統 計 學 ( 一 ) 期 貨 與 選 擇 權 國 際 - 管 理 學 保 險 學 商
格 成 績 證 明 第 六 條 第 七 條 本 系 大 四 課 程 中 規 劃 日 本 韓 國 越 南 專 題 研 究, 學 生 需 於 大 四 時 修 習 該 課 程, 並 於 規 定 期 間 內 提 出 專 題 報 告, 取 得 合 格 成 績 證 明 本 系 規 定 學 生 畢 業 時 需 取
國 立 高 雄 大 學 東 亞 語 文 學 系 大 學 部 修 業 規 則 (104 學 年 後 入 學 學 生 適 用 ) 修 正 對 照 表 條 文 修 正 後 條 文 原 條 文 備 註 第 二 條 第 三 條 第 四 條 第 五 條 大 學 部 104 學 年 度 入 學 學 生 大 四 上 下 皆 未 選 擇 校 外 實 習 I 及 校 外 實 習 Ⅱ 者 畢 業 學 分 為 128 學
奇 妙 的 24 摘 要 從 撲 克 牌 中 隨 機 抽 取 4 張 牌 可 以 有 1820 種 牌 組, 在 這 1820 種 牌 組 中, 有 1362 組 可 經 由 四 則 運 算 的 方 式, 算 出 24 點, 有 458 組 無 解 快 速 求 解 的 方 法 有 相 加 法 因 數
金 門 地 區 第 55 屆 中 小 學 科 學 展 覽 會 作 品 說 明 書 科 別 : 數 學 組 組 別 : 國 小 組 作 品 名 稱 : 奇 妙 的 24 關 鍵 詞 :24 點 四 則 運 算 ( 最 多 3 個 ) 編 號 :( 由 主 辦 單 位 填 寫 ) 奇 妙 的 24 摘 要 從 撲 克 牌 中 隨 機 抽 取 4 張 牌 可 以 有 1820 種 牌 組, 在 這 1820
128 提 示 樞 紐 分 析 表 的 用 途 樞 紐 分 析 表 是 指 可 以 用 來 快 速 合 併 和 比 較 大 量 資 料 的 互 動 式 表 格, 透 過 它 可 以 詳 細 分 析 數 值 資 料, 特 別 適 用 於 下 列 情 況 : 需 要 從 含 有 大 量 資 料 的 清
Chapter 06 使 用 樞 紐 分 析 表 快 速 分 組 資 料 127 學 習 要 點 認 識 樞 紐 分 析 表 建 立 樞 紐 分 析 表 調 整 樞 紐 分 析 表 的 版 面 配 置 顯 示 群 組 小 計 的 合 計 折 疊 與 展 開 明 細 資 料 篩 選 與 排 序 樞 紐 分 析 表 資 料 新 增 計 算 欄 位 本 章 結 構 什 麼 是 樞 紐 分 析 表 適 用
Microsoft PowerPoint - 104年說明會簡報-final-0923.ppt [相容模式]
主 任 導 師 一 年 級 導 師 系 學 會 導 師 二 年 級 導 師 教 育 專 業 課 26 學 分 教 師 資 格 檢 定 考 試 ( 每 年 3 月 ) 中 等 學 校 教 師 證 書 學 習 護 照 ( 實 地 實 習 研 習 服 務 時 數 心 霊 美 學 與 藝 術 人 文 活 動 ) 修 畢 師 資 職 前 教 育 證 明 書 教 師 甄 試 專 門 課 程 ( 任 教 類
行政院金融監督管理委員會全球資訊網-行政院金融監督管理委員會
發 行 人 證 券 商 證 券 交 易 所 會 計 主 管 資 格 條 件 及 專 業 進 修 辦 法 暨 發 行 人 證 券 商 證 券 交 易 所 會 計 主 管 進 修 機 構 審 核 辦 法 問 答 集 105 年 5 月 修 訂 一 會 計 主 管 之 定 義 ( 會 計 主 管 資 格 條 件 及 專 業 進 修 辦 法 第 2 條 ) ( 一 ) 何 謂 會 計 主 管? 證 券 交
關 於 教 育 部 學 習 拍 立 得 教 育 部 於 (103) 年 度 整 合 各 縣 市 政 府 部 屬 機 構 大 學 及 民 間 的 數 位 資 源 與 服 務, 依 不 同 類 型, 分 別 匯 集 於 教 育 大 市 集 教 育 百 科 教 育 媒 體 影 音 教 育 部 學 習 拍
教 育 部 學 習 拍 立 得 - 教 師 版 使 用 手 冊 v2.0 2015.10.31 關 於 教 育 部 學 習 拍 立 得 教 育 部 於 (103) 年 度 整 合 各 縣 市 政 府 部 屬 機 構 大 學 及 民 間 的 數 位 資 源 與 服 務, 依 不 同 類 型, 分 別 匯 集 於 教 育 大 市 集 教 育 百 科 教 育 媒 體 影 音 教 育 部 學 習 拍 立 得
102.6.30.xls
之 二 資 產 負 債 權 益 展 開 表 102 年 6 月 30 日 單 位 : 新 臺 幣 千 元 資 產 會 計 項 目 展 開 項 目 現 金 及 約 當 現 金 75,497 75,497 存 放 央 行 及 拆 借 銀 178 178 同 業 透 過 損 益 按 公 允 價 值 衡 量 之 金 融 資 產 139,578 139,578 對 金 融 相 關 事 業 之 資 本 投 資
行政院金融監督管理委員會全球資訊網-行政院金融監督管理委員會
104 年 6 月 17 日 修 正 證 券 商 辦 理 財 富 管 理 業 務 應 注 意 事 項 問 答 集 一 證 券 商 於 98 年 9 月 28 日 前 經 本 會 核 准 辦 理 財 富 管 理 業 務 者 ( 辦 理 顧 問 諮 詢 業 務 ), 擬 依 新 修 正 證 券 商 辦 理 財 富 管 理 業 務 應 注 意 事 項 ( 以 下 簡 稱 注 意 事 項 ) 第 2 點 第
C12711--CH4.tpf
第 直 流 迴 路 章 4-1 節 點 電 壓 法 4-2 迴 路 電 流 法 4-3 重 疊 定 理 4-4 戴 維 寧 定 理 4-5 最 大 功 率 轉 移 4-6 諾 頓 定 理 4-7 戴 維 寧 與 諾 頓 之 轉 換 重 點 掃 描 習 題 探 討 熟 練 節 點 電 壓 法 的 解 題 技 巧 熟 練 迴 路 電 流 法 的 解 題 技 巧 熟 練 重 疊 定 理 的 解 題 技 巧
一、 資格條件:
臺 灣 港 務 股 份 有 限 公 司 新 進 人 員 甄 選 規 範 交 通 部 民 國 102 年 7 月 22 日 交 人 字 第 1025010095 號 函 核 定 交 通 部 民 國 103 年 8 月 4 日 交 授 港 總 人 字 第 10300564431 號 函 核 定 修 正 交 通 部 民 國 104 年 2 月 13 日 交 授 港 總 人 字 第 10401620891
桃園市104年國民中學新進教師甄選各校複試方式及需求表
桃 園 市 105 年 國 民 中 學 新 進 教 師 甄 選 各 校 複 試 方 式 及 需 求 表 編 號 校 名 教 評 會 審 查 方 式 及 學 校 需 求 備 註 1 2 桃 園 青 溪 ( 一 ) 口 試 80% 是 否 符 合 學 校 需 求 度 20% 具 數 學 專 長 者 為 佳 ( 一 ) 口 試 70% 是 否 符 合 學 校 需 求 度 30 % 需 擔 任 資 源 班
支 持 機 構 : 社 會 文 化 司 主 辦 機 構 : 澳 門 學 聯 澳 門 青 年 研 究 協 會 電 話 : 傳 真 : 網 址 : 報 告 主 筆 : 李 略 博 士 數 據 錄
家 長 對 澳 門 中 小 學 教 育 現 狀 的 意 見 調 查 報 告 主 辦 機 構 : 澳 門 中 華 學 生 聯 合 總 會 澳 門 青 年 研 究 協 會 2009.3 支 持 機 構 : 社 會 文 化 司 主 辦 機 構 : 澳 門 學 聯 澳 門 青 年 研 究 協 會 電 話 : 00853-28365314 28526255 傳 真 : 00853-28526937 網 址 :
PROSPECT EXPLORATION 壹 前 言 20 90 066 第 9 卷 第 2 期 中 華 民 國 100 年 2 月
專 題 研 究 法 律 與 法 制 探 析 中 國 大 陸 現 行 土 地 估 價 法 律 制 度 體 系 探 析 中 國 大 陸 現 行 土 地 估 價 法 律 制 度 體 系 A Study on the Legal Framework of Real Estate Appraisal in China 蔣 國 基 * (Chiang, Kuo-chi) 香 港 鴻 裕 公 司 法 務 長 摘
長跨距暨挑高建築特殊結構系統之調查分析
第 一 章 1 2 3 4 第 二 章 5 6 7 8 1. 2. 9 3. 4. 5. 6. 7. 8. 9. 10. 11. 10 12. 13. 14. 15. 16. 17. 18. 19. 11 第 三 章 p 12 b / B 0.75 13 p 14 15 D = l 20 +10 16 17 p l D l D l D 3 p 4 3 18 19 20 21 22 23 24 25
壹、組織編制 代碼:C0101意見反映
項 目 編 號 DA14 金 門 縣 政 府 人 事 處 教 師 敘 薪 標 準 作 業 流 程 序 說 明 表 項 目 名 稱 教 師 敘 薪 標 準 作 業 承 辦 單 位 人 事 處 第 一 科 作 業 流 程 說 明 一 起 敘 : ( 一 ) 新 進 教 師 到 職 聘 任 後, 按 其 所 具 資 格 條 件 ( 以 學 歷 為 主 ), 依 公 立 各 級 學 校 教 職 員 敘 薪
瑞興銀行
網 路 銀 行 基 金 服 務 系 統 - 查 詢 類 操 作 手 冊 中 華 民 國 一 零 五 年 版 第 1 頁 目 錄 文 件 導 引 說 明... 3 壹 基 金 服 務 - 查 詢 類... 1 一 我 的 基 金 ( 含 使 用 者 風 險 等 級 )... 1 1.1 更 新 損 益... 2 二 基 金 往 來 明 細 查 詢 ( 含 配 息 )... 5 2.1 基 金 單 筆
二零零六至零七年施政報告
1 3 4 13 14 34 17 19 20 24 2 5 26 27 28 29 3 0 31 32 3 3 3 4 35 50 36 42 43 45 46 48 49 50 51 66 52 57 58 60 61 65 6 6 67 76 1. 2. 3. 1 4. 5. 6. CEPA 7. 8. 9. 2 10. 11. 12. 13. 3 14. 15. 16. 17. 4 18.
第一章 緒論
第 五 章 實 證 結 果 第 一 節 敘 述 統 計 表 11 表 12 分 別 為 男 女 癌 症, 實 驗 組 與 控 制 組 樣 本 之 基 本 特 性 此 為 罹 癌 前 一 年 度 樣 本 特 性 由 於 我 們 以 罹 癌 前 一 年 有 在 就 業, 即 投 保 類 別 符 合 全 民 健 康 保 險 法 中 所 規 定 之 第 一 類 被 保 險 人, 且 年 齡 介 於 35 至
???T????????
資 訊 王 資 料 可 於 相 關 網 站 查 詢 對 應 表 系 統 選 項 資 料 選 項 對 應 相 關 網 址 上 櫃 公 司 現 金 增 資 資 料 現 金 增 資 與 股 上 市 股 票 公 開 申 購 資 訊 票 申 購 上 櫃 股 票 公 開 申 購 資 訊 http://www.twse.com.tw/ch/announcement/public.php 合 併 / 個 別 財 務
如何正確使用自己所擁有的正版音樂光碟?
學 生 的 共 同 筆 記 有 無 著 作 權? 學 校 任 課 教 師 上 課 時 的 授 課 演 講, 是 一 種 語 文 著 作 上 課 的 學 生 將 教 師 的 授 課 內 容, 一 字 一 句 的 抄 錄 成 筆 記, 這 是 一 種 重 製 行 為 學 生 上 課 的 目 的, 在 於 獲 得 授 課 教 師 所 傳 授 的 知 識, 而 學 生 上 課 做 筆 記, 是 一 種 習
本 題 各 點 彼 此 均 有 相 互 關 聯, 作 答 不 完 整, 將 影 響 各 評 分 點 之 得 分, 請 注 意 檔 名 儲 存 錯 誤, 該 題 一 律 0 分 計 算 1. 1. 深 淺 圖 表.xlsx 請 依 下 方 題 目 敘 述 操 作 ( 佔 總 分 :) 儲 存 格 範
2012 世 界 盃 電 腦 應 用 技 能 競 賽 全 國 總 決 賽 競 賽 試 題 暨 評 分 彙 總 表 競 賽 項 目 文 書 處 理 文 書 處 理 Word 2007 Word 2010 電 子 試 算 表 電 子 試 算 表 Excel 2007 電 腦 簡 報 電 腦 簡 報 PowerPoint 2007 PowerPoint 2010 試 題 攜 出 試 場, 一 律 零 分
包 裝 維 生 素 礦 物 質 類 之 錠 狀 膠 囊 狀 食 品 營 養 標 示 應 遵 行 事 項 一 本 規 定 依 食 品 安 全 衛 生 管 理 法 第 二 十 二 條 第 三 項 規 定 訂 定 之 二 本 規 定 所 稱 維 生 素 礦 物 質 類 之 錠 狀 膠 囊 狀 食 品, 指
包 裝 維 生 素 礦 物 質 類 之 錠 狀 膠 囊 狀 食 品 營 養 標 示 應 遵 行 事 項 一 本 規 定 依 食 品 安 全 衛 生 管 理 法 第 二 十 二 條 第 三 項 規 定 訂 定 之 二 本 規 定 所 稱 維 生 素 礦 物 質 類 之 錠 狀 膠 囊 狀 食 品, 指 以 營 養 添 加 劑 作 為 維 生 素 礦 物 質 來 源 之 錠 狀 膠 囊 狀 食 品 三
目 錄
目 錄 1. 收 回 本 年 度 經 費 1 ~ 2 2. 收 回 以 前 年 度 保 留 經 費 3 ~ 11 3. 新 舊 年 度 期 間 常 生 問 題 集 12 ~ 20 4. 收 款 收 據 錯 誤 之 問 題 集 21 ~ 22 歲 入 類 - 5. 轉 正 通 知 書 及 收 入 退 還 書 23 ~ 25 6. 其 他 26 ~ 26 7. 保 管 款 之 說 明 27 ~ 30 8.
<4D6963726F736F667420576F7264202D20B2C433B3B92020B971B8F4A4C0AA52A7DEA5A9>
研 習 完 本 章, 將 學 會 1. 節 點 電 壓 法 --------------------------------------------01 2. 節 點 電 壓 法 之 特 例 -----------------------------------------08 3. 網 目 分 析 法 --------------------------------------------15 4.
2 2.1 A H 2.2 601288 1288 12 360001 360009 69 100005 86-10-85109619 86-10-85108557 [email protected] 2
AGRICULTURAL BANK OF CHINA LIMITED 1288 2016 2016 3 31 571 XIVA 13.09(2) 13.10B 1 1.1 1.2 2016 4 28 2016 5 2016 1414 1.3 1.4 1 2 2.1 A H 2.2 601288 1288 12 360001 360009 69 100005 86-10-85109619 86-10-85108557
Microsoft Word - BM900HD-2F電腦設定.doc
3.4 控 制 機 能 1/20 1. 顯 示 區 顯 示 當 前 起 重 機 狀 態 2. 蜂 鳴 器 蜂 鳴 器 主 要 用 於 過 載 ( 包 括 載 荷 限 制 警 報 ) 當 負 荷 到 達 90% 時, 蜂 鳴 器 間 歇 性 警 報, 到 達 100% 率 時 連 續 警 報 負 荷 率 增 加 時, 蜂 鳴 器 警 報 間 隔 時 間 越 來 越 短 警 報 類 型 間 斷 連 續
( 二 ) 輔 導 員 除 有 特 殊 情 形 外, 同 時 間 以 輔 導 一 人 為 原 則, 至 多 不 得 超 過 二 人 ( 三 ) 實 務 訓 練 機 關 ( 構 ) 學 校 於 實 務 訓 練 期 間 對 由 資 深 人 員 擔 任 之 輔 導 員 得 酌 減 業 務 五 輔 導 重
公 務 人 員 考 試 錄 取 人 員 實 務 訓 練 輔 導 要 點 中 華 民 國 九 十 年 十 一 月 十 五 日 保 訓 會 公 訓 字 第 九 六 四 四 七 號 函 發 布 中 華 民 國 九 十 一 年 十 月 二 十 一 日 保 訓 會 公 訓 字 第 九 一 六 二 四 號 函 修 正 發 布 中 華 民 國 九 十 三 年 三 月 八 日 保 訓 會 公 訓 字 第 九 三 一
廿一世紀集居環境規劃與建築型態塑造之研究
第 一 章 緒 論 第 一 節 研 究 動 機 與 目 的 1 第 二 節 研 究 內 容 與 方 法 2 3 4 5 第 二 章 回 顧 與 前 瞻 第 一 節 文 獻 回 顧 一 集 居 環 境 規 劃 5 6 7 8 9 10 11 12 13 14 15 1. 2. 3. 4. 5. 6. 1. 2. 3. 4. 5. 6. 7. 8. 1. 2. 3. 4. 5. 6. 7. 8. 9.
PART 2 系 統 篇 仔 細 檢 查 記 憶 體 和 顯 示 卡 4-2 4-1 AIDA64 Everest 操 作 : 使 用 AIDA64 檢 測 主 機 溫 度 AIDA64 DirectX AIDA64 http://www.aida64.com/downloads 78
Chapter 0 4 系 統 不 穩 定 4-1 3D 2 2-1-2 BIOS 因 超 頻 所 導 致 的 系 統 運 作 不 穩 定, 可 以 從 BIOS 中 還 原 設 定 值 77 PART 2 系 統 篇 仔 細 檢 查 記 憶 體 和 顯 示 卡 4-2 4-1 AIDA64 Everest 操 作 : 使 用 AIDA64 檢 測 主 機 溫 度 AIDA64 DirectX AIDA64
Microsoft Word - _3_???????-Ch20140625_???
綠 河 股 份 有 限 公 司 董 事 會 議 事 規 則 制 訂 及 修 正 紀 錄 一 本 規 則 初 版 於 2012 年 7 月 21 日 制 訂 二 本 規 則 第 一 次 修 訂 於 2013 年 6 月 29 日 三 本 規 則 第 二 次 修 訂 於 2014 年 6 月 25 日 綠 河 股 份 有 限 公 司 董 事 會 議 事 規 則 第 1 條 本 董 事 會 議 事 規 則
( 五 ) 財 務 會 計 理 論 研 討 3 學 分 ( 六 ) 審 計 理 論 研 討 3 學 分 ( 七 ) 管 理 會 計 理 論 研 討 3 學 分 第 四 條 選 修 科 目 : ( 一 ) 數 量 方 法 3 學 分 ( 二 ) 財 務 會 計 專 題 研 討 ( 一 ) 3 學 分
國 立 雲 林 科 技 大 學 會 計 系 管 理 博 士 班 會 計 組 研 究 生 修 業 要 點 101 年 9 月 19 日 101 學 年 度 第 1 學 期 第 2 次 系 務 會 議 通 過 第 一 章 訂 定 依 據 第 一 條 會 計 系 管 理 博 士 班 會 計 組 研 究 生 修 業 要 點 ( 以 下 簡 稱 本 修 業 要 點 ) 依 據 國 立 雲 林 科 技 大 學
55202-er-ch03.doc
8 第 章 機 率 - 樣 本 空 間 與 事 件 列 出 擲 一 粒 骰 子 所 出 現 點 數 的 樣 本 空 間, 並 以 集 合 表 示 下 列 各 事 件 : A 是 出 現 點 數 為 偶 數 的 事 件, B 是 出 現 點 數 為 奇 數 的 事 件, C 是 出 現 點 數 大 於 的 事 件 骰 子 出 現 的 點 數 可 能 是,,, 4,5, 6, 因 此 出 現 點 數 的
目 錄 頁 1. 歡 迎 使 用 網 上 預 約 面 談 訪 問 系 統... 3 2. 新 用 戶... 4 2.1 新 用 戶 登 入 帳 戶 程 序... 4 2.2 啟 動 網 上 預 約 面 談 訪 問 帳 戶... 5 2.2.1 核 對 帳 戶 的 地 址 資 料... 5 2.2.2
網 上 預 約 面 談 訪 問 使 用 指 南 香 港 特 別 行 政 區 政 府 統 計 處 目 錄 頁 1. 歡 迎 使 用 網 上 預 約 面 談 訪 問 系 統... 3 2. 新 用 戶... 4 2.1 新 用 戶 登 入 帳 戶 程 序... 4 2.2 啟 動 網 上 預 約 面 談 訪 問 帳 戶... 5 2.2.1 核 對 帳 戶 的 地 址 資 料... 5 2.2.2 閱
268 別 行 政 區 所 以, 全 國 人 民 代 表 大 會 根 據 憲 法 第 31 條 規 定 設 立 了 特 別 行 政 區 沒 有 憲 法 第 31 條 的 規 定, 就 沒 有 特 別 行 政 區 制 度 存 在 的 合 法 性 基 礎 62 正 如 上 述, 憲 法 為 特 別 行
行 政 第 二 十 三 卷, 總 第 八 十 八 期,2010 No.2,267 275 267 * 憲 法 和 基 本 法 是 澳 門 特 別 行 政 區 的 憲 制 基 礎, 體 現 在 二 個 方 面 第 一, 一 國 兩 制 的 實 施 需 要 制 度 化 和 法 律 化, 制 度 化 就 是 設 立 特 別 行 政 區, 法 律 化 就 是 制 定 特 別 行 政 區 基 本 法 制 度
<4D6963726F736F667420576F7264202D20A4BDA640BADEB27ABD64C3A5A44AC2BEB4B6B371B67DA6D25FB3F8A6D2B0DDC344B6B05F3134303830365F636E>
公 共 管 理 範 疇 技 術 員 職 程 普 通 對 外 入 職 開 考 第 一 職 階 二 等 技 術 員 職 位 空 缺 報 考 集 有 關 報 考 地 點 日 期 及 時 間 報 考 地 點 在 那 裡? 開 考 通 告 上 所 述 遞 交 投 考 申 請 表 的 期 限 為 二 十 日, 自 本 通 告 在 澳 門 特 別 行 政 區 公 報 公 佈 後 第 一 個 工 作 日 起 計 如
sle cover 1
給 愛 尋 根 究 底 的 青 少 年 紅 斑 狼 瘡 冷 知 識 鳴 謝 給 愛 尋 根 究 底 的 青 少 年 紅 斑 狼 瘡 冷 知 識 ~ Hospital for Special Surgery 2003 For Inquiring Teens With LUPUS ~ Our Thoughts, Issues & Concerns Nichole Niles 為 什 麼 會 有 這 本
代 理 人 者, 由 常 務 董 事 或 董 事 互 推 一 人 代 理 之 第 八 條 本 公 司 董 事 會 召 開 時, 總 經 理 室 應 備 妥 相 關 資 料 供 與 會 董 事 隨 時 查 考 召 開 董 事 會, 得 視 議 案 內 容 通 知 相 關 部 門 或 子 公 司 之 人
南 亞 科 技 股 份 有 限 公 司 董 事 會 議 事 規 範 民 國 105 年 6 月 22 日 董 事 會 修 正 通 過 第 一 條 為 建 立 本 公 司 良 好 董 事 會 治 理 制 度 健 全 監 督 功 能 及 強 化 管 理 機 能, 爰 依 公 開 發 行 公 司 董 事 會 議 事 辦 法 之 規 定 訂 定 本 規 範, 以 資 遵 循 第 二 條 本 公 司 董 事
2016年中國語文科試卷三聆聽及綜合能力考核樣本試卷示例及說明
目 錄 2016 年 中 國 語 文 科 試 卷 三 聆 聽 及 綜 合 能 力 考 核 樣 本 試 卷 示 例 及 說 明 前 言 1 第 五 級 示 例 一 2 第 五 級 示 例 二 11 第 四 級 示 例 一 20 第 四 級 示 例 二 28 第 三 級 示 例 一 37 第 三 級 示 例 二 45 第 二 級 示 例 一 53 第 二 級 示 例 二 61 第 一 級 示 例 一 68
ART_RAE16_ticket_cn_p.1
1. 2. 3. 4. 基 础 部 分 - 色 彩 TM TM Premier B2C Sales to China 2014 TM OCR www.divcom.com.hk/ocrc 現 在 開 始 計 劃 訪 問 亞 洲 零 售 博 覽 的 行 程! 交 通 配 套 乘 車 路 線 : 由 機 場 乘 坐 公 共 汽 車 : A11 或 E11 到 灣 仔 (~80 分 鐘 ) 地 鐵 :
連江縣政府所屬學校兼任代課及代理教師聘任實施要點(草案)
連 江 縣 中 小 學 兼 任 代 課 及 代 理 教 師 聘 任 補 充 規 定 中 華 民 國 95 年 5 月 4 日 連 教 學 字 第 0950012838 號 中 華 民 國 97 年 7 月 25 日 連 教 學 字 第 0970022418 號 修 訂 中 華 民 國 99 年 1 月 11 日 連 教 學 字 第 0990001112 號 修 訂 中 華 民 國 101 年 10
3. 給 定 一 整 數 陣 列 a[0] a[1] a[99] 且 a[k]=3k+1, 以 value=100 呼 叫 以 下 兩 函 式, 假 設 函 式 f1 及 f2 之 while 迴 圈 主 體 分 別 執 行 n1 與 n2 次 (i.e, 計 算 if 敘 述 執 行 次 數, 不
1. 右 側 程 式 正 確 的 輸 出 應 該 如 下 : * *** ***** ******* ********* 在 不 修 改 右 側 程 式 之 第 4 行 及 第 7 行 程 式 碼 的 前 提 下, 最 少 需 修 改 幾 行 程 式 碼 以 得 到 正 確 輸 出? (A) 1 (B) 2 (C) 3 (D) 4 1 int k = 4; 2 int m = 1; 3 for (int
HSBC Holdings plc Interim Report 2015 - Chinese
聯 繫 客 戶 創 先 機 助 握 商 情 百 五 載 HSBC Holdings plc 滙 豐 控 股 有 限 公 司 2015 年 中 期 業 績 報 告 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
第 一 條 : 為 建 立 本 公 司 良 好 董 事 會 治 理 制 度 健 全 監 督 功 能 及 強 化 管 理 機 能, 爰 依 公 開 發 行 公 司 董 事 會 議 事 辦 法 第 二 條 訂 定 本 規 範, 以 資 遵 循 第 二 條 : 本 公 司 董 事 會 之 議 事 規 範,
環 瑞 醫 投 資 控 股 股 份 有 限 公 司 內 部 控 制 管 理 辦 法 董 事 會 議 事 規 範 Page 1 of 7 第 一 條 : 為 建 立 本 公 司 良 好 董 事 會 治 理 制 度 健 全 監 督 功 能 及 強 化 管 理 機 能, 爰 依 公 開 發 行 公 司 董 事 會 議 事 辦 法 第 二 條 訂 定 本 規 範, 以 資 遵 循 第 二 條 : 本 公 司
認可人士、註冊結構工程師及註冊岩土工程師作業備考 ADM-6
屋 宇 署 認 可 人 士 註 冊 結 構 工 程 師 及 註 冊 岩 土 工 程 師 作 業 備 考 ADM-6 結 構 及 岩 土 設 計 使 用 的 電 腦 程 式 認 可 人 士 註 冊 結 構 工 程 師 或 註 冊 岩 土 工 程 師 可 以 使 用 電 腦 程 式 作 計 算 分 析 來 輔 助 其 設 計, 或 使 用 電 腦 程 式 製 備 呈 交 予 建 築 事 務 監 督 的
文 ( 一 ) 閱 讀 理 解 英 語 數 學 社 會 自 然 及 國 文 ( 二 ) 語 文 表 達 等 各 科 此 外 嘉 義 區 則 另 外 單 獨 辦 理 測 驗 五 專 亦 有 辦 理 特 色 招 生 考 試 分 發 入 學, 與 高 中 高 職 分 開 辦 理, 但 成 績 同 樣 採
想 報 考 103 年 五 專 特 色 招 生 考 試 分 發 入 學 103.2.20 1. 文 藻 外 語 大 學 ( 雙 外 語 跨 領 域 國 際 專 業 人 才 菁 英 班 ) 2. 國 立 臺 中 科 技 大 學 ( 資 訊 應 用 菁 英 班 創 意 商 品 設 計 菁 英 班 ) 3. 國 立 臺 北 商 業 技 術 學 院 ( 企 業 管 理 菁 英 班 國 際 貿 易 科 企 業
(3) 澳 門 特 別 行 政 區 之 稅 務 知 識 及 (4) 商 法 典 ( 二 ) 重 新 批 准 註 冊 為 註 冊 會 計 師 / 專 業 會 計 員 之 筆 試 科 目 如 下 : (1) 澳 門 特 別 行 政 區 之 稅 務 知 識 及 (2) 商 法 典 ( 三 ) 考 試 範
核 數 師 暨 會 計 師 註 冊 委 員 會 首 次 註 冊 為 註 冊 會 計 師 / 專 業 會 計 員 及 重 新 批 准 註 冊 為 註 冊 會 計 師 / 專 業 會 計 員 之 考 試 規 章 根 據 十 一 月 一 日 第 72/99/M 號 法 令 核 准 之 會 計 師 通 則 第 四 條 第 三 款 之 規 定, 申 請 首 次 註 冊 為 註 冊 會 計 師 / 專 業 會
(Microsoft Word - 3-3 \245\277\244\361\273P\244\317\244\361.doc)
觀 念 篇 關 係 式 描 述 兩 個 變 數 x 與 y 之 間 關 係 的 數 學 式 子 例 題 練 習 1. 時 速 60 (km/h) 前 進, 求 距 離 y ( 公 里 ) 與 時 間 x ( 小 時 ) 的 關 係 式 關 係 式 就 是 描 述 兩 個 變 數 x 與 y 之 間 關 係 的 數 學 式 子 例 如 :y=60x 2. 媽 媽 的 年 齡 (x 歲 ) 比 女 兒
Microsoft Word - LongCard_Promo_2013_FAQ_tc_pdf.doc
陸 港 通 龍 卡 常 遇 問 題 一 般 問 題 o 甚 麼 是 陸 港 通 龍 卡? o 陸 港 通 龍 卡 具 有 哪 些 特 點? o 陸 港 通 龍 卡 適 合 甚 麼 客 戶 使 用? 陸 港 通 龍 卡 申 請 須 知 o 陸 港 通 龍 卡 的 發 卡 對 象 是 甚 麼? o 聯 名 賬 戶 或 公 司 客 戶 可 以 申 請 陸 港 通 龍 卡 嗎? o 現 時 哪 一 個 建
1
地 獄 少 女 地 獄 少 女 ( 藤 商 事 ) 八 通 屋 育 樂 事 業 有 限 公 司 07-3733316 www.8tw.com.tw 此 攻 略 本 是 引 至 日 本 遊 戲 攻 略 說 明, 內 容 僅 供 參 考, 一 切 演 出 以 官 方 為 主, 若 有 任 何 錯 誤 或 問 題 敬 請 告 知, 我 們 會 盡 快 改 善, 謝 謝 本 書 圖 片 取 材 自 網 路
基 金 配 息 資 訊 聯 博 境 外 基 金 2016 AA/AD/AT/BA/BD/BT 月 份 除 息 日 2016 年 01 月 01 月 28 日 01 月 29 日 2016 年 02 月 02 月 26 日 02 月 29 日 2016 年 03 月 03 月 30 日 03 月 31
基 金 配 息 資 訊 聯 博 基 金 歷 史 配 息 及 報 酬 率 資 訊 境 外 基 金 ( 本 基 金 有 相 當 比 重 投 資 於 非 投 資 等 級 之 高 風 險 債 券 且 配 息 來 源 可 能 為 本 金 ) ( 本 基 金 主 要 係 投 資 於 非 投 資 等 級 之 高 風 險 債 券 且 配 息 來 源 可 能 為 本 金 ) ( 基 金 之 配 息 來 源 可 能 為
