PicoBlaze是8位微处理器,在Xilinx公司的Virtex、Spartan-II系列以上FPGA与CoolRunner-II系列以上的CPLD器件设计中以IP核的方式提供,使用是免费的 (百度百科)。
常见的版本有KCPSM3和KCPSM6。其中KCPSM支持7系列的Xilinx FPGA。
PicoBlaze非常小,只有一个VHDL/Verilog文件,KCPSM6在FPGA中只需要26块逻辑单元Slice,每个指令都可以再2个时钟周期内完成,在Spartan-6中可以达到105MHz时钟频率(-2速度等级),在Kintex-7(-3速度等级)中能到达238MHz。它能提供两个寄存器Bank,每个Bank有16个寄存器。
另外
很多时候我们用FPGA的HDL语言很难实现某些功能,但是用软件方式就比较容易,但是我们又不希望花很多硬件资源去搭建一个嵌入式系统,比如基于MicroBlaze的系统。这样,我们就可以使用轻量级的PicoBlaze实现。
通常使用汇编语言写PicoBlaze程序,以KCPSM6为例,我们基于它的指令集可以很方便实现一些简单的程序,指令集如下:
Xilinx提供了相应的汇编器,可以生成带指令数据的ROM的VHDL/Verilog代码,也可以生成HEX文件供动态加载到RAM。
下面介绍开发流程,我们以一个简单的开关输入LED输出为例,之后我们会介绍简单的流水灯以及中断。
首先,我们去Xilinx官网下载所需的KCPSM6的相关文件以及辅助程序。下载地址:http://www.xilinx.com/ipcenter/processor_central/picoblaze/member/
本文基于ZedBoard进行试验,所以只需要下载PicoBlaze for UltraScale, 7-series, 6-series FPGAs 即可。下载后解压出来,会有很多实例,JTAG_Loader以及kcpsm6.exe汇编器等。
以下是汇编器的功能图:
一般情况下,我们的处理器系统如下所示:
Kcpsm6处理器核与rom相连,rom中装载我们的编译后的代码数据。这两个模块都是通过工具生成,不过我们的程序还是需要写汇编代码实现。
Kcpsm6外部信号很少,常用的就是in_port和out_port,地址线和bram_enable以及instruction信号与rom相连,在不使用中断和休眠信号的情况下将interrupt和sleep拉低即可。Clk连接在FPGA外部输入的时钟引脚上,我们这里是Y9(100MHz)。
本文使用Verilog语言实现硬件逻辑。
创建一个基于ZedBoard的xc7z020-2clg484的工程。
建立一个顶层文件top.v,参照下载的文件夹中的Verilog目录中的kcpsm6_design_template.v,添加处理器核的例化
添加内部信号
另外,由于我们暂时没用到中断和休眠,将kcpsm6_sleep和interrupt拉低
我们再加入ROM的例化
将其中的
之后我们定义DIP开关作为输入管脚,并将内部In_port信号与其相连,定义输入管脚为LED,并将out_port信号与其相连。
现在,我们可以编写汇编程序了。这里先写一个最简单的程序,只是将输入端口01与输出端口01直接相连。
;8个LED
constant led_port,01
;8个DIP开关
constant dip_port,01
start: input s0,dip_port
output s0,led_port
jump start
其中生成的.v是我们现在需要的,也就是含指令的ROM的Verilog代码,.hex文件是后面我们通过JTAG_LOADER动态修改程序时候需要的。
将产生的.v文件连同kcpsm6.v一起拷贝到ISE项目下,并编写UCF文件进行管脚和电平约束。
综合,生成比特流之后,将top.bit用IMPACT下载到FPGA,就可以运行了。
下面我们换成流水灯的汇编程序。
;8个LED
constant led_port,01
load s0,01
output s0,led_port
start: call delay1s
SLA s0
;output s0,led_port
jump start
delay1s:
load s1,FF
call delay1
sub s1,01
output s1,led_port
jump c,delay1s
return
delay1:
load s2,FF
call delay2
sub s2,01
jump c,delay1
return;
delay2:
load s3,FF
call delay3
sub s3,01
jump c,delay2
return;
delay3:
load s4,04
sub s4,01
jump c,delay3
return;
这次我们编译后,使用JTAG_LOADER下载,不需要改变硬件配置。为了让JTAG_LOADER正常加载运行所需的dll,我们使用ISE Design Suite 64 Bit Command Prompt启动命令行,cd到JTAG_LOADER路径
因为本文PC为win7 x64,故使用JTAG_Loader_Win7_64.exe,过程如下
对于中断的测试,我们首先需要开启硬件中的中断连接,我们添加一个input输入,UCF中连接到按键上,并将处理器核的interrupt信号连接到int,interrupt_ack信号是在进入中断服务程序前的响应信号,这里没有使用。由于picoblaze只提供一个中断输入,要实现多级中断,需要自己在FPGA中实现对应逻辑。
然后我们修改汇编程序,首先开启中断ENABLE INTERRUPT,然后在结尾加上中断服务程序,中断服务程序会自动关闭中断,跳出时候再恢复。
以下参考http://xilinx.eetrend.com/blog/2328
中断时序图
完整的中断程序,中断修改了s7寄存器的值,使得流水灯由两个灯变成一个灯:
;8个LED
constant led_port,01
ENABLE INTERRUPT
load s7,03
main: load s0,s7
load sA,00
output s0,led_port
start: load s1,0F
call delay1s
SLA s0
compare s0,00
jump z,main
output s0,led_port
jump start
delay1s:
load s2,FF
call delay1
sub s1,01
COMPARE sA,s1
jump c,delay1s
return
delay1:
load s3,FF
call delay2
sub s2,01
COMPARE sA,s2
jump c,delay1
return
delay2:
load s4,04
call delay3
sub s3,01
COMPARE sA,s3
jump c,delay2
return
delay3:
sub s4,01
;COMPARE sA,s4
jump nc,delay3
return
;interrupt service routine
isr: load s7,01
returni ENABLE
address 3FF
JUMP isr