SOC开发流程入门(VIVADO+KEIL软硬件协同设计)

软硬件开发层次
设计总是从硬件到软件,硬件在底层,软件在顶层。
用FPGA配置成SOC之后,他还只是个空壳子,SOC的工作依赖一条条指令,生成指令是软件干的事,你需要用C或汇编写程序,写好的程序通过编译生成汇编代码,汇编代码通过arm指令集的对应转换,生成机器码。将机器码存在SOC的存储器,这时候SOC就能根据指令执行了。

SOC开发流程
1)我们用Verilog描述完一个soc之后,要用vivado编译,综合和实现,用硬件实现soc功能;
2)keil将c或汇编转换为机器码,仿真过程中将机器码作为verilog描述的ram的初始化内容,就可以进行仿真了;
3)仿真工具可以选用vivado自带仿真,也可使用modelsim。仿真后看到预期波形后,就可以将机器码下载到soc中,soc就可以执行你所编写的程序,开发板可以看到和波形预期的结果。

认识总线
认识总线的过程很麻烦,很痛苦,但要设计soc必须要和总线打交道,硬着头皮看吧,假设大家已经了解总线知识了。

Memory Map
我们挂在总线上的外设,在处理器核看来,只是memory map上一块连续区域,例如下图所示RAMCODE,其地址编码为 0x00000000-0x0000ffff,那么处理器核通过 AHB 总线发出的任何一次总线操作,只要地址总线上的值在 0x00000000-0x0000ffff 之间,都认为是处理器核在向 RAMCODE提出总线操作。
在这里插入图片描述

总线扩展
当SOC有多个外设,单处理器核只有一个master总线接口的情况下,就需要有总线扩展模块,使处理器核能访问多个外设。下图是单主机总线扩展模块,主要由两部分组成:Decoder 与 Slave MUX。
Decoder 的作用是对地址总线进行译码,生成对应的外设的选择信号,同样以RAMCODE 外设为例,由于其地址编码为 0x00000000-0x0000ffff,那么只要地址总线HADDR 的高 16bit 为 0x0000 时,地址总线的值必定处于 RAMCODE 的地址编码区域中,则判定为处理器核对 RAMCODE 提起的一次总线操作,因此 RAMCODE 对应的选择信号HSEL 将会被置位有效;
在这里插入图片描述
需要注意的是, 对于每个外设, Decoder 利用地址总线生成选择信号 HSEL 所需要的宽度是不同的。例如 RAMCODE 的地址编码为 0x00000000-0x0000ffff,其有效长度为0x0000-0xffff,那么 RAMCODE 对于的选择信号(HSEL_RAMCODE)需要对 HADDR 的高 16bit 进行译码;而 WaterLight 的地址编码为 0x40000000-0x4000000f,其有效长度为 0x0-0xf,因此 WaterLight 对应的选择信号需要对 HADDR 的高28bit 进行译码。

Slave MUX 的作用则是选中slave返回的数据,即通过每个外设的选择信号,对所有外设返回的读取数据(HRDATA)、响应信号(HRESP)以及反馈信号(HREADYOUT)进行选择,保证返回给Master 端口的数据来自于当前总线操作的目标外设。 例如当前总线操作是读取 RAMCODE的数据,那么所有外设的选择信号中只有 RAMCODE 对应的选择信号为‘1’,其他所有选择信号为‘0’,那么 Slave MUX 则根据这些选择信号选中 RAMCODE 返回的数据,保证处理器核能够正确读取。

每增加一个外设,只需要将外设Slave接口与上图 Master 接口相连接,再在 Dcoder 模块中添加对应的译码模块生成选择信号即可。

搭建SOC实例
本实验的目的是认识总线、 RAM、汇编与调试,走完soc设计流程;工程在我的主页免费下载;

实验要求:
在裸核+总线扩展模块的基础上,添加 Block RAM 与 BRAM总线接口模块,并将其接入总线扩展模块预留的 Master 接口下,然后完成 Decoder 模块中对 RAM 的译码,最终经过 vivado 编译、综合、实现,下载至 FPGA 中。完成硬件设计后,本节实验还需要学习 keil 的使用,以及编写简单的汇编代码,并通过调试器将代码下载至 SoC 中,利用 keil 进行调试运行。下图是本实验搭建的soc在这里插入图片描述
1.硬件部分
1.找到AHBlite_Decoder.v” 文件,修改 Decoder模块代码。
A. 在端口参数部分,令 RAMCODE 使能有效。(将parameter Port0_en = 0 改为 1)
B. 生成选择信号,根据 memory map 来修改,RAMCODE 的总线编码为 0x00000000-0x0000ffff,因为对于一次总线操作,只要地址总线的高 16 位为 0,则Decoder 认为这是一次对指令存储器的操作。(将assign P0_HSEL = 1’b0 改为assign P0_HSEL = (HADDR[31:16] == 16’h0000) ? Port0_en : 1’b0)

2.在顶层文件中将 RAMCODE 总线接口与总线扩展模块连接
在CortexM0_SoC.v 中,已经完成了处理器核、总线扩展模块、 RAMCODE 总线接口模块以及 Block RAM 模块的例化(调用这些模块,将这些模块添加至设计里面) , 但未在总线扩展模块接口部分连接 RAMCODE 总线接口。方法如下

