安路FPGA移植Cortex-M0内核

        本文是关于基于安路FPGA EG4S20BG256移植Cortex M0内核的笔记。硬件平台使用硬木课堂的安路核心板,软件使用安路的TD5.6.2和keil5。(博主刚学FPGA不久,文中有不足之处请帮忙指出)

        在移植之前,博主看了网上很多的文章、教程,感觉没有找到一篇手把手从头到尾移植的教程,或者缺少RAM IP核移植,或者缺少SWD、JTAG的引出,最后是结合了各家的代码和教程,以及ARM官方给的示例,移植完了M0内核。

        在移植之前,笔者已经学习了AHB总线、ARM内核、单片机、FPGA verilog基础语法部分。


一、准备部分

1.1 DesignStart计划

        ARM官方的DesignStart计划提供了Cortex-M0、Cortex-M3、Cortex-A5等内核,每一种IP也有不同的版本:Eval版,FPGA版,Pro版。其中Eval版本提供处理器核的网表形式的Verilog代码。

        进入网站:https://developer.arm.com/,搜索“Cortex-M0 Designstart Eval”,就可以找到Eval版的资源。下载资源需要登录ARM账号。

        如果注册ARM账号太麻烦,也可以在CSDN等其它平台上下载。

1.2 TD和Keil5准备

        安路FPGA开发需要使用安路官方的TD(TangDynasty),笔者使用的是TD5.6.2,好像TD不同版本支持的芯片是不一样,读者可以认真阅读以下安路官网。

        至于Keil5笔者就不再赘述了,开发ARM内核的必备,网上也有很多资源了。

        下载了TD还需要下载TD的License,注册以后免费下载。


二、解析ARM DesignStart

        解压之后,里面有文档说明,建议读者详细阅读ARM官方给的文档,里面说的很详细,虽然是全英文,可以带着翻译慢慢读,这对后面移植还是很有帮助的。

        documentation/arm_cortex_m0_designstart_eval_user_guide.pdf里第14页,1.2节有关于Cortex-M0 DesignStart Eval的目录结构说明。

        打开systems/cortex_m0_mcu/verilog/cmsdk_mcu.v,然后根据cmsdk_mcu.v中的模块,层层梳理,可以得到下图所示的结构。

将cmsdk_mcu.v看作一个顶层文件。

  • AHB_RAM和AHB_ROM,即RAM和ROM模块。
  • cmsdk_mcu_clkctrl:时钟控制模块。
  • cmsdk_mcu_pin_mux:引脚复用模块。
  • cmsdk_mcu_system:Cortex-M0系统的系统级设计。
    • cmsdk_mcu_addr_decode:AHB地址解码。
    • cmsdk_ahb_slave_mux:AHB从多路复用器。
    • cmsdk_ahb_default_slave:AHB总线默认从属设备,当被选择传输时返回error。
    • CORTEXM0INTEGRATION:Cortex-M0 DesignStart processor 集成级。
      • Cortexm0ds_logic:Cortex-M0 DesignStart processor 逻辑级。
    • cmsdk_ahb_cs_rom_table:该模块实现了一个通用的4入口的AHB CoreSight ROM Table。
    • cmsdk_mcu_sysctrl:系统控制器。
    • cmsdk_ahb_gpio:IOP GPIO外设。
    • cmsdk_mcu_stclkctrl:系统嘀嗒信号控制。
    • cmsdk_apb_subsystem:APB子系统
      • cmsdk_apb_slave_mux:APB从多路复用器
      • cmsdk_ahb_to_apb:AHB-APB桥
      • cmsdk_apb_timer:定时器
      • cmsdk_apb_dualtimers:两个32位向下计数器
      • cmsdk_apb_watchdog:看门狗
      • cmsdk_apb_uart:串口
      • cmsdk_apb_test_slave:在APB子系统中测试等待状态和error回应的从设备。

三、移植

