为 Wujian100 添加外设

前言

本文是为数电课编写的实验指导,介绍了如何为 Wujian100 添加一个简单的外设。本文主要参考了视频,添加了一个三色灯控制器。

实验目的

  1. 熟悉基本的软硬件开发流程。
  2. 学习 Block Design,给 wujian100 SoC 添加外设。

实验器材

Basys3, Vivado 2022.2

实验原理

wujian100 SoC 概述

Wujian100 是阿里平头哥自主研发的 RISC-V SOC。其系统结构层次如下图所示。(其中有删除线的代表在移植过程中被裁剪的模块,虚线框的代表我们将会在实验一二中添加的模块)

Wujian100 SoC 基于玄铁 E902,是一块极低功耗、极低成本的嵌入式 CPU 核,非常适用于边缘智能场景。E902 采用 RISC-V RV32E[M]C 指令集架构,并支持部分平头哥自研拓展指令。

Wujian100 SoC 采用哈佛架构,拥有一块 64KB 的指令 SRAM 以及三块大小均为 64KB 的数据 SRAM。如果软件程序不是很大,在实现时我们可以通过删去部分 DRAM 来节省 FPGA 资源。

Wujian100 SoC 的系统总线支持 AMBA3.0 AHB-Lite 协议。AHB 总线协议主要用于高性能、高时钟频率的系统结构中。E902 实现了 AHB-Lite 协议中的部分内容。系统总线连接了 CPU,DMA 以及 SRAM 等核心部件,还连接了很多没有内部逻辑的 Dummy 模块。SoC 预留了这些 Dummy 模块的接口以及地址,方便用户自己设计支持 AHB 协议的模块替换 Dummy 以实现功能拓展。由各个 Dummy 模块名可知,用户可以设计主设备、从设备以及指令、数据存储器,连接到系统总线上。

系统总线通过同步桥连接到低速 AHB 总线上,后者再转接到低速 APB 总线并连接各个 APB 外设上:脉宽调制器(PWM)、定时器(TIM)、串行接口模块(USI)等。其中 USI 兼容支持 USART,SPI 以及 I2C 三种串行总线协议。在 SoC 文档 doc\wujian100_open Userguide v1.0.docx 中我们可以了解到 USI 的复用方式和对应信号名。此外,在低速总线上也预留了很多 Dummy 模块以供拓展。

wujian100 soc 的源码可以通过以下方法获取:

git clone https://github.com/T-head-Semi/wujian100_open

为了方便同学们实验,我们已经帮大家完成了 wujian100 到 Basys3 的移植,并且裁剪了部分模块以适应 Basys3 的硬件资源。同学们可以通过北大网盘链接下载得到工程文件,工程结构详见 readme。

我们主要完成了以下工作,需要同学们注意:

  1. 删除了 DMA 模块。删除了第三个 DATA SRAM,其地址空间为:0x2002_0000~0x2002_FFFF。因此,修改了 CDK 项目链接脚本 sdk\board\wujian100_open_evb\gcc_csky.ld 的地址空间。
  2. 修改了约束文件:映射了 GPIO,USART,JTAG,RST_N 等信号。请仔细阅读约束文件。其中系统的低有效复位键映射到了拨码开关 SW15 上,SW15 断开时系统复位。
  3. 添加了 pll 分频器,将板载 100MHz 时钟分频为 20MHz,以适用于 wujian100 SoC。
  4. 编写了 tcl 脚本,用于忽略综合和比特流生成时的警告。

外设添加

Wujian100 SoC 为我们预留了很多 dummy 模块,观察它们的源码可以看到它们只有基础的 AHB-Lite 总线端口定义,没有内部逻辑。我们可以设计自己的模块,再通过替换这些 dummy 来接入 SoC。

在本实验中,我们将借助 Vivado 的 Block Design 工具设计一个三色灯控制器。

三色灯及其电路图如下所示:

当 R、G、B 引脚为高电平(3.3V-5V)时,三色灯发出对应颜色的灯光。

我们要设计的三色灯控制器结构如下图所示:

三色灯控制器主要分为三个模块:AHB-Lite to AXI Bridge,AXI Interconnect 以及 MYIO。

  • MYIO:我们将在 Vivido 中创建的三色灯驱动 IP,采用 AXI-Lite 协议,受总线控制输出 32 位的信号 myio。由于三色灯只需要 3bits 信号控制,因此实现时我们只使用输出信号的低三位。
  • AHB-Lite to AXI Bridge:wujian100 SoC 的系统总线采用 AHB-Lite 协议,而我们创建的 IP MYIO 是 AXI-Lite 总线,因此我们需要转接桥来实现总线协议的转换。AHB-Lite to AXI Bridge 能将 AHB-Lite 转换为 AXI。
  • AXI Interconnect:能够将 AXI 协议进一步转换为 AXI-Lite,最终连接到 MYIO 上。

调试原理