将这段代码

/* Connect to Interconnect Port 0 */
.HCLK (clk),
.HRESETn (cpuresetn),
.HSEL (/*Port 0*/),
.HADDR (/*Port 0*/),
.HPROT (/*Port 0*/),
.HSIZE (/*Port 0*/),
.HTRANS (/*Port 0*/),
.HWDATA (/*Port 0*/),
.HWRITE (/*Port 0*/),
.HRDATA (/*Port 0*/),
.HREADY (/*Port 0*/),
.HREADYOUT (/*Port 0*/),
.HRESP (/*Port 0*/),
.BRAM_ADDR (RAMCODE_ADDR),
.BRAM_RDATA (RAMCODE_RDATA),
.BRAM_WDATA (RAMCODE_WDATA),
.BRAM_WRITE (RAMCODE_WRITE)

改为如下代码

/* Connect to Interconnect Port 0 */
.HCLK (clk),
.HRESETn (cpuresetn),
.HSEL (HSEL_P0),
.HADDR (HADDR_P0),
.HPROT (HPROT_P0),
.HSIZE (HSIZE_P0),
.HTRANS (HTRANS_P0),
.HWDATA (HWDATA_P0),
.HWRITE (HWRITE_P0),
.HRDATA (HRDATA_P0),
.HREADY (HREADY_P0),
.HREADYOUT (HREADYOUT_P0),
.HRESP (HRESP_P0),
.BRAM_ADDR (RAMCODE_ADDR),
.BRAM_RDATA (RAMCODE_RDATA),
.BRAM_WDATA (RAMCODE_WDATA),
.BRAM_WRITE (RAMCODE_WRITE)

硬件部分已改完
2.汇编、启动与 Keil 工具
软件部分只需修改启动代码“startup_CMSDK_CM0.s“
1)打开 Keil, 点击左上角 Project 菜单,选择 new uVision project,在“keil” 文件夹下新建名为 code 的工程,在第一个弹框初并选择 CMSDK_CM0
在这里插入图片描述
2.在左侧 Project 导航栏中,展开 Target1,右键点击 Source Group 1,在工程中添加之前编写的汇编文件
在这里插入图片描述
3.在左边导航栏处右键点击 Target 1,选择 Option,对 Target 栏进行配置。此步骤为将片上起始地址为 0x00000000,大小为 0x10000 的 Memory 作为ROM, Keil 将会通过调试器把程序下载到这一段存储器中。
在这里插入图片描述
4.在 Output 栏处修改输出文件夹,点击 Select Folder for Objects,将输出文件地址从 Objects 改为上一级文件夹地址,及工程所在文件夹地址在这里插入图片描述

5.勾选 Run #1,并在后面添加"fromelf -cvf .\code.axf --vhx --32x1 -o code.hex"
勾选 Run #2,并在后面添加:“fromelf -cvf .\code.axf -o code.txt”
在这里插入图片描述
6.在 Linker 处勾选 Use Memory Layout from Target Dialog 以及 Don’tSearch Standard Librarise
在这里插入图片描述
7. 在 Debug 处取消勾选 Load Application at Startup, 选择 CMSIS-DAPDebugger 并在工程目录下新建名为 code.ini 的启动脚本文件(在keil文件夹)在这里插入图片描述
8.进入 Debugger setting,选择 Flash Download 栏目,由于我们没有 Flash,所以选择 Do not Erase,并且取消勾选 Program 以及 Verify
在这里插入图片描述
9.在 Utilities 出取消勾选 Update Target before Debugging在这里插入图片描述
10.在“keil/startup_CMSDK_CM0.s” 文件中,实现 ARM 汇编编写计数,使得 R0 从 0 计数到 4 后重新开始计数,循环往复。在启动代码中加入下面这段程序

;Inset a loop algorithm there;
MOVS R1, #4
Clear MOVS R0, #0
Adder ADDS R0, R0, #1
CMP R0, R1
BEQ Clear
BNE Adder

在这里插入图片描述
11.编译在这里插入图片描述
12.去vivido,把生成的hex文件路径添加到RAM中,然后编译,生成比特流文件,然后到keil里调试。由于接下来这些步骤本人主页都可找得到。不加以赘述。

13.最终的实验现象:在红框 1 处为 CPU 内部寄存器的值,能够实时显示每一步寄存器值的变化,而在红框2 处为当前执行的汇编代码以及代码地址,在红框 3 处显示的是当前执行的源代码,这里的源代码既可以是汇编代码也可以是 C 语言代码。根据之前汇编语言编写的循环计数,在红框 1 处的 R1 的值保持为 4,而 R0 则应该在 0-4 之间循环计数。至此我们完成了最小 SoC 的设计,完成 AHB 总线扩展编写了 BRAM 以及 RAM 总线接口,编写了汇编代码并成功仿真与调试, SoC 的整个设计流程大致如此。
在这里插入图片描述

  • 7
    点赞
  • 67
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值