3.1 导入文件

        根据第二章的结构分析,将下列文件从Cortex-M0 DesignStart中找到,添加到工程中

  1. cores/cortexm0_designstart_r2p0/logical/cortexm0_integration/verilog/cortexm0ds_logic.v
  2. cores/cortexm0_designstart_r2p0/logical/cortexm0_integration/verilog/CORTEXM0INTEGRATION.v
  3. systems/cortex_m0_mcu/cmsdk_ahb_cs_rom_table.v
  4. systems/cortex_m0_mcu/cmsdk_mcu.v
  5. systems/cortex_m0_mcu/cmsdk_mcu_addr_decode.v
  6. systems/cortex_m0_mcu/cmsdk_mcu_clkctrl.v
  7. systems/cortex_m0_mcu/cmsdk_mcu_defs.v
  8. systems/cortex_m0_mcu/cmsdk_mcu_pin_mux.v
  9. systems/cortex_m0_mcu/cmsdk_mcu_stclkctrl.v
  10. systems/cortex_m0_mcu/cmsdk_mcu_sysctrl.v
  11. systems/cortex_m0_mcu/cmsdk_mcu_system.v
  12. logic/cmsdk_ahb_default_slave/cmsdk_ahb_default_slave.v
  13. logic/cmsdk_ahb_gpio/cmsdk_ahb_gpio.v
  14. logic/cmsdk_ahb_gpio/cmsdk_ahb_to_iop.v
  15. logic/cmsdk_ahb_slave_mux/cmsdk_ahb_slave_mux.v
  16. logic/cmsdk_ahb_to_apb/cmsdk_ahb_to_apb.v
  17. logic/cmsdk_apb_dualtimers/cmsdk_apb_dualtimers.v
  18. logic/cmsdk_apb_dualtimers/cmsdk_apb_dualtimers_defs.v
  19. logic/cmsdk_apb_dualtimers/cmsdk_apb_dualtimers_frc.v
  20. logic/cmsdk_apb_slave_mux/cmsdk_apb_slave_mux.v
  21. logic/cmsdk_apb_subsystem/cmsdk_apb_subsystem.v
  22. logic/cmsdk_apb_subsystem/cmsdk_apb_test_slave.v
  23. logic/cmsdk_apb_timer/cmsdk_apb_timer.v
  24. logic/cmsdk_apb_uart/cmsdk_apb_uart.v
  25. logic/cmsdk_apb_watchdog/cmsdk_apb_watchdog.v
  26. logic/cmsdk_apb_watchdog/cmsdk_apb_watchdog_defs.v
  27. logic/cmsdk_apb_watchdog/cmsdk_apb_watchdog_frc.v
  28. logic/cmsdk_iop_gpio/cmsdk_iop_gpio.v
  29. logic/models/memories/cmsdk_ahb_memory_models_defs.v
  30. logic/models/memories/cmsdk_ahb_ram.v
  31. logic/models/memories/cmsdk_ahb_ram_beh.v
  32. logic/models/memories/cmsdk_ahb_rom.v

        以上共计32个文件,加入到工程中,将cmsdk_mcu.v设置为顶层文件,然后直接进行编译。右键点击cmsdk_mcu->Set As Top。

        控制台会报错误,循环次数不能大于10000,这是由于cmsdk默认设置的RAM和ROM时64KB,而这样建立工程的时候没有使用FPGA的RAM IP核,占用了大量的寄存器和逻辑单元。

3.2 修改RAM和ROM大小

        在cmsdk_mcu.v文件里,找到cmsdk_ahb_rom和cmsdk_ahb_ram两个模块,将参数AW从16修改为8。并将cmsdk_ahb_rom里的filename参数给删除,如果需要烧录映像,可以将hex文件添加,这里暂时删除。

        重新进行编译,这里就已经能够顺利编译完成了。

3.3 Keil读取内核

        在能够顺利编译之后,根据引脚,自行分配SWD引脚,重新编译,并下载到开发板中,连接DAP仿真器,用Keil创建一个ARM CM0的工程,打开创建好的KEIL工程。

        先在小魔法棒中检查是否能读取到ARM内核。如果能够成功读取到IDCODE,并且读取到ARM CoreSight SW-DP,表明内核已经可以工作了。

