🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ## 一、简介 ### 1.1关于PicoBlaze ` `PicoBlaze 是 8 位微处理器,在 Xilinx 公司的 Virtex、Spartan-II 系列以上 FPGA 与 CoolRunner-II 系列以上的 CPLD 器件设计中以 IP 核的方式提供,使用是免费的 。对于用 FPGA 的 HDL 语言实现某些复杂的功能,会消耗大量的硬件资源,此时我们就会考虑用软件 的方式去搭建一个嵌入式系统,比如基于 MicroBlaze 的 8 位嵌入式系统。这样,我们就可 以使用轻量级的 PicoBlaze 实现。 ` `常见的版本有 KCPSM3 和 KCPSM6。其中 KCPSM6 支持 7 系列的 Xilinx FPGA。PicoBlaze 非常小,只有一个 VHDL/Verilog 文件,KCPSM6 在 FPGA 中只需要 26 块逻辑单元 Slice,每 个指令都可以再 2 个时钟周期内完成,在 Spartan-6 中可以达到 105MHz 时钟频率(-2 速度 等级),在 Kintex-7(-3 速度等级)中能到达 238MHz。 ### 1.2 接口说明 ` `Kcpsm6 外部信号很少,常用的就是 in_port 和 out_port。地址线和 bram_enable 以及 instruction 信号与 FPGA rom 相连,总的框架如下,以 KCPSM6 为例: ![](https://img.kancloud.cn/3f/c5/3fc5f5ac9d24e631351aba75c8e95ae8_1141x797.png) ### 1.3 KCPSM6 的架构 ` `具体架构如下,它能提供两个寄存器 Bank,每个 Bank 有 16 个寄存器。 ![](https://img.kancloud.cn/9c/99/9c99247e9382862dae5732f967f222d0_1112x753.png) ## 二、内部指令集 讲解 ` `通常使用汇编语言写 PicoBlaze 程序,以 KCPSM6 为例,我们基于它的指令集可以很方 便实现一些简单的程序,指令集如下(具体指令在附录): ` `具体介绍下主要的输入输出端口的操作指令: ` `Input sx,sy; 将 inport 的数据传入 sx,sy 输出到 port_id ` `Output sx,sy; 将 sx 的数据传出至 out_port,sy 输出到 port_id ![](https://img.kancloud.cn/09/45/09450fb39d57f0b8f7a1dedb494623df_1117x829.png) ## 三、操作指引 ### 3.1 概述 ` `Xilinx 提供了相应的汇编器,可以生成带指令数据的 ROM 的 VHDL/Verilog 代码,也可 以生成 HEX 文件供动态加载到 RAM。 ` `下面介绍开发流程,我们以一个简单的LED闪烁为例。 ` `首先,我们去 Xilinx 官网下载所需的 KCPSM6 的相关文件以及辅助程序。下载地址: http://www.xilinx.com/ipcenter/processor_central/picoblaze/member/ 本文基于 zynq7020 进行试验,所以只需要下载 PicoBlaze for UltraScale, 7-series, 6-series FPGAs 即可。下载后解压出来,会有很多实例,JTAG_Loader 以及 kcpsm6.exe 汇 编器等。 ### 3.2 生成微核 ` `先在文本中编辑好一个汇编程序,保存后把后缀名改为.psm,然后写一个简单的代码, 将输入直接输出,如下图(.psm 代码): ``` ;平台为zynq7系列,实现的功能是控制led灯,让其 ;500mss翻转一次,系统时钟为50MHz constant led_port,01 ;定义led_port为常量01 constant led_on,00000010'b ; constant led_off,00000000'b ; start: load sF, led_on; output sF,led_port ;led亮 CALL delay_500ms ;延时 load sF, led_off; output sF,led_port ;led灭 CALL delay_500ms ;延时 jump start ;跳转的开始 ; 500ms is 2,500,000 x 100ns (10,000,000 = 989680 hex) ; delay_500ms: LOAD s2, 26 LOAD s1, 25 LOAD s0, a0 JUMP software_delay software_delay: LOAD s0, s0 ;pad loop to make it 10 clock cycles (5 instructions),50MHz SUB s0, 1'd SUBCY s1, 0'd SUBCY s2, 0'd JUMP NZ, software_delay RETURN ``` ` `然后新建一个文件夹包含以下文件(如果缺少 ROM_form.v,是无法生成想要的文件的), ROM_form.v使用下载文件中verilog文件夹下的, 将其拷贝就可。 ![](https://img.kancloud.cn/ed/4d/ed4d3b60e071cf54f5eefe51dd5b7b9c_1084x336.png) ` `双击 kcpsm6.exe ![](https://img.kancloud.cn/70/78/707897f00a2541ce1adf4d2bcec0f85c_990x792.png) ![](https://img.kancloud.cn/46/db/46db349ef7cbd4ede430c282c641f67f_994x789.png) ` `回车,注意ROM_form.v一定要使用上问题到的那个, 不然不会生成.v文件。 ![](https://img.kancloud.cn/c7/fd/c7fd5789f4f8da3ae07ad0092864fd08_1008x794.png) ![](https://img.kancloud.cn/6f/17/6f17a970c410d31cae3ec0b75ba133d7_1184x530.png) ### 3.3 建立工程 ` `Kcpsm6 外部信号很少,常用的就是 in_port 和 out_port。地址线和 bram_enable 以及 instruction 信号与 FPGA rom 相连,在不使用中断和休眠信号的情况下将 interrupt 和 sleep 拉低即可。Clk 连接在 FPGA 外部输入的时钟引脚上,我们这里是 50MHz。本文使用 Verilog 语言实现硬件逻辑。 ` `编写的顶层文件如下: ``` `timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 2020/01/11 17:46:19 // Design Name: // Module Name: top // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module top( input clk, output reg led ); wire [11:0] address ; wire [17:0] instruction ; wire bram_enable ; reg [7:0] in_port ; wire [7:0] out_port ; wire [7:0] port_id ; wire write_strobe ; wire k_write_strobe ; wire read_strobe ; wire interrupt_ack ; reg reset; reg [31:0]cnt; wire pcreset; always@(posedge clk) begin if(cnt<=32'd5000)reset <= 1'b1; else if(cnt<=32'd10000)reset <= 1'b0; else reset <= 1'b1; if(cnt>=32'd10001)cnt <= 32'd10001; else cnt<=cnt + 1; end always@(posedge clk) begin if(!reset)begin led <= 1'b0; end else begin if(write_strobe)begin if(port_id==8'h01)begin led <= out_port[1]; end end end end (*dont_touch = "true"*)kcpsm6 #( .interrupt_vector(12'h3ff), .hwbuild(8'h00), .scratch_pad_memory_size(64)) processor( .address (address ), .instruction (instruction ), .bram_enable (bram_enable ), .in_port (in_port ), .out_port (out_port ), .port_id (port_id ), .write_strobe (write_strobe ), .k_write_strobe (k_write_strobe ), .read_strobe (read_strobe ), .interrupt (1'b0 ), .interrupt_ack (interrupt_ack ), .sleep (1'b0 ), .reset (pcreset ), .clk (clk ) ) ; led_water #( .C_JTAG_LOADER_ENABLE(0), .C_FAMILY("7S"), .C_RAM_SIZE_KWORDS(1)) program_rom( .address (address), .instruction (instruction), .enable (bram_enable), .clk (clk), .rdl (pcreset) ); endmodule ``` ` `在例化模块时要根据自己的FPGA芯片,来使用不同的参数。 ` `如图为 ROM_form.v 中对参数的介绍。 ![](https://img.kancloud.cn/f4/78/f478c32ffad1ac697be6783514a2643f_1127x291.png) ## 四、综合烧录 ` `最后添加对应的引脚约束,编译成功后生成 top.bit,就按正常的烧写步骤把 bit 文件 烧录到板上即可。