本教程內容力求以詳細的步驟和講解讓讀者以最快的方式學會 MC8051 IP core 的應用以及相關設計軟件的使用,並激起讀者對 SOPC 技術的興趣。本實驗重點講 8051Core 的應用,並通過一個簡單 C51 程序對 51Core 進行硬件測試。
本實驗教程的內容編排如下:
第 1 章簡單的描述了 MC8051 IP core 的基本結構及一些應用說明。
第 2 章詳細的介紹 8051Core 綜合、編譯應用。包括 Quartus II軟件的基本應用,ROM、RAM 模塊的生成,8051Core 的封裝及應用測試。 附錄 A 為 MC8051 IP Core 的指令集。
在閱讀本教程的過程中,請讀者注意以下幾點:
本教程在編寫時充分借鑒了周立功編寫的mc8051 IP核教程,同時針對其中較為落后的一些內容進行了更新(周立功的教程使用的還是Cyclone系列的器件,軟件版本也很低,很多操作與目前使用的主流版本有較大區別),同時刪除了其教程中使用Synplicity對工程進行綜合的部分,轉而使用Quartus II軟件直接綜合。
本實驗教程的 MC8051 IP Core (V1.6) 源於 http://oregano.at/ip/8051.htm 網站,讀者如有需要可到該網站下載。
第1章 MC8051 的基本結構
這一章將簡單的介紹 MC8051 IP Core 的基本硬件結構和一些設計應用的注意事項,具
體內容包括:
1. 功能特點
2. 頂層結構
3. 設計層次
4. 硬件配置
5. 並行 I/O 口
6. 其它說明
本章介紹的內容可能過於簡略,如果要更詳細的資料可參考 mc8051_user_guide.pdf
文檔(位於:“mc8051_v1.6源碼.zip\Version1_6\doc”文件夾里面)。
1.1 功能特點
● 采用完全同步設計
● 指令集和標准 8051 微控制器完全兼容
● 指令執行時間為 1~4 個時鍾周期,執行性能優於標准 8051 微控制器 8 倍左右
● 用戶可選擇定時器/計數器、串行接口單元的數量
● 新增了特殊功能寄存器用於選擇不同的定時器/計數器、串行接口單元
● 可選擇是否使用乘法器(乘法指令 MUL)
● 可選擇是否使用除法器(除法指令 DIV)
● 可選擇是否使用十進制調整功能(十進制調整指令 DA)
● I/O 口不復用
● 內部帶 256Bytes RAM
● 最多可擴展至 64Kbytes 的 ROM 和 64Kbytes 的 RAM
● 最多可擴展至 64Kbytes 的 ROM 和 64Kbytes 的 RAM
1.2 頂層結構
MC8051 IP Core 頂層結構圖如圖 1.1 所示,圖中指示了 mc8051_core 的頂層結構以及同 三個存儲模塊的連接關系,同時顯示了頂層的輸入輸出 I/O 口,各 I/O 信號的描述如表 1.1 所示。定時器/計數器和串行接口單元對應於圖中的 mc8051_tmrctr 和 mc8051_siu 模塊,數量是可選擇的,在圖中用虛線表示。
圖 1.1 MC8051 IP Core 頂層結構圖
表 1.1 頂層信號名
1.3 設計層次
MC8051 IP Core 的層次結構及對應的 VHDL 文件如圖 1.2 所示。
VHDL 源文件的命名格式如下:
核心由定時器/計數器、ALU、串行接口和控制單元各模塊組成。ROM 和 RAM 模塊不
包括於核心內,處於設計的頂層,方便於不同的應用設計及仿真。
圖 1.2 MC8051 IP Core 的設計層次
1.4 硬件配置
1.4.1 定時器/計數器、串口和中斷
標准的 8051 核只有兩個定時器/計數器,一個串口和兩個外部中斷源。而在 MC8051 IPCore 中,這些單元最多可增加到 256 組,只需要在 VHDL 源程序文件 mc8051_p.vhd 中,更改C_IMPL_N_TMR、C_IMPL_N_SIU、C_IMPL_N_EXT的常量值就可以了,范圍是1~256。相關的代碼如程序清單 1.1 所示。
程序清單 1.1 定時器/計數器、串口及中斷的配置程序
-------------------------------------------------------------------- -- Select how many timer/counter units should be implemented -- Default: 1 constant C_IMPL_N_TMR : integer := 1; -------------------------------------------------------------------- -------------------------------------------------------------------- -- Select how many serial interface units should be implemented -- Default: C_IMPL_N_TMR ---(DO NOT CHANGE!)--- constant C_IMPL_N_SIU : integer := C_IMPL_N_TMR; -------------------------------------------------------------------- -------------------------------------------------------------------- -- Select how many external interrupt-inputs should be implemented -- Default: C_IMPL_N_TMR ---(DO NOT CHANGE!)--- constant C_IMPL_N_EXT : integer := C_IMPL_N_TMR; --------------------------------------------------------------------
C_IMPL_N_TMR、C_IMPL_N_SIU、C_IMPL_N_EXT 這三個常量是不能獨立修改數值的,也就是說只能同時增減。C_IMPL_N_TMR 加一,就意味 IP Core 中同時添加了兩個定時器/計數器,一個串口單元和兩個外部中斷源。 為了控制這些新增的控制單元,微控制器在特殊寄存器內存空間增加了兩個寄存器。分別是 TSEL(定時器/計數器選擇寄存器,地址為 0X8E)和 SSEL(串口選擇寄存器,地址為 0X9A),如果沒有對這兩個寄存器賦值,其缺省值為 1。電路結構如圖 1.3 所示。
圖 1.3 使用附加的 TSEL 寄存器選擇 TCON 寄存器
如果在中斷發生期間設備(寄存器)沒被選中(比如 TSEL),那么相應的中斷標志位將保持置位,直到中斷服務程序被執行。
1.4.2 可選擇的指令
在某些場合,有些指令是用不到的,因此可以通過禁用這些指令來節省片上(比如 FPGA)資源。這些指令有 8 位乘法器(MUL)、8 位除法器(DIV)和 8 位十進制調整器(DA)。禁用時只需要在 VHDL 源程序文件 mc8051_p.vhd 中將 C_IMPL_MUL(乘法指令 MUL)、 C_IMPL_DIV(除法指令 DIV)或 C_IMPL_DA(十進制調整指令 DA)的常量值設置為 0。相應的 VHDL 程序代碼段如所示。
程序清單 1.2 可選指令配置程序
-------------------------------------------------------------------- -- Select whether to implement (1) or skip (0) the multiplier -- Default: 1 constant C_IMPL_MUL : integer := 1; -------------------------------------------------------------------- -------------------------------------------------------------------- -- Select whether to implement (1) or skip (0) the divider -- Default: 1 constant C_IMPL_DIV : integer := 1; -------------------------------------------------------------------- -------------------------------------------------------------------- -- Select whether to implement (1) or skip (0) the decimal adjustment command -- Default: 1 constant C_IMPL_DA : integer := 1; --------------------------------------------------------------------
這三條可選擇指令如果沒被設置執行,芯片(FPGA)可節省將近 10%的空間(資源)。
1.5 並行 I/O 口
為了便於 IC 設計,MC8051 IP Core 的 I/O 口不提供復用功能,包括 4 個 8 位輸入輸出口、串行接口、計數器輸入端和擴展存儲器接口。如果 I/O 要做為雙向口應用,其基本電路
結構圖如圖 1.4 所示。
圖1.4 並行I/O口基本結構
圖 1.4 中的兩個 D 觸發器起同步輸入信號的作用(mc8051_core 的輸入 I/O 無做同步處理),也可以不用。上拉電阻是必要的,因為 I/O 口輸出高電平是靠上拉電阻實現的。
1.6 其它說明
(1) MC8051 IP Core 的定時器和串口波特率的計算和標准 8051 一樣,計數時鍾也是由系 統時鍾經 12 分頻得到。
(2) 外部中斷信號是經兩級寄存器做同步處理后輸入的。
(3) MC8051_core 的輸入 I/O 沒有做同步處理,必要時可自己添加,如圖 1.4 所示。
(4) 寫應用程序時,I/O 口如果沒有做成雙向口(如圖 1.4 所示),而是輸入和輸出分開的,那么要特別注意,像 P1=~P1、P1^0=P1^0 這樣的 I/O 取反操作是無效(不起作用)的,因為讀回來的值不是 I/O 寄存器的值,而是輸入引腳的狀態。
(5) MC8051 IP Core 經 Quartus II 綜合編譯后,觀看時序分析報告,其最高運行頻率為 32MHz(每次編譯都可能不同,I/O 分配不同結果可能不同),因此系統時鍾不能超過時序報告的時鍾最高頻率(即 fmax)。
第2章 MC8051 的硬件運行
本實驗的硬件平台是采用芯航線FPGA學習套件,關於本實驗套件的的詳細介紹,請參看《芯航線FPGA學習平台用戶手冊》,這里就不重復說明。這里只簡單說一些本實驗用到的硬件資源以及相關軟件的基本操作。
本章我們主要講述 MC8051 core 的生成及封裝,最后進行硬件下載運行並測試 I/O 口、 UART 及定時器。用到的硬件資源有為開發套件核心板上的LED0~LED3 、USB轉串口接口。 本章將分以下幾部分來講述:
1. MC8051 中 ROM、RAM 模塊的生成;
2. MC8051 core RTL 的封裝;
3. MC8051 core 在 Quartus II 中的應用;
4. 測試 MC8051 的 I/O、UART 和定時器功能。 本實驗力求以詳細的步驟和講解讓讀者以最快的方式學會 MC8051 IP core 的應用以及
相關設計軟件的使用,並激起讀者對 SOPC 技術的興趣。
2.1 MC8051 中 ROM、RAM 模塊的生成
本節的內容是建立一個 Quartus II 應用工程,並利用 Quartus II 自身集成的 Megawizard Plug_in Manager 工具(/在Quartus II 14.0版本及以后,名字改為了IP Catlog)來生成 MC8051 中所需的內部 RAM、外擴 RAM 及 ROM。
2.1.1 建立 Quartus II 工程
從【開始】>>【程序】>>【Altera】>>【Quartus II 13.0】或直接雙擊桌面的Quartus II軟件圖標打開 Quartus II 13.0 軟件,軟件界面如圖 2.1 所示。
圖 2.1 Quartus II 軟件界面
在圖 2.1 中從【File】>>【New】打開新建文件選項卡,在選項卡中選擇【New Quartus II Project】來新建一項工程,軟件界面如圖 2.2 所示。
圖 2.2 新建Quartus II 文件
打開后顯示界面如下所示:
圖 2.3 新建工程路徑、名稱、頂層實體指定對話框
不要將文件夾設在計算機已有的安裝目錄中,更不要將工程文件直接放在安裝目錄中。文件夾所在路徑名和文件夾名中不能用中文,不能用空格,不能用括號(),可用下划線_,最好也不要以數字開頭。
圖 2.3 第一欄用於指定工程所在的工作庫文件夾;第二欄用於指定工程名,工程名可以取任何名字,也可以直接用頂層文件的實體名作為工程名(建議使用);第三欄用於指定頂層文件的實體名。本例工程的路徑為 E:\CoreCourse_fpga\mc8051_test文件夾,工程名與頂層文件的實體名同名為 mc8051_test。
圖 2.4 新建工程添加文件對話框
由於是新建工程,暫無輸入文件,所以直接單擊,進入圖2.5所示的指定目標器件對話框。這里我們選擇芯航線FPGA核心板上使用的Cyclone IV系列的EP4CE10F17C8
圖 2.5 新建工程器件選擇對話框
在圖 2.5 右邊的過濾器欄(Filters)中,設計者可以通過指定封裝、管腳數以及器件速
度等級來加快器件查找的速度。
圖 2.6 新建工程 EDA 工具設置對話框
本實驗利用 QuartusII 的集成環境進行開發,不進行仿真驗證,故不使用任何 EDA 工具,因此這里不作任何改動。圖 2.6 中單擊 進入圖 2.7 所示的工程信息報告對話框。從工程信息報告對話框,設計者可以看到工程文件配置信息報告。點擊
,完成新建工程的建立。 需要注意的是,建立工程后,還可以根據設計中的實際情況對工程進行重新設置,可選擇【Assignments】>> 【Settings…】進行設置,也可以選擇工具欄上的
按鈕。
圖 2.7 新建工程配置信息報告對話框
2.1.2 建立工程頂層文件
在Quartus II中,常見的頂層文件有原理圖形式和Verilog/VHDL形式,早期高校教學多選擇以原理圖形式為主。采用原理圖形式作為工程頂層,在工程並不復雜的情況下,方便清晰的展示設計結構。但是當設計變的復雜,頂層中需要添加的模塊越來越多之后,原理圖形式的頂層文件,弱點也明顯的暴露出來,主要表現為連線復雜,容易出錯,可讀性差,不便於修改。同時,隨着Quartus II新版本軟件的推出,不同版本間對於原理圖形式的文件解析方式有差異,導致同一工程在不同的軟件版本中打開的樣式並不一致,在升級中很容易出錯。因此這里采用Verilog/VHDL的形式創建文件頂層。
由於目前Verilog的普及率越來越高,熟悉Verilog的人遠遠大於熟悉VHDL的人,因此這里我們使用Verilog格式的文件來作為工程頂層。
點擊【File】>>【New…】,選擇Verilog HDL File,如圖 2.8 所示:
圖 2.8 新建Verilog HDL文件對話框
點擊OK即可創建一個新的Verilog文件。
接着點擊【File】>>【Save As…】將文件存儲為” mc8051_test.v”, 如圖 2.9 所示:
圖 2.9 保存Verilog文件
該文件就將作為我們工程的頂層文件
2.1.3 ROM 和 RAM 模塊的生成
MC8051 中所需要的存儲模塊有,內部 RAM、擴展 RAM 和 ROM。其中內部RAM 和ROM 是必要的,內部 RAM 固定為 128Bytes,ROM 最大可選 64KBytes,鑒於 FPGA(這里我們選用 EP4CE10)片上 RAM 資源有限(EP4CE10的片上 RAM 約 51.75KBytes,這里我們選擇 4Kbytes(可根據自己需要修改);擴展 RAM 是可選,最大也可以達到 64KBytes,這里我們選擇 2Kbytes。
(1)創建一個ROM模塊所需使用的初始化文件
這里首先創建該文件是為了使后面創建ROM模塊時能夠順利進行。因為在生成ROM模塊時,如果不指定一個存在的hex或mif格式的初始化文件,生成過程是無法順利完成的。
點擊【File】>>【New…】,選擇Hexadecimal (Intel-Format)File。然后點擊OK。如圖 2.10所示:
圖 2.10 新建hex文件
在彈出的對話框中,設置Number of words為4096,Word size為8,然后點擊OK,即可創建一個新的hex文件,如圖 2.11所示:
圖 2.11 設置hex文件大小
接着點擊【File】>>【Save As…】將文件存儲為” mcu_test.hex”。 如圖 2.12所示:
圖 2.12 保存hex文件
(2) 生成ROM模塊
(1) 從【Tools】>>【MegaWizard Plug-In Manager…】打開如圖 2.13 所示添加兆功能模塊向導。選擇【Create a new custom megafunction variation】新建一個新的兆功能模塊。然后點擊進入向導 page2。
圖 2.13 添加兆功能模塊向導對話框
(2) 在 page2,在搜索框中輸入“rom”,選擇搜索結果中的ROM:1-PORT,然后指定生成這個ROM 的器件系列(默認已經是Cyclone IV E),硬件描述語言(VHDL)和輸出文件存放路徑及名字(mc8051_rom),如圖2.14所示。
圖 2.14 page2創建ROM IP核
(3) 在 page3 上,設置 ROM 的信息:數據寬度 8bits,數據個數 4069。其余默認就行了。如圖 2.15 所示。
圖 2.15 page3 設置存儲器大小
(4) 在 page4 上,取消 ROM 的輸出寄存器,時鍾使能信號及異步清零信號不用選,如圖2.16所示
圖 2.16 page4 取消輸出寄存器
(5) 如圖 2.17 所示在 page5 上指定 ROM 的初始化數據文件(也即單片機程序的機器碼.hex 文件)。初始化數據文件可以是.mif 或.Hex 文件。對於 ROM 模塊,是一定要指定初始化數據的,要不然向導就不能完成。這里我們選擇之前創建的那個空白hex文件mcu_test.hex 文件(這里我們是先先隨便找了個.hex 文件填進去,到后面再更換成我們所要的測試文件)。
然后我們勾選“Allow In-System Memory Content Editor to capture and update content independently of the system clock”,這樣,當我們更改了我們的軟件代碼並生成了新的Hex文件時,就可以直接使用In-System Memory Content Editor工具來在線將新的hex文件下載到ROM中,從而避開在工程中重新替換hex文件並編譯工程的工作。
圖 2.17 page5 指定ROM的初始化hex文件
(6) 在 page6 上,不需要進行任何更改
(7) 在page7上,選擇需要生成的文件,這里我們勾選上mc8051_rom_inst.vhd。然后點“finish”即可生成 ROM 宏單元了。其中 mc8051_rom.vhd 為生成的VHDL 源文件。如圖 2.18 所示
圖 2.18 page7 指定需要生成的文件
(2) 生成RAM模塊
MC8051 中 RAM 模塊包括內部 RAM 和擴展 RAM,其生成方法和 ROM 的生成方法差不多。這里只簡單的說一下參數設置,詳細的步驟可參考 ROM 模塊的生成這一部分的內容。
(1) 內部 RAM 的參數設置 在如圖 2.14 所示的對話框中輸入ram,在搜索結果中選擇 RAM:1-PORT 模塊,並將其命名為 mc8051_ram;設置數據寬度為 8bits,數據個數為 128;取消 RAM 的數據輸出寄存器,同時選中時鍾使能信號端,如圖 2.19所示;勾選上生成mc8051_ram_inst.vhd文件,其它的選項默認不變。
圖 2.19 page7 RAM設置
(2) 擴展 RAM 的參數設置 在如圖 2.14 所示的對話框中輸入ram,在搜索結果中選擇 RAM:1-PORT 模塊,並將其命名為 mc8051_ramx;設置數據寬度為 8bits,數據個數為 2048;取消 RAM 的數據輸出寄存器;不需要選中時鍾使能信號端,如圖 2.20所示;勾選上生成mc8051_ramx_inst.vhd文件,其它的選項默認不變。
圖 2.20 page7 RAM設置
至此我們已經完成了 mc8051 中 ROM、RAM 模塊的生成。下面將介紹如何對 mc8051
core 進行封裝,也可以說是對 mc8051 core 進行打包,方便於以后的設計調用。
2.2 MC8051 core 的組裝
到現在為止,MC8051核RTL級實現的所有模塊都已經具備了,接下來就使用將這些模塊組裝到一起,得到一個含完整mc8051核的Quartus· II工程,在新建工程之前我們還要對一些 mc8051 core 的源文件進行更新修改,使之符合我們的設計。
2.2.1 更新 mc8051 core 的頂層源文件
由於默認提供的源碼中的頂層設計文件中的存儲模塊(ROM、RAM)是仿真時使用的, 現在要進行硬件測試,所以必須改成我們實際用到的 ROM、RAM 模塊(也就是前一節我們生成的 ROM、RAM 模塊)。
(1) 首先在工程目錄下新建一個 mc8051core 的文件夾,將 mc8051 core 的源代碼文件(位於:\mc8051_Source\VHDL 目錄)拷貝到 mc8051core 文件夾。
(2) 打開 mc8051_Source\VHDL 目錄下的 mc8051_p.vhd 文件,將原文件中 ROM、RAM 模塊調用的代碼(如程序清單 2.1 所示)全部替換為符合本設計的程序代碼(如程序清單 2.2 所示)。
程序清單 2.1 mc8051_p.vhd 文件代修改代碼
-------------------------------------------------------------------- -- START: Component declarations for simulation models -------------------------------------------------------------------- component mc8051_ram port ( clk : in std_logic; reset : in std_logic; ram_data_i : in std_logic_vector(7 downto 0); ram_data_o : out std_logic_vector(7 downto 0); ram_adr_i : in std_logic_vector(6 downto 0); ram_wr_i : in std_logic; ram_en_i : in std_logic); end component; component mc8051_ramx port ( clk : in std_logic; reset : in std_logic; ram_data_i : in std_logic_vector(7 downto 0); ram_data_o : out std_logic_vector(7 downto 0); ram_adr_i : in std_logic_vector(15 downto 0); ram_wr_i : in std_logic); end component; component mc8051_rom port ( clk : in std_logic; reset : in std_logic; rom_data_o : out std_logic_vector(7 downto 0); rom_adr_i : in std_logic_vector(15 downto 0)); end component; -------------------------------------------------------------------- -- END: Component declarations for simulation models --------------------------------------------------------------------
程序清單 2.2 mc8051_p.vhd 文件更新的源代碼
-------------------------------------------------------------------- -- START: Component declarations for simulation models -------------------------------------------------------------------- component mc8051_ram port ( clock : in std_logic; data : in std_logic_vector(7 downto 0); q : out std_logic_vector(7 downto 0); address : in std_logic_vector(6 downto 0); wren : in std_logic; clken : in std_logic); end component; component mc8051_ramx port ( clock : in std_logic; data : in std_logic_vector(7 downto 0); q : out std_logic_vector(7 downto 0); address : in std_logic_vector(10 downto 0); wren : in std_logic); end component; component mc8051_rom port ( clock : in std_logic; q : out std_logic_vector(7 downto 0); address : in std_logic_vector(11 downto 0)); end component; -------------------------------------------------------------------- -- END: Component declarations for simulation models --------------------------------------------------------------------
(3) 打開 mc8051core目錄下的 mc8051_top_struc.vhd 文件,首先做如程序清單 2.3 所示修改,其中行末標注“--new”的行為新增加的內容。然后將原文件中 ROM、RAM 模塊調用部分的代碼修改成如程序清單 2.4 所示的代碼。這樣就完成了源文件更新修改。
程序清單 2.3 mc8051_top_struc.vhd 文件新增的代碼
architecture struc of mc8051_top is signal s_rom_adr_sml: std_logic_vector(11 downto 0); -- new signal s_ramx_adr_sml: std_logic_vector(10 downto 0); -- new signal s_rom_adr: std_logic_vector(15 downto 0); -- Programmcounter = -- ROM-adress signal s_rom_data: std_logic_vector(7 downto 0); -- data input from ROM signal s_ram_data_out: std_logic_vector(7 downto 0); -- data output to -- internal RAM signal s_ram_data_in: std_logic_vector(7 downto 0); -- data input from -- internal RAM signal s_ram_adr: std_logic_vector(6 downto 0); -- internal RAM-adress signal s_ram_wr: std_logic; -- read (0)/write (1) -- internal RAM signal s_ram_en: std_logic; -- RAM-block enable signal s_ramx_data_out: std_logic_vector(7 downto 0); -- data output to -- ext. RAM signal s_ramx_data_in: std_logic_vector(7 downto 0); -- data input from -- ext. RAM signal s_ramx_adr: std_logic_vector(15 downto 0); -- ext. RAM-adress signal s_ramx_wr: std_logic; -- read (0)/write (1) -- ext. RAM begin -- architecture structural s_rom_adr_sml <= std_logic_vector(s_rom_adr(11 downto 0)); -- *** new s_ramx_adr_sml <= std_logic_vector(s_ramx_adr(10 downto 0)); -- *** new i_mc8051_core : mc8051_core port map(clk => clk, reset => reset, rom_data_i => s_rom_data,
其中,
和
就是新增加的內容
程序清單 2.4 mc8051_top_struc.vhd 文件中更新的源代碼
-------------------------------------------------------------------- -- Hook up the general purpose 128x8 synchronous on-chip RAM. i_mc8051_ram : mc8051_ram port map ( clock => clk, data => s_ram_data_in, q => s_ram_data_out, address => s_ram_adr, wren => s_ram_wr, clken => s_ram_en); -- THIS RAM IS A MUST HAVE!! -------------------------------------------------------------------- -------------------------------------------------------------------- -- Hook up the (up to) 64kx8 synchronous on-chip ROM. i_mc8051_rom : mc8051_rom port map ( clock => clk, q => s_rom_data, address => s_rom_adr_sml); -- THE ROM OF COURSE IS A MUST HAVE, ALTHOUGH THE SIZE CAN BE SMALLER!! -------------------------------------------------------------------- -------------------------------------------------------------------- -- Hook up the (up to) 64kx8 synchronous RAM. i_mc8051_ramx : mc8051_ramx port map ( clock => clk, data => s_ramx_data_out, q => s_ramx_data_in, address => s_ramx_adr_sml, wren => s_ramx_wr); -- THIS RAM (IF USED) CAN BE ON OR OFF CHIP, THE SIZE IS ARBITRARY. --------------------------------------------------------------------
2.2.2 添加mc8051 Core相關文件到Quartus II工程中
在將mc8051的源碼添加到Quartus II工程前,我們需要首先對部分文件的文件名進行更改。原版的VHDL源碼,部分文件的文件名末尾加了有“_”,而實際源碼中的模塊名沒有加“_”,因此,如果將這些文件直接添加到Quartus II工程中,編譯就會報錯,提示找不到模塊。
因此我們首先將源碼文件以“_”結尾的文件名中的“_”全部去掉,例如,將“addsub_core_.vhd”更改為“addsub_core.vhd”。當所有的文件名更改完成之后,方可添加這些文件到工程中。
在Quartus II軟件中,點擊【Project】>>【Add/Remove Files in Project】,在彈出的對話框中,點擊瀏覽文件符號,如圖 2.21 所示:
圖 2.21 添加文件按鈕
選擇mc8051core文件夾下的所有非配置文件(即以cfg結尾的文件不用選中),然后點擊打開按鈕,即可將文件添加到工程中來。如圖 2.22 所示:
圖 2.22 選擇需要添加的文件
點“OK”完成文件的添加。
2.2.3設置工程頂層文件
在Files欄中,選中mc8051_top.vhd文件,點擊右鍵,選擇“Set as Top-Level Entity”,即可將mc8051_top.vhd設置為工程的頂層文件,(這里設置為頂層主要是為了封裝IP核方便,臨時性的,並不是最終作為工程頂層)。如圖 2.23 所示:
圖 2.23 選擇需要添加的文件
2.2.4 綜合工程文件
(1) 綜合工程
在 Quartus II 軟件的主界面,點擊分析和綜合按鈕(或者直接按鍵盤組合鍵ctrl+k),即可開始對工程進行分析和綜合。這個過程大概需要幾分鍾到十幾分鍾,視軟件版本和電腦配置,耗費時間有差異。
(2) 查看RTL圖
綜合編譯后我們需要檢查頂層設計是否正確,這時可以通過 RTL 圖來檢查,雙擊RTL Viewer,如圖2.24 所示
圖 2.24 點擊打開RTL Viewer
按鈕可以打開 RTL 圖,我們可以很清晰的看到 8051 core 的頂層結構圖,如圖 2.25所示。如果沒問題我們就可以進行下一步的設計了。
圖 2.25 mc8051 core RTL 圖
2.3 MC8051 core 在 Quartus II 中的應用
在看這節內容之前建議大家先看一下 2.4 節,了解一下單片機的應用測試程序及測試流
程,因為這兩部分內容是同時進行,密切關聯。
在這一節我們將對 2.1 節建立的 Quartus 工程做進一步的設計,並將 mc8051 core 應用
於設計中。同時對 Quartus 的簡單應用做進一步的學習。具體包括以下內容:
1. 建立 PLL 數字鎖相環模塊;
2. mc8051 core 在 Quartus II 中的應用設計;
3. FPGA 參數設置;
4. 下載硬件設計到目標 FPGA。
2.3.1 建立 PLL 數字鎖相環模塊
眾所周知,單片機需要時鍾信號才能運行,那怎樣才能得到一個穩定而可靠的時鍾源呢?我們的實驗板上有一個 50MHz 的有源晶振,但對於 mc8051core 來說,頻率比較高,需要分頻,這時可以用 FPGA 自帶的 PLL 調整時鍾頻率,PLL 輸出的時鍾頻率、相位都可調而且精度很高,下面我們將介紹如何在 Quartus II 中調用 PLL 模塊。
(1) 打開我們在 2.1 節建立的 QuartusII 工程,從【Tool】>>【MegaWizard Plug-In Manager…】打開如圖 2.13 所示的添加宏單元的向導。
(2) 在圖 2.13 中按進入向導第 2 頁,按圖 2.26 所示輸入“pll”選擇 ALTPLL,並選擇器件類型及存放路徑,注意標記部分。
圖 2.26 MegeWizard Plug-In Manager page2
(3) 在圖 2.26 中按進入向導第 3 頁,按圖 2.27 所示選擇和設置,注意標記部分。由於電路板上的有源晶振頻率為 50MHz,所以輸入頻率設為 50MHz。
圖 2.27 page3 設置輸入時鍾頻率
(4) 在圖 2.27 中按進入向導第 4 頁,在圖 2.28 所示的窗口選擇 PLL 的控制信號,如 PLL 使能控制“pllena”;異步復位“areset”;鎖相輸出“locked”等。這里我們不選任何控制信號。
圖 2.28 page4 設置控制信號
(5) 在圖 2.28中按連續按下直到進入向導第8頁,按圖2.30所示選擇c0輸出頻率為18MHz,時鍾相移和占空比不改變。
圖 2.29 page8 設置時鍾輸出頻率
(6) 在圖 2.29 中按進入向導第 9 頁 c1 的設置界面,由於c1以及后續其他輸出都不再使用,因此,這里可以直接跳過其他所有輸出的配置,直到最后按
完成 PLL 兆功能模塊的定制。
在完成定制 PLL 后,在 Quartus II工程文件夾中將產生 pll.bsf文件和 pll.v 的Verilog HDL源文件。
2.3.2 建立MC8051應用工程,
這一小節將講述如何使用以上移植的mc8051的核建立一個實際的Quartus II 工程並能夠在芯航線FPGA學習套件的主板上運行。 具體步驟如下:
(1) 在工程頂層中例化mc8051核
(2) 在工程頂層中例化pll
(3) 對工程進行分析和綜合
(4) 分配引腳
(5) 編譯並生成FPGA配置文件
(6) 使用USB Blaster配置FPGA
打開之前建立的Quartus II工程,打開mc8051_test.v文件,首先編寫模塊的端口,這個模塊的端口也是工程最終的對外引腳,這里直接設置模塊端口為mc8051的IO。 如程序清單2.5的第1行至第23行所示。
接着在工程中例化mc8051核,這里就是例化mc8051_top。Quartus II中,可以直接在Verilog文件中例化使用VHDL編寫的模塊,因此這里直接按照Verilog的格式例化mc8051_top即可,如程序清單2.5的第33行至第56行所示。注意,mc8051核的復位端口是高電平復位,而我們開發板上是將復位信號接到了輕觸按鍵上,輕觸按鍵在沒有被按下時,輸出的是高電平,因此該信號不能直接接到mc8051的復位輸入端,需要先將其取反,因此直接在例化時將Rst_n取反后連接到mc8051的reset端即可(第36行)。
然后在工程中例化pll核,例化pll的代碼如程序清單2.5的第27行至第31行所示,pll的時鍾輸入端連接到芯片的時鍾輸入信號Clk50M上,c0輸出為18M,連接到mc8051的時鍾輸入端口clk上。
程序清單 2.5 mc8051_test.v 文件的源代碼
01 module mc8051_test( 02 input Clk50M,//板級時鍾源,50M 03 input Rst_n, //復位端口 04 input int0_i, //mc8051外部中斷0輸入 05 input int1_i, //mc8051外部中斷1輸入 06 input all_t0_i, //mc8051計數器0輸入 07 input all_t1_i, //mc8051計數器1輸入 08 09 input [7:0]p0_i, //mc8051端口0輸入 10 input [7:0]p1_i, //mc8051端口1輸入 11 input [7:0]p2_i, //mc8051端口2輸入 12 input [7:0]p3_i, //mc8051端口3輸入 13 14 output [7:0]p0_o, //mc8051端口0輸出 15 output [7:0]p1_o, //mc8051端口1輸出 16 output [7:0]p2_o, //mc8051端口2輸出 17 output [7:0]p3_o, //mc8051端口3輸出 18 19 input all_rxd_i, //mc8051串口接收端口 20 output all_rxd_o, //mc8051串口方式0時輸出端口 21 output all_txd_o, //mc8051串口發送端口 22 output all_rxdwr_o //rxd 輸入/輸出方向控制信號(高電平輸出) 23 ); 24 25 wire Clk18M; 26 27 //例化PLL模塊 28 pll pll( 29 .inclk0(Clk50M), 30 .c0(Clk18M) 31 ); 32 33 //例化mc8051核 34 mc8051_top mc8051_top_inst( 35 .clk(Clk18M), 36 .reset(~Rst_n), //mc8051為高電平復位,因此將復位按鍵狀態取反接到reset上 37 .int0_i(int0_i), 38 .int1_i(int1_i), 39 .all_t0_i(all_t0_i), 40 .all_t1_i(all_t1_i), 41 42 .p0_i(p0_i), 43 .p1_i(p1_i), 44 .p2_i(p2_i), 45 .p3_i(p3_i), 46 47 .p0_o(p0_o), 48 .p1_o(p1_o), 49 .p2_o(p2_o), 50 .p3_o(p3_o), 51 52 .all_rxd_i(all_rxd_i), 53 .all_rxd_o(all_rxd_o), 54 .all_txd_o(all_txd_o), 55 .all_rxdwr_o(all_rxdwr_o) 56 ); 57 58 endmodule
接着我們將mc8051_test.v文件設置為工程頂層,然后點擊分析和綜合按鈕(或者按下鍵盤組合鍵ctrl+k)來對工程進行分析和綜合。
分析和綜合完成后,我們打開Pin planner,進行引腳的鎖定。依次點擊【Assignments】>>【Pin Planner】,如圖 2.30所示:
圖 2.30 打開引腳分配卡
這里,我們只需要分配我們使用到的部分外設,沒有使用到的暫不做引腳分配。本例中,我們將在Keil中編寫軟件代碼測試mc8051的定時器、串口和P1口。我們使用開發板上板載的4個led燈進行測試P1口P1_o[0:3]的測試。因此我們需要分配引腳的端口有P1_o[0:3],all_rxd_i,all_txd_o,Clk50M以及Rst_n。其他沒有使用的端口暫不分配引腳。引腳分配表如下所示:
將以上引腳對應分配給相應的信號即可。分配結果如圖 2.31所示:
圖 2.31 引腳分配結果
引腳分配完畢后,關閉Pin Planner,點擊Start Compilation(或者鍵盤組合鍵ctrl+L)·來對工程進行全編譯並生成FPGA配置文件(.sof)。
編譯完畢后,使用USB Mini線連接芯航線FPGA開發板,連接上USB Blaster,然后打開Programmer,在Hardware Setup中選擇USB Blaster。添加mc8051_test.sof文件,然后點擊start即可將生成的配置文件下載到FPGA芯片中。如圖 2.32所示:
圖 2.32 引腳分配結果
2.4 測試 MC8051 的 I/O、UART 和定時器功能
在這一節中我們將通過一個簡單的流水燈、UART 程序驗證我們的 mc8051 core。
2.4.1 Keil C 測試程序
我們的 mc8051 core 已經建立起來了,現在需要一個程序進行硬件測試,這里的程序
是指普通的 51 程序,可以用 Keil C 或其它工具來編譯我們寫的測試程序,並生成.HEX 文件具體的操作過程就不用做介紹了。
如程序清單 2.6 所示是一個簡單的測試程序,用於測試 I/O、定時器和 UART。定時器 0 用來做流水燈控制,從 P1 口輸出;串口波特率(9600b/s)由定時器 1 決定 。
程序清單 2.6 mc8051 IP核測試程序
/************************************************* * mc8051 IP核I/O、Timer、UART 測試程序 * 時鍾頻率:18MHz * 文件名:main.c *************************************************/ #include<reg51.h> #include<stdio.h> #define uchar unsigned char #define uint unsigned int char xdata Xcount _at_ 0x500; //定義外部 RAM 變量 uchar led=0xff; //LED 初化值 uchar counter; //500ms 計數器 //*************************** 延時程序 void delay(uint n) { uint k; while(n--); { for (k=0;k<40000;k++) {;} } } //*************************** 定時器中斷 0 程序 void timer0(void) interrupt 1 { ET0=0; //關定時器 0 中斷 TR0=0; //不允許定時器 0 計數 TH0=0x8a; //重裝定時初值(18MHz) TL0=0xd0; TR0=1; //允許時器 0 計數 if(++counter==25) //500ms 計數 { counter=0; if(led==0xf0) led=0xff; else led<<=1; //左移 1 位 } P1=led; //輸出到 P0 口 ET0=1; } //*************************** UART 程序 char putchar(char c) { SBUF = c; if (c == '\n') SBUF = 0x0D; while (!TI); TI = 0; return (c); } //*************************** 主程序 main() { SCON = 0x50; //選擇模式 1, 8 位數據格式,使能 UART PCON |= 0x80; //波特率加倍 TMOD = 0x21; //定時器 0:模式 1;定時器 1:模式 2 TH0=0x8a; //20ms 定時初值(18MHz) TL0=0xd0; TH1 = 0xF6; //定時器 1 自動裝載初值, 時鍾頻率 18MHz, 0xF6(9600bps) TL1 = 0xF6; TR0=1; //允許定時器 0 計數 TR1 = 1; //定時器 1 計數使能 ET0=1; //允許定時器 0 中斷 EA=1; //開總中斷 Xcount=0; while(1) { printf("Xiao MeiGe 8051 System On FPGA\n"); printf("Xin Hangxian Starter Board\n"); printf("http://xiaomeige.taobao.com/\n"); printf("This is the UART and led experiment\n"); printf("Xcount = %02bX\n",Xcount++); printf("20160101\n"); printf("\n\n\n\n"); printf("hello world\n"); delay(30000); delay(30000); delay(30000); delay(30000); delay(30000); delay(30000); } }
2.4.2 測試步驟
將程序清單 2.6 的程序進行編譯並生成.hex 文件,為了方便大家測試,我們提供了一個創建好的Keil工程,在“mc8051_test\Cproject\uart_led”目錄下,使用Keil C51 v4打開。
在Quartus II軟件中,依次選擇【Tools】>>【In-System Memory Content Editor】,打開In-System Memory Content Editor工具,右側選擇Hardware為USB-Blaster [USB-0],如圖 2.33所示:
圖 2.33 選擇下載器
然后工具會自動搜索到器件和器件中存在的支持該工具的節點,搜索完成后整個工具界面如圖 2.34所示:
圖 2.34 In-System Memory Content Editor界面
鼠標選中ROM0(這里是我在配置ROM核的時候修改的索引名,如果你在配置的時候忘了修改索引名,則這里默認顯示的名字應該是NONE),點擊右鍵,選擇Import Data From File。定位到C工程目錄下,我這里為:E:\CoreCourse_fpga\mc8051_test\Cproject\uart_led,選擇uart_led_test.hex文件並打開。這時候我們可以看到,工具下方已經有數據了,我們點擊下傳按鈕以將數據傳輸進FPGA中的ROM中。如圖 2.35所示:
圖 2.35 下載程序到mc8051的ROM中
然后,我們打開電腦上的串口調試工具(任意一個你熟悉的就行),我這里使用友善串口調試助手,選擇板子端口對應串口,設置波特率為9600,數據位為8位,無校驗位,1位停止位,接收格式為ASCII。然后點擊打開串口,則可以看到串口接收窗口中接收到了開發板傳輸過來的數據。同時板子開發板上的4個LED燈循環依次點亮。如圖 2.36所示:
圖 2.36 串口接收的數據
當我們的程序調試無誤后需要固定到芯片中永久使用時,就將編譯好的hex文件名稱修改為mcu_test.hex,替換工程目錄下原有的mcu_test.hex文件,然后重新編譯文件,然后配置FPGA即可。
小梅哥
2016年2月26日星期五
芯航線電子工作室
小梅哥店鋪鏈接:https://xiaomeige.taobao.com/
關於學習資料,小梅哥系列所有能夠開放的資料和更新(包括視頻教程,程序代碼,教程文檔,工具軟件,開發板資料)都會發布在我的雲分享。(記得訂閱)鏈接:http://yun.baidu.com/share/home?uk=402885837&view=share#category/type=0
贈送芯航線AC6102型開發板配套資料預覽版下載鏈接:鏈接:http://pan.baidu.com/s/1slW2Ojj 密碼:9fn3
贈送SOPC公開課鏈接和FPGA進階視頻教程。鏈接:http://pan.baidu.com/s/1bEzaFW 密碼:rsyh
附錄 A MC8051 指令表
附表 1 MC8051 指令表