Wujian100 SoC 支持平头哥自定义的两线调试接口协议,通过两线接口与调试器 CKLink 通信。调试器通过 USB 与 PC 机相连,并与 Debug Server 通信。最后,借助平头哥的集成开发环境 CDK,我们可以实现对 wujian100 的调试。

调试时,首先我们将 CKLink 的 TCKTMSGND 连接至 Basys3 映射好的两线调试接口以及 GND 上,连接 CKLink 至 PC。在 CDK 中,默认设置下 Debug Server 即可识别到 CPU E902。在编译好程序后,我们就可以利用调试模式全速运行程序或者进行调试。

最后,Basys3 的管脚映射图可以参阅附录图。

实验步骤

移植运行wujian100

进入 Vivado 工程目录 wujian100_basys3_base\,解压打开工程。

综合、实现、生成比特流。

为提高运行速度,可以在 tcl console 中输入以下命令以多线程运行。$max_threads 是你电脑支持的最高线程数。

set_param general.maxThreads $max_threads

下载比特流到basys3上。

在 IMPLEMENTATION -> Open Implemented Design -> Report Utilization 中可以看到详细的资源使用情况:

测试 GPIO

连接 CKLink 的 TCKTMSGND 至 basys3。basys3 的对应 pin 请参阅约束文件。

在本例中,PAD_JTAG_TCLK 连接 J1,即 Pmod JA1;PAD_JTAG_TMS 连接 L2,即 Pmod JA2。连线结果如下图:

gpio cdk 工程位于 sdk\projects\Labs\Lab1\gpio,打开项目文件 CDK\wujian100_open-gpio.cdkproj,编译。

打开 Project Settings -> Debug -> Connector Configurations -> Use ICE Settings,保持默认参数如下:

点击右侧 Connected Debug Target -> Update,出现如下信息表示 CKLink 成功识别到了 wujian100 的 CPU E902M:

Running Debug Server, auto to check the target at first...
T-HEAD: CKLink_Lite_V2, App_ver 2.36, Bit_ver null, Clock 2526.316KHz,
       2-wire, With DDC, Cache Flush On, SN CKLink_Lite_V2-0307F39794.
+--  Debug Arch is CKHAD.  --+
+--  CPU 0  --+
T-HEAD Xuan Tie CPU Info:
    WORD[0]: 0x0804000c
    WORD[1]: 0x10000000
    WORD[2]: 0x24204038
    MISA   : 0x40001014
Target Chip Info:
    CPU Type is E902M, Endian=Little, ISA Patch: 0x0, Revision: 0x0.
    HWBKPT number is 5, HWWP number is 2.
    MISA: (RV32MCE, Imp M-mode)

GDB connection command for CPUs(CPU0):
    target remote 172.29.64.1:1025
    target remote 192.168.1.5:1025

否则,请排查以下问题:

  1. bitstream 下载是否正确。
  2. CKLink 连线是否正确。
  3. 是否正确安装了 CKLink 的驱动,连接上后在设备管理器中能否找到 CKLink。
  4. 作为复位键的拨码开关 SW15 是否处于闭合状态。
  5. 是否打开了多个 CDK 工程的 Debug Server。

编译成功,且 CKLink 连接成功后,打开调式模式,点击运行,即可运行程序。

可以观察到 led 灯组正在展示一个二进制累加器:

测试 USART

仔细阅读 SoC 文档了解 USI 的复用方式和对应信号名,并在约束文件查看已经映射好的对应 basys3 pin。

在本例中,PAD_USI0_SCLKRXD,映射到 A14,即 Pmod JB1;PAD_USI0_SD0TXD,映射到 A16,即 Pmod JB2。

USART 的 CDK 项目位于 sdk\projects\Labs\Lab1\usart,打开项目文件并编译。

提前在 pc 上安装好 USB 转 TTL 模块(如 CH340)的驱动程序,连接模块的 GNDTXDRXD 到 basys3 对应 pin。打开 pc 的串口调试程序,初始化波特率 115200,8N1。CDK 利用调试模式全速运行程序,即可进行串口测试。

为 wujian100 添加外设

我们将在 Vivado 中通过创建 block design 来为 SoC 添加外设——三色灯控制器,替代 main_dummy_top0

首先我们点击左侧:IP INTEGRATOR->Create Block Design,命名为 ahb_axi。

添加 AHB-Lite 转 AXI 桥

我们需要将 AXI-Lite 的 MYIO 与 AHB-Lite 系统总线桥接起来。

先添加 AHB-Lite 转 AXI 桥。右键 Add IP,搜索并添加 AHB-Lite to AXI Bridge。选中新加入的 IP,点击上方工具栏的 Make External 或直接按下 Ctrl+T,增加外部接口。

创建 IP

点击 Vivado 顶部 tools->create and package new ip->Create AXI4 Peripheral,命名为 myio。设置保持如下默认即可:

