12.7 PicoBlaze 設計實例
一、 設計要求
1. PICOBLAZE 嵌入式系統,包括1 個8 位的方波輸出口,一個驅動兩位7 段LED 的輸出口,一個時鐘輸入和一個中斷輸入。
2. 在Spartan-3an starter 套件中實現。
二、 設計過程
1. 在ISE 11.x中建立一個新的項目,項目名為kcpsm3_int_test,并加入源文件kcpsm3.vhd,這僅僅是一個PicoBlaze控制器核文件,讀者可以根據自己的愛好選擇不同的設計語言。
2. 編寫PicoBlaze的匯編語言源程序,本例中的匯編源程序為int_test.psm,具體如下。
;Interrupt example
;
CONSTANT waveform_port, 02 ;定義方波輸出端口ID為02
CONSTANT counter_port, 04 ;定義中斷計數器輸出端口ID為04
CONSTANT sel_port, 08 ;定義2位7段LED選擇輸出端口ID為08
CONSTANT pattern_10101010, AA ;定義方波輸出口初始值
CONSTANT ini_sel, 01 ;定義2位7段LED位選初始值為01
NAMEREG sA, interrupt_counter ;將sA寄存重新命名為interrupt_counter
;
start: LOAD interrupt_counter, 00 ;中斷計數寄存器清零
LOAD s2, pattern_10101010 ;將方波數據載入寄存器s2中
LOAD sD, ini_sel ;將位選值裝載入寄存器sD中
ENABLE INTERRUPT ;使能中斷
;
drive_wave: OUTPUT s2, waveform_port ;輸出方波
OUTPUT sD, sel_port ;輸出LED位選
LOAD s0, FF ;延時
loop3: LOAD s1, FF
loop4: SUB s1, 01
ADD s1, 01
SUB s1, 01
JUMP NZ, loop4
SUB s0, 01
JUMP NZ, loop3
XOR s2, FF ;方波值取反
XOR sD, FF ;位選值取反
JUMP drive_wave
;
ADDRESS 2B0 ;定義程序存儲地址
int_routine: ADD interrupt_counter, 01 ;中斷計數器加1
OUTPUT interrupt_counter, counter_port ;輸出計數值
OUTPUT sD, sel_port ;輸出位選
LOAD sF, FF ;延時
loop1: LOAD sE, FF
loop2: SUB sE, 01
ADD sE, 01
SUB sE, 01
JUMP NZ, loop2
SUB sF, 01
JUMP NZ, loop1
XOR sD, FF
RETURNI ENABLE ;中斷返回
;
ADDRESS 3FF ;中斷入口地址
JUMP int_routine
3. 將int_test.psm 文件拷貝到Assembler 目錄下, 運行DOS 命令, 進入
Assembler 目錄,運行如下命令:
kcpsm3 int_test.psm > screen 回車
編譯后Assembler 目錄中產生了一些新的文件, 如圖12-30 所示。其中INT_TEST.VHD/INT_TEST.V 文件為我們需要的文件,它就是PicoBlaze 的程序存儲器文件,將它加入到kcpsm3_int_test 項目中。可以看到,生成的PROM 文件名與匯編源程序的文件名相同。
圖12-30 編譯后Assembler 目錄文件
其中screen 文件為一個文本文件,編譯過程記錄在此文件中,如果源文件有錯誤,錯誤信息會在此文件中找到。
4. 建立一個頂層文件。在頂層文件中完成PROM 文件以及PicoBlaze 核文件的連接。下面對頂層文件進行簡要說明。
例化kcpsm3 和INT_TEST。
初始化未用的PicoBlaze 輸入引腳in_port 和reset。
擴展輸出寄存器, 分別是waveforms 、counter 和sel,其端口ID 分別為0x02、0x04 和0x08。
中斷輸入邏輯。
將計數器的結果譯碼為7 段LED 的輸入編碼。
頂層文件源代碼如下。
--
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
--
-------------------------------------------------------------------------
entity kcpsm3_int_test is
Port ( LED : out std_logic_vector(6 downto 0);
waveforms : out std_logic_vector(7 downto 0);
interrupt_event : in std_logic;
clk : in std_logic;
selp : out std_logic);
end kcpsm3_int_test;
-------------------------------------------------------------------------
architecture Behavioral of kcpsm3_int_test is
--
component kcpsm3
Port ( address : out std_logic_vector(9 downto 0);
instruction : in std_logic_vector(17 downto 0);
port_id : out std_logic_vector(7 downto 0);
write_strobe : out std_logic;
out_port : out std_logic_vector(7 downto 0);
read_strobe : out std_logic;
in_port : in std_logic_vector(7 downto 0);
interrupt : in std_logic;
interrupt_ack : out std_logic;
reset : in std_logic;
clk : in std_logic);
end component;
--
component int_test
Port ( address : in std_logic_vector(9 downto 0);
instruction : out std_logic_vector(17 downto 0);
clk : in std_logic);
end component;
--
-------------------------------------------------------------------------
signal address : std_logic_vector(9 downto 0);
signal instruction : std_logic_vector(17 downto 0);
signal port_id : std_logic_vector(7 downto 0);
signal out_port : std_logic_vector(7 downto 0);
signal in_port : std_logic_vector(7 downto 0);
signal write_strobe : std_logic;
signal read_strobe : std_logic;
signal interrupt : std_logic :='0';
signal interrupt_ack : std_logic;
signal reset : std_logic;
signal counter : std_logic_vector(7 downto 0);
signal HEX0 : std_logic_vector(3 downto 0);
signal HEX1 : std_logic_vector(3 downto 0);
signal HEX : std_logic_vector(3 downto 0);
signal sel : std_logic;
--
-------------------------------------------------------------------------
begin
processor: kcpsm3
port map( address => address,
instruction => instruction,
port_id => port_id,
write_strobe => write_strobe,
out_port => out_port,
read_strobe => read_strobe,
in_port => in_port,
interrupt => interrupt,
interrupt_ack => interrupt_ack,
reset => reset,
clk => clk);
program: int_test
port map( address => address,
instruction => instruction,
clk => clk);
-- Unused inputs on processor
in_port <= "00000000";
reset <= '0';
-- Adding the output registers to the processor
IO_registers: process(clk)
begin
if clk'event and clk='1' then
-- waveform register at address 02
if port_id(1)='1' and write_strobe='1' then
waveforms <= out_port;
end if;
-- Interrupt Counter register at address 04
if port_id(2)='1' and write_strobe='1' then
counter <= out_port;
end if;
-- sel port register at address 08
if port_id(3) = '1' and write_strobe = '1' then
sel <= out_port(0);
end if;
end if;
end process IO_registers;
-- Adding the interrupt input
-- Note that the initial value of interrupt (low) is
-- defined at signal declaration.
interrupt_control: process(clk)
begin
if clk'event and clk='1' then
if interrupt_ack='1' then
interrupt <= '0';
elsif interrupt_event='1' then
interrupt <= '1';
else
interrupt <= interrupt;
end if;
end if;
end process interrupt_control;
HEX0 <= counter(3 downto 0);
HEX1 <= counter(7 downto 4);
with HEX SELect
LED <= "0000110" when "0001", --1
"1011011" when "0010", --2
"1001111" when "0011", --3
"1100110" when "0100", --4
"1101101" when "0101", --5
"1111101" when "0110", --6
"0000111" when "0111", --7
"1111111" when "1000", --8
"1101111" when "1001", --9
"1110111" when "1010", --A
"1111100" when "1011", --b
"0111001" when "1100", --C
"1011110" when "1101", --d
"1111001" when "1110", --E
"1110001" when "1111", --F
"0111111" when others; --0
HEX <= HEX0 when sel = '0' else HEX1;
selp <= sel;
end Behavioral;
添加約束文件,約束文件內容如下。
NET "clk" LOC = "E12"|IOSTANDARD = LVCMOS33 ;
NET "selp" LOC = "AB19"|IOSTANDARD = LVCMOS33|SLEW = SLOW|DRIVE = 8;
NET "LED<6>" LOC = "AA19"|IOSTANDARD = LVCMOS33|SLEW = SLOW|DRIVE = 8;
NET "LED<5>" LOC = "AB21"|IOSTANDARD = LVCMOS33|SLEW = SLOW|DRIVE = 8;
NET "LED<4>" LOC = "AA21"|IOSTANDARD = LVCMOS33|SLEW = SLOW|DRIVE = 8;
NET "LED<3>" LOC = "V16"|IOSTANDARD = LVCMOS33|SLEW = SLOW|DRIVE = 8;
NET "LED<2>" LOC = "W16"|IOSTANDARD = LVCMOS33|SLEW = SLOW|DRIVE = 8;
NET "LED<1>" LOC = "V15"|IOSTANDARD = LVCMOS33|SLEW = SLOW|DRIVE = 8;
NET "LED<0>" LOC = "V14"|IOSTANDARD = LVCMOS33|SLEW = SLOW|DRIVE = 8;
NET "waveforms<0>" LOC ="R20"|IOSTANDARD=LVCMOS33|SLEW = SLOW|DRIVE = 8;
NET "waveforms<1>" LOC ="T19"|IOSTANDARD=LVCMOS33|SLEW = SLOW|DRIVE = 8;
NET "waveforms<2>" LOC ="U20"|IOSTANDARD=LVCMOS33|SLEW = SLOW|DRIVE = 8;
NET "waveforms<3>" LOC ="U19"|IOSTANDARD=LVCMOS33|SLEW = SLOW|DRIVE = 8;
NET "waveforms<4>" LOC ="V19"|IOSTANDARD=LVCMOS33|SLEW = SLOW|DRIVE = 8;
NET "waveforms<5>" LOC ="V20"|IOSTANDARD=LVCMOS33|SLEW = SLOW|DRIVE = 8;
NET "waveforms<6>" LOC ="Y22"|IOSTANDARD=LVCMOS33|SLEW = SLOW|DRIVE = 8;
NET "waveforms<7>" LOC ="W21"|IOSTANDARD=LVCMOS33|SLEW = SLOW|DRIVE = 8;
#PACE: Start of PACE Area Constraints
NET "interrupt_event" LOC = "T9"|IOSTANDARD = LVCMOS33|PULLUP ;
5. 綜合、布局布線。如圖12-31所示,在ISE中完成布局布線。
?
圖12-31 綜合、布局布線
6. 配置FPGA。用iMPACT配置FPGA。
7. 讀者可以在/CH12/kcpsm3_int_test中找到ISE工程文件,在/CH12/assembler中找到int_test.psm源文件。
12.8 小結
本章介紹了PicoBlaze微控制器,包括其基本結構、指令系統和開發工具,最后用一個簡單的實例介紹了PicoBlaze的開發流程。PicoBlaze具有精小、易用、靈活、高性能等優點,不會像很多MCU一樣停產,影響產品生命周期,可以方便地應用在Xilinx的FPGA中,特別適合應用于小型的控制系統中,用來實現狀態機控制,進行系統管理。
目前,FPGA已經廣泛地應用在游戲機產品、小型電機控制和醫療產品中,希望通過本章介紹,使其應用更加廣泛。
評論
查看更多