3.4 激活SWD   

        此时,还不能正常使用调试功能,需要在内核中将调试功能打开。找到cmsdk_mcu_system.v,找到278行附近:

        wire              EDBGRQ;

        在后面添加以下代码:

wire      cdbgpwrupack_wire;
wire      cdbgpwrupreq_wire;
assign    cdbgpwrupack_wire = cdbgpwrupreq_wire;

         然后找到CORTEXM0INTEGRATION模块,POWER MANAGEMENT里的CDBGPWRUPREQ和CDBGPWRUPACK,分别填入cdbgpwrupreq_wire和cdbgpwrupack_wire。

        重新编译,下载。

3.5 Keil进行内存调试

        打开KEIL工程,取消勾选魔法棒->Debug->Load Application at Startup,取消勾选魔法棒->Debug->Settings->Reset after Cornnect,取消勾选魔法棒->Utilities->Update Target before Debugging。

        点击调试。点击工具栏->View->Memory Windows->Memory 1。在内存窗口中,输入地址0x20000000,按下回车键,然后随意修改任意地址,观察是否能成功修改内存的值。如果能够成功修改,说明RAM和ROM是没有问题的。

四、RAM和ROM

4.1 自动RAM和ROM

        ARM官方的代码生成的RAM和ROM不能够太大(笔者能力有限),笔者从网上抄了一份RAM的代码,由于时间久远,忘记出处了,无法标记原作者。


// AHB-Lite Memory Modulemodule EG4_AHBLite_AutoRAM#(parameter MEMWIDTH = 12)               // Size = 4KB(input wire           HSEL,input wire           HCLK,input wire           HRESETn,input wire           HREADY,input wire    [31:0] HADDR,input wire     [1:0] HTRANS,input wire           HWRITE,input wire     [2:0] HSIZE,input wire    [31:0] HWDATA,output wire          HREADYOUT,output reg    [31:0] HRDATA,output wire          HRESP);assign HREADYOUT = 1'b1; // Always readyassign HRESP     = 1'b0;// Memory Arrayreg  [31:0] memory[0:(2**(MEMWIDTH-2)-1)];// Registers to store Adress Phase Signalsreg  [31:0] hwdata_mask;reg         we;reg  [31:0] buf_hwaddr;// Sample the Address Phase   always @(posedge HCLK or negedge HRESETn)beginif(!HRESETn)beginwe <= 1'b0;buf_hwaddr <= 32'h0;endelseif(HREADY)beginwe <= HSEL & HWRITE & HTRANS[1];buf_hwaddr <= HADDR;casez (HSIZE[1:0])2'b1?: hwdata_mask <=  32'hFFFFFFFF;                        // Word write2'b01: hwdata_mask <= (32'h0000FFFF << (16 * HADDR[1]));    // Halfword write2'b00: hwdata_mask <= (32'h000000FF << (8 * HADDR[1:0]));   // Byte writeendcaseendend// Read and Write Memoryalways @ (posedge HCLK)beginif(we) memory[buf_hwaddr[MEMWIDTH:2]] <= (HWDATA & hwdata_mask) | (HRDATA & ~hwdata_mask);HRDATA = memory[HADDR[MEMWIDTH:2]];endendmodule

4.2 IP核生成RAM和ROM

        笔者尝试了自己使用安路TD的IP generate生成一个RAM IP核,然后接入到AHB总线中,代码如下,仅供参考

