3. 开发环境搭建
拿到一份RTL代码,很多人第一反应是直接打开顶层文件,然后被密密麻麻的连线吓退。我刚开始看蜂鸟E203的时候也是这样,后来发现一个窍门——先看目录结构,再看模块划分。说白了,代码的组织方式就是设计者的思维导图。
蜂鸟E203的RTL代码,核心就三个大模块:Core(处理器核心)、Mem(存储子系统)、Periph(外设)。这三个模块各司其职,互相配合。今天我就带你把这三大块拆开揉碎,看看里面到底藏着什么。
一句话总结:Core负责算,Mem负责存,Periph负责跟外界打交道。三者通过总线连在一起,构成了一个完整的SoC。
3.1 顶层目录结构
我们先看看蜂鸟E203的RTL目录长什么样。你打开e203_rtl目录,会看到下面这些子目录:
e203_rtl/
├── core/ # 处理器核心
├── mem/ # 存储子系统
├── periph/ # 外设模块
├── soc/ # 顶层SoC集成
├── debug/ # 调试模块
└── lib/ # 通用库文件
嗯,这里要注意,soc目录是顶层集成,它把core、mem、periph三个大模块粘在一起。debug目录放的是JTAG调试相关的逻辑,lib目录则是一些通用的寄存器文件、FIFO、同步器之类的库单元。
我个人习惯,拿到一个新项目的RTL,第一件事就是看soc目录下的顶层文件。它会告诉你整个芯片的骨架是什么样子的。
3.2 Core模块:处理器的“大脑”
Core模块是蜂鸟E203的心脏。它实现了RISC-V RV32IMAC指令集架构。你想想看,所有程序的执行、数据的计算、控制流的跳转,全在这里完成。
打开core目录,你会看到这些关键文件:
| 文件名 | 作用 |
|---|---|
e203_core.v |
Core顶层,实例化所有子模块 |
e203_ifu.v |
指令取指单元(Instruction Fetch Unit) |
e203_idu.v |
指令译码单元(Instruction Decode Unit) |
e203_exu.v |
执行单元(Execution Unit),包含ALU、乘法器、除法器 |
e203_lsu.v |
加载存储单元(Load Store Unit),处理内存访问 |
e203_csr.v |
控制状态寄存器模块(CSR) |
我在项目中遇到过一个问题:指令取指和数据访问冲突了,导致CPU卡死。后来查了半天,发现是IFU和LSU在争抢同一个内存端口。蜂鸟E203的设计里,IFU和LSU是分开的,各走各的路,这就避免了这种冲突。说白了,这就是经典的哈佛架构思想——指令和数据走不同的通道。
小技巧:如果你想快速了解Core的流水线结构,直接看e203_core.v里的模块实例化顺序。从上到下,就是指令从取指到写回的全流程。
3.3 Mem模块:存储子系统
Mem模块负责管理所有的存储资源。蜂鸟E203的存储架构很有意思,它把ITCM(指令紧耦合存储器)和DTCM(数据紧耦合存储器)直接挂在Core旁边,访问延迟极低。
关键文件一览:
| 文件名 | 作用 |
|---|---|
e203_mem.v |
存储子系统顶层 |
e203_itcm.v |
指令紧耦合存储器控制器 |
e203_dtcm.v |
数据紧耦合存储器控制器 |
e203_biu.v |
总线接口单元(Bus Interface Unit),连接系统总线 |
为什么要有ITCM和DTCM?你想想看,如果每次取指令都要走系统总线,那延迟得多大。蜂鸟E203把最常用的指令和数据放在TCM里,Core可以直接访问,不需要经过总线仲裁。我在做性能调优的时候,把关键代码段和数据段都放在TCM里,性能提升非常明显。
注意:TCM的大小是有限的。蜂鸟E203默认的ITCM是64KB,DTCM是64KB。如果你把程序塞得太大,超出TCM范围,就会触发总线访问,性能会急剧下降。我曾经踩过这个坑,一个循环体太大,放不进ITCM,结果跑起来慢了好几倍。
3.4 Periph模块:外设接口
Periph模块是处理器跟外部世界打交道的桥梁。蜂鸟E203的外设不算多,但够用。主要包括:
- GPIO:通用输入输出,控制LED、按键之类的东西
- UART:串口通信,调试和打印信息全靠它
- SPI:连接Flash、传感器等SPI设备
- Timer:定时器,用于计时和产生中断
- PLIC:平台级中断控制器,管理所有外部中断
关键文件:
| 文件名 | 作用 |
|---|---|
e203_periph.v |
外设模块顶层 |
e203_gpio.v |
GPIO控制器 |
e203_uart.v |
UART控制器 |
e203_spi.v |
SPI控制器 |
e203_timer.v |
定时器 |
e203_plic.v |
中断控制器 |
外设模块的设计有一个共同点:它们都通过内存映射的方式跟Core交互。也就是说,Core读写某个外设,就像读写内存一样简单。每个外设被分配了一段地址空间,Core往那个地址写数据,外设就能收到指令。
3.5 三大模块的互联关系
这三个模块不是孤立的,它们通过总线连在一起。蜂鸟E203使用了一种叫做ICB(Internal Chip Bus)的内部总线协议。ICB是蜂鸟E203自己定义的一套简单总线协议,说白了就是一套握手规则。
下面这张图展示了三大模块之间的连接关系:
从这张图可以看得很清楚:Core是中心,Mem和Periph是它的左右手。Core通过ICB总线访问Mem和Periph。但这里有个细节——ITCM和DTCM是直连Core的,不走总线仲裁。这意味着Core访问TCM的速度非常快,一个时钟周期就能完成。
而访问外设呢?Core需要先通过BIU(总线接口单元)桥接到系统总线,然后再访问外设。这个路径就长了,延迟也大了。所以,如果你对性能有要求,尽量把数据放在TCM里,而不是外设的寄存器里。
3.6 关键文件与目录作用总结
最后,我把所有关键目录和文件的作用整理成一个表格,方便你查阅:
| 目录/文件 | 作用 | 备注 |
|---|---|---|
core/ |
处理器核心,包含IFU、IDU、EXU、LSU、CSR | 性能调优的重点区域 |
mem/ |
存储子系统,包含ITCM、DTCM、BIU | TCM大小可配置 |
periph/ |
外设模块,包含GPIO、UART、SPI、Timer、PLIC | 根据需求裁剪 |
soc/ |
顶层SoC集成,连接Core、Mem、Periph | 从这里开始看代码 |
debug/ |
JTAG调试模块 | 调试时用到 |
lib/ |
通用库单元,如寄存器、FIFO、同步器 | 可复用的基础模块 |
我的建议:刚开始接触蜂鸟E203的RTL代码,不要试图一口气看完所有文件。先看soc目录下的顶层文件,了解整体架构。然后看core目录下的e203_core.v,理解流水线结构。最后再深入到各个子模块。这样循序渐进,效率最高。
好了,这一章的内容就到这里。记住三大模块的划分和各自的作用,后面我们做配置和性能调优的时候,会反复用到这些知识。