在 IP Catalog 中找到新建的 IP,右键点击 Edit in ip package。修改 module hdl 代码:myio_v1_0_S00_AXI.v。观察代码可知,CPU 能通过总线读写 slv_reg0/1/2/3。因此:

我们在用户接口定义处添加:

        // Users to add ports here
        output [31:0] myio,
        // User ports ends

在最后的用户逻辑中添加:

    // Add user logic here
    assign myio=slv_reg0;
    // User logic ends

这样,我们将第一个 slave 寄存器的输出连接到 myio 上,再取 myio 的任意3个口(如低3位)输出到三色灯上。这样就能通过软件让 cpu 控制三色灯了。

再修改顶层代码:myio_v1_0.v

添加接口:

output [31:0] myio,

再在模块 myio_v1_0_S00_AXI 的实例化中添加接口:

myio_v1_0_S00_AXI_inst (
        .myio (myio)
        ...
        );

最后,回到 Vivado Package IP 中,一步步完成左侧的 Packaging Steps,最终 Re-Package IP 完成我们 IP 的创建和打包。

互联

打包后就可以在 Block Design 中添加刚刚创建的 IP 了。

由于我们创建的 IP myio 使用的是轻量级 AXI 总线,因此还需要加入 AXI Interconnect。加入后右键 Customize IP,改为输入输出各1个接口。

接着,Run connection automation。为简化工程,删掉自动生成的复位模块,直接将三个模块的复位端口相连,并连接到 s_ahb_hresetn_0 上,后者最后将和 soc 中 AHB 总线相连。

为 myio Make External,引出 myio[31:0]

在 Address Editor 中修改 myio 的地址。我们要将它分配到 main_dummy_top0 的位置上,因此地址范围为:0x4001_0000~0x4001_FFFF

最后,在 Diagram 上方工具栏中点击 Validate Design,完成设计。最终的结构应和原理中的相同。

系统整合

完成 Block Design 后,我们需要将 ahb_axi 整合进 SoC 中。

在 Source->Design Sources 中找到我们设计的 ahb_axi。右键 Generate Output Product,接着再 Create HDL Wrapper。打开源码 ahb_axi_wrapper.v 可以看到,ports 的最后三个就是我们的 myio,时钟和复位,其余的都是 AHB-Lite 的。

在 Sources 中新建一个 myio_top.v,作为顶层模块用来替代 main_dummy_top0。后者是模块 ahb_dummy 的实例化。

因此首先,我们定义 myio_top 的输入输出接口和 ahb_dummy 一致。

接着,我们再实例化我们的模块 ahb_axi_wrapper。将它的接口与 myio_top 的接口匹配相连。注意以下几个问题:

  1. 将同一信号的 port 相连。wrapper 中的端口名基本上只是多了开头的 AHB_INTERFACE_0_,除了以下几个 port。
  2. hreadyahb_axi_wrapper 里有 hready_inhready_out。但是 ahb_dummy 只有 hready。处理方法是将 hready_outhready 直接相连,hready_in 则:
   wire hready_in;
   assign hready_in=hready;

原因请自行查阅 wujian100 和 Xilinx 手册。

  1. ahb_axi_wrapper 多了一个 hburst,直接加到 myio_top 作为 input。事实上 dummy0 的顶层模块是有这根线的。
   input  hburst; 
   wire [2:0] hburst; 
  1. hresphresp 是 2bits 信号,而 ahb_axi_wrapper 中的 AHB_INTERFACE_0_hresp 只需要 hresp 最低位,处理方法:
   wire [1:0] hresp;
   assign hresp[1]=1'b0;
   ahb_axi_wrapper  u_ahb_axi_wrapper (
   ...
   .AHB_INTERFACE_0_hresp       ( hresp[0]       ),
   ...
   );
  1. myio,引为 myio_top 的 output port。

完成 myio_top.v 后,我们到 ahb_matrix_top.v 中替代 x_main_dummy_top0。注意 hburstmyio

myio_top  x_main_dummy_top0 (  //ahb_dummy_top
    ...
    .hburst                  (hmain0_dummy0_s7_hburst),
    .myio                    (myio)
};

将模块的输出 myio 一直引到系统顶层:wujian100_open_fpga_top.v。注意要在每层同时添加 port、wire 和实例化的连线。

最后,在约束文件中添加:

set_property -dict {PACKAGE_PIN M18 IOSTANDARD LVCMOS33 } [get_ports { myio[0] }]; #R
set_property -dict {PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { myio[1] }]; #G
set_property -dict {PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { myio[2] }]; #B

映射到了 Basys3 JC 的三个口。

综合实现生成比特流,下载到 Basys3 上。

测试外设

连接三色灯到 Basys3 JC 对应 pin。

在本例中,R 对应 M18,即 Pmod JC2G 对应 N17,即 Pmod JC3B 对应 P18,即 Pmod JC4

测试三色灯的 CDK 项目位于 sdk\projects\Labs\Lab1\myio,编译,调试模式运行。可以观察到三色灯的颜色变化:

附录

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