// AHB-Lite Memory Modulemodule EG4_AHBLite_BRAM
(input wire           HCLK,input wire           HRESETn,input wire           HSEL,input wire           HREADY,input wire    [31:0] HADDR,input wire     [1:0] HTRANS,input wire           HWRITE,input wire     [2:0] HSIZE,input wire    [31:0] HWDATA,output wire          HREADYOUT,output wire   [31:0] HRDATA,output wire          HRESP
);assign HREADYOUT = 1'b1;assign HRESP     = 1'b0;reg	[31:0]	buf_hwaddr;reg			ram_cs;reg	[3:0]	ram_we;wire [31:0]	buf_hraddr;assign buf_hraddr = HADDR>>2;always @(posedge HCLK or negedge HRESETn) beginif (!HRESETn) beginbuf_hwaddr <= 32'd0;ram_cs <= 1'b0;ram_we <= 4'd0;endelse beginbuf_hwaddr <= HADDR>>2;ram_cs <= HSEL & HWRITE & HTRANS[1];if (HWRITE) begin	casez (HSIZE[1:0])2'b1?: ram_we <= 4'b1111;						// Word write2'b01: ram_we <= (4'b0011<< (HADDR[1]<<1));		// Halfword write2'b00: ram_we <= (4'b0001<< HADDR[1:0]);		// Byte writeendcaseendelse beginram_we <= 4'd0;ram_cs <= 1'b0;endendendmcu_ram u_mcu_ram(		.clka		(HCLK),				// clock.cea		(ram_cs),			// clock enable,active High// .rsta		(1'b0),			// reset,active High.addra		(buf_hwaddr),		// address input.dia		(HWDATA),			// data input.wea		(ram_we),			// write byte.clkb		(HCLK),.ceb		(1'b1),// .rstb		(1'b0),			// reset,active High.addrb		(buf_hraddr),		// address input.dob		(HRDATA)			// data output// .oceb		(1'b1) 			// data output register enable);// parameter DATA_WIDTH_A = 32; // parameter ADDR_WIDTH_A = 12;// parameter DATA_DEPTH_A = 4096;// parameter DATA_WIDTH_B = 32;// parameter ADDR_WIDTH_B = 12;// parameter DATA_DEPTH_B = 4096;// parameter REGMODE_A    = "NOREG";// parameter REGMODE_B    = "NOREG";// parameter WRITEMODE_A  = "NORMAL";// parameter WRITEMODE_B  = "NORMAL";// EG_LOGIC_BRAM #( .DATA_WIDTH_A(DATA_WIDTH_A),// 			.DATA_WIDTH_B(DATA_WIDTH_B),// 			.ADDR_WIDTH_A(ADDR_WIDTH_A),// 			.ADDR_WIDTH_B(ADDR_WIDTH_B),// 			.DATA_DEPTH_A(DATA_DEPTH_A),// 			.DATA_DEPTH_B(DATA_DEPTH_B),// 			.BYTE_ENABLE(8),// 			.BYTE_A(4),// 			.BYTE_B(4),// 			.MODE("PDPW"),// 			.REGMODE_A(REGMODE_A),// 			.REGMODE_B(REGMODE_B),// 			.WRITEMODE_A(WRITEMODE_A),// 			.WRITEMODE_B(WRITEMODE_B),// 			.RESETMODE("SYNC"),// 			.IMPLEMENT("9K"),// 			.INIT_FILE("NONE"),// 			.FILL_ALL("NONE"))// 		inst(// 			.dia(HWDATA),// 			.dib({32{1'b0}}),// 			.addra(buf_hwaddr),// 			.addrb(buf_hraddr),// 			.cea(ram_cs),// 			.ceb(1'b1),// 			.ocea(1'b0),// 			.oceb(1'b0),// 			.clka(HCLK),// 			.clkb(HCLK),// 			.wea(1'b0),// 			.bea(ram_we),// 			.web(1'b0),// 			.beb(2'b00),// 			.rsta(1'b0),// 			.rstb(1'b0),// 			.doa(),// 			.dob(HRDATA));endmodule

五、结束

        至此,已经能够跑通M0内核,并且能够下载程序和运行了,关于代码里带有的Uart、TIM定时器等外设,读者可以自行参考ARM官方的案例和手册。

        关于自己写APB、AHB外设,读者可以参考ARM官方给的各种外设,是如何挂到总线上,如何例化,如何读写寄存器、中断等,ARM官方给的示例非常丰富,值得仔细学习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/28701.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32——串口通信 UART

一、基础配置 Universal Asynchronous Receiver Transmitter 异步&#xff0c;串行&#xff0c;全双工 TTL电平 &#xff1a;高电平1 低电平0 帧格式&#xff1a; 起始位1bit 数据位8bit 校验位1bit 终止位1bit NVIC Settings一栏使能接受中断。 之前有设置LCD&#xff0c;…

flink集成tidb cdc

Flink TiDB CDC 详解 1. TiDB CDC 简介 1.1 TiDB CDC 的核心概念 TiDB CDC 是 TiDB 提供的变更数据捕获工具&#xff0c;能够实时捕获 TiDB 集群中的数据变更&#xff08;如 INSERT、UPDATE、DELETE 操作&#xff09;&#xff0c;并将这些变更以事件流的形式输出。TiDB CDC 的…

DeepSeek×博云AIOS:突破算力桎梏,开启AI普惠新纪元

背景 在全球人工智能技术高速迭代的背景下&#xff0c;算力成本高企、异构资源适配复杂、模型部署效率低下等问题&#xff0c;始终是制约企业AI规模化应用的关键。 DeepSeek以创新技术直击产业痛点&#xff0c;而博云先进算力管理平台AIOS的全面适配&#xff0c;则为这一技术…

ArcGIS Pro建库中常用公式的应用与技巧

在当今数字化的时代&#xff0c;地理信息系统&#xff08;GIS&#xff09;在各个领域都发挥着至关重要的作用。 ArcGIS Pro作为一款功能强大的GIS软件&#xff0c;为用户提供了丰富的工具和功能&#xff0c;使得数据处理、地图制作和空间分析变得更加高效和便捷。 本文将为您…

C++入门基础

文章目录 C核心特性详解&#xff08;基础增强版&#xff09;一、第一个C程序&#xff1a;Hello World完整代码解析新手常见问题 二、命名空间&#xff08;详解版&#xff09;1. 为什么需要命名空间&#xff1f;2. 命名空间使用场景3. 嵌套命名空间4. 匿名命名空间 三、输入输出…

探秘基带算法:从原理到5G时代的通信变革【三】Turbo 编解码

文章目录 2.2 Turbo 编解码2.2.1 基本概念与系统构成2.2.2 编码过程分步解析交织器递归系统卷积编码器复接器总结 2.2.3 译码算法分类与原理Turbo码的强大主要来源于其解码器理论基础解码过程详解交织与解交织译码算法总结 2.2.4 Turbo码的应用场景无线通信卫星通信深空通信 2.…

一键无损放大视频,让老旧画面重焕新生!

打工人们你们好&#xff01;这里是摸鱼 特供版~ 嘿&#xff0c;朋友们&#xff01;在数字时代&#xff0c;视频已经成为我们生活中不可或缺的一部分。无论是珍贵的家庭录像&#xff0c;还是老旧的影视素材&#xff0c;我们都希望能以高清画质重温那些美好瞬间。但很多时候&…

build gcc

1&#xff0c;下载源码 wget https://gcc.gnu.org/pub/gcc/infrastructure/mpfr-4.1.0.tar.bz2 wget https://gcc.gnu.org/pub/gcc/infrastructure/gmp-6.1.0.tar.bz2 wget https://gcc.gnu.org/pub/gcc/infrastructure/mpc-1.2.1.tar.gz git clone --mirror https://github…

《用Python+PyGame开发双人生存游戏!源码解析+完整开发思路分享》

导语​ "你是否想过用Python开发一款可玩性高的双人合作游戏&#xff1f;本文将分享如何从零开始实现一款类《吸血鬼幸存者》的生存射击游戏&#xff01;包含完整源码解析、角色系统设计、敌人AI逻辑等核心技术点&#xff0c;文末提供完整代码包下载&#xff01;" 哈…

AutoGen学习笔记系列(一)Tutorial - Model

这个系列文章记录了学习微软 AutoGen 的过程&#xff0c;与 smolagents 学习笔记系列一样&#xff0c;仍然以官方教程自己的理解为主线&#xff0c;中间可能穿插几个番外支线的形式写博客。 【注意】&#xff1a;在阅读这篇文章之前需要确保已经按照其 Installation 小节完成必…

探秘基带算法:从原理到5G时代的通信变革【八】QAM 调制 / 解调

文章目录 2.7 QAM 调制 / 解调2.7.1 概述2.7.2 星座图星座图的结构与性能发射端的信息编码与接收端的解码差分编码的分类与实现差分编码的模4格雷加法器公式16QAM星座图与映射关系 2.7.3 信号表达式正交振幅调制的基本原理与系统分析相位误差对QAM性能的影响多电平正交振幅调制…

本地YARN集群部署

请先完成HDFS的前置部署&#xff0c;部署方式可查看:本地部署HDFS集群https://blog.csdn.net/m0_73641796/article/details/145998092?spm1001.2014.3001.5502 部署说明 组件配置文件启动进程备注Hadoop HDFS需修改 需启动: NameNode作为主节点 DataNode作为从节点 Secondary…

vivado 充分利用 IP 核

充分利用 IP 核 使用预先验证的 IP 核能够大幅减少设计和验证工作量&#xff0c;从而加速产品上市进程。如需了解更多有利用 IP 的信息&#xff0c;请参 阅以下资源&#xff1a; • 《 Vivado Design Suite 用户指南&#xff1a;采用 IP 进行设计》 (UG896) [ 参照 1…

Python-07PDF转Word

2025-03-04-PDF转Word DeepSeek等大模型从来都不是简单的写一个静态博客这么肤浅&#xff08;太多博主都只讲这个内容了&#xff09;借助全网大神的奇思妙想&#xff0c;拓展我狭隘的思维边界。 文章目录 2025-03-04-PDF转Word [toc]1-参考网址2-学习要点3-核心逻辑4-核心代码 …

android11使用gpio口控制led状态灯

目录 一、简介 二、解决方法 A、底层驱动 B、上层调用 C、验证 一、简介 1、需求&#xff1a;这里是用2个gpio口来控制LED灯&#xff0c;开机时默认亮蓝灯&#xff0c;按开机键&#xff0c;休眠亮红灯&#xff0c;唤醒亮蓝灯。 原理图&#xff1a; 这里由于主板上电阻R63…

el-input 设置类型为number时,输入中文后光标会上移,并且会出现上下箭头

光标上移 设置 el-input 的 typenumber后&#xff0c;只能输入数字&#xff0c;输入中文后会自动清空&#xff0c;但是会出现一个问题&#xff1a;【光标会上移&#xff0c;如下图】 解决方法&#xff1a;修改样式 注意&#xff1a;需要使用样式穿透 :deep( ) /*解决el-in…

el-table一格两行;概率;find

样式&#xff1a; 根据概率表头关键代码&#xff1a;rateRanges&#xff1b; scope.row.targetHitTable.find((target:any) > target.targetHitRate > range.min && target.targetHitRate < range.max)!.targetHitNum &#xff08;1&#xff09;!.是TypeScri…

CSS定位详解上

1. 相对定位 1.1 如何设置相对定位&#xff1f; 给元素设置 position:relative 即可实现相对定位。 可以使用 left 、 right 、 top 、 bottom 四个属性调整位置。 1.2 相对定位的参考点在哪里&#xff1f; 相对自己原来的位置 1.3 相对定位的特点&#xff1…

二、Java-封装playwright UI自动化(根据官网执行步骤,首先封装BrowserFactory枚举类及BrowserManager)

前言 查看playwright官网&#xff0c;api文档了解到&#xff0c;playwright的基本步骤&#xff1a; 1、实例化一个playwright 2、启动一个浏览器类型 3、打开一个页面 所以&#xff0c;在封装时需要有一个浏览器工厂类&#xff0c;定义不同的浏览器类型&#xff0c;在配置文…

【问题解决】Jenkins使用File的exists()方法判断文件存在,一直提示不存在的问题

小剧场 最近为了给项目组提供一个能给Java程序替换前端、后端的增量的流水线&#xff0c;继续写上了声明式流水线。 替换增量是根据JSON配置文件去增量目录里去取再替换到对应位置的&#xff0c;替换前需要判断增量文件是否存在。 判断文件是否存在&#xff1f;作为一个老Ja…