FPGA/ASIC技术
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已经广泛地应用在游戏机产品、小型电机控制和医疗产品中,希望通过本章介绍,使其应用更加广泛。
全部0条评论
                快来发表一下你的评论吧 !