实验 4:内存串口实验
串口是实现计算机与外接设备通信最为简单的接口,在实际的计算机系统中,它经常作为一个总线上的外设设备出现。本实验由同学实现 Wishbone 总线 Master 模块,通过本实验中给出的 UART 控制器,实现对 ThinPAD 教学计算机上串口的访问;同时,结合实验 3 中设计的 SRAM 控制器,实现 SRAM 与 UART 之间数据的双向传输,为后续的 CPU 设计实验做好准备。
模板文件
本实验的顶层模块模板:thinpad_top.srcs/sources_1/new/lab5/lab5_top.sv
Wishbone 非对齐访问
关于在 Wishbone 总线上进行非对齐访问的情况,请 严格 按照 Wisbone Master 实现#非对齐访问中说明的方式处理。即在访问 0x10000005
这个地址时, wb_sel 应使用 4'b0010
。在群内的相关讨论以及实验前小测题有误。如已经完成实验 4, 不需要 修改自己通过测试的实现。
实验目的
- 熟悉 ThinPAD-Cloud 教学计算机串行接口的配置及与总线的连接方式;
- 掌握 Wishbone Master 的时序及模块设计方法;
- 理解总线数据传输的基本原理;
- 熟悉通过总线访问 UART 等外设的方法。
实验环境
- 硬件环境:PC 计算机,Windows 10 或者 Linux 操作系统;ThinPAD-Cloud 远程实验平台;
- 软件环境:FPGA 开发工具软件 Vivado;ThinPAD-Cloud 远程实验平台提供的串口调试工具;
- 基础模块:
- 实验 3 中编写的 Wishbone SRAM 控制器;
wb_mux_3
1M3S 总线仲裁模块;- Wishbone UART 控制器
uart_controller
(教学团队给出,已经包含在工程模板内)。
实验内容
使用教学计算机上的 FPGA 芯片,编写代码,通过 Wishbone 协议及给出的 Wishbone UART 控制器、之前编写的 Wishbone SRAM 控制器,同时完成对教学机 UART 和 SRAM 的访问。实现和外部设备(实验中为 ThinPAD-Cloud 平台)的通信。要求分别实现如下功能:
- 将拨码开关设置为起始地址 Addr,该地址是 Wishbone 总线的地址,如
0x8000_1000
表示 BaseRAM 这一内存区域的第 0x1000 字节。 - 单击复位按钮。
- 使用云平台向 FPGA 的串口发送 10 个字节的随机数,FPGA 将随机数存储到从 Addr 开始的连续 10 个 word 上(存储进最低 8 位,高 24 位不使用),即每次读写操作地址应当 +4。
- FPGA 将上述 10 个随机数发送回串口,云平台从 FPGA 的串口接收 10 个字节。
- 程序读取 BaseRAM 中对应位置的数据,并将 SRAM 中数据、串口接收到的数据与初始随机数进行对比,对比时只考虑 SRAM 数据的最低 8 位。
同学需要在顶层模块中实现 Wishbone Master 状态机,根据拨码开关的输入,生成总线上的请求,从而实现实验的要求。
原理图
实验步骤
本实验的操作比较复杂,首先需要在 ThinPAD-Cloud 云平台上正确选择直连串口,并正确配置串口的参数(波特率默认为 115200)。然后,在编写 Verilog 代码时,要正确理解 UART 的工作原理,了解 UART 控制器内部各个寄存器之间的关系,设计好状态机的各个状态。在此基础上,设计好实现的代码,再将代码下载到 FPGA 中,进行调试。
- 从复位中恢复的时候,把拨码开关指示的地址记录下来,记作
addr
,保证addr
对齐到四字节的边界。 -
读串口:用 Verilog 语言编写从串口读取数据的代码。
- 读串口需要循环读取串口控制器的状态寄存器(地址是
0x1000_0005
),当它的状态显示可以读入新的数据的时候,再读取串口控制器的数据寄存器(地址是0x1000_0000
)。实际上就是用硬件状态机实现了实验一中的READ_SERIAL
函数。 - 建议设计状态:
READ_WAIT_ACTION
(正在读取状态寄存器)、READ_WAIT_CHECK
(读取了状态寄存器当前的取值,判断是否可以读取新的值)、READ_DATA_ACTION
(正在读取数据寄存器)、READ_DATA_DONE
(完成读取数据寄存器,进入下面的操作)
循环读取状态寄存器,直到可以读取新数据的一种可能的波形:
其中
R_W_C
表示READ_WAIT_CHECK
,波形中不断读取0x10000005
,直到可以读取数据,才去读取0x100000000
。注意ADR_O
SEL_O
DAT_I
在非对齐访问时的写法。之后写串口也是类似的。 - 读串口需要循环读取串口控制器的状态寄存器(地址是
-
写内存:把从串口读取的数据写入到内存中。
-
每次从串口读取一个字节的数据,就要向内存写入一个字节的数据(仅存储最低 8 位),第 i 次写入的 Wishbone 操作地址是
addr+4*i
,也就是每次写入的时候地址增加 4 -
建议设计状态:
WRITE_SRAM_ACTION
(正在写入 SRAM)、WRITE_SRAM_DONE
(写入 SRAM 完成,进入下面的操作) -
写串口:再把从串口读取的数据写回到串口。
-
写串口需要循环读取串口控制器的状态寄存器(地址是
0x1000_0005
),当它的状态显示可以写入新的数据的时候,再写入串口控制器的数据寄存器(地址是0x1000_0000
)。实际上就是用硬件状态机实现了实验一中 WRITE_SERIAL 函数。 -
建议设计状态:
WRITE_WAIT_ACTION
(正在读取状态寄存器)、WRITE_WAIT_CHECK
(读取了状态寄存器当前的取值,判断是否可以写入新的值)、WRITE_DATA_ACTION
(正在写入数据寄存器)、WRITE_DATA_DONE
(完成写入数据寄存器,进入下面的操作) -
循环以上过程,直到完成了十次。
实验提示
- 本实验中使用的是 ThinPAD 教学计算机的 直连串口,即
uart_txd
和uart_rxd
两个信号,连接到 Wishbone 串口控制器上。注意不要与共享总线(CPLD 串口)相混淆。实验时,请将uart_rdn
和uart_wrn
两个 CPLD 串口的控制线置为 1,避免与 SRAM 产生冲突。 - Wishbone 串口控制器模块需要正确指定时钟的频率和串口波特率,实验模板中默认置为了 10MHz,波特率为 115200。如果需要修改系统时钟的频率,需要修改对应参数的数值。
思考题
- 阅读 Wishbone UART 控制器的代码,体会 MMIO 寄存器的概念。映射到地址空间上的“内存”的内容一定是只受 Master 端控制的吗?如何将数码管和拨码开关也映射到地址空间上?
实验报告要求
-
给出你的状态机设计,并简要解释每个状态的功能。
-
进行仿真,给出仿真波形,初步验证设计的正确性。
-
上板进行实验,给出实验过程截图,验证设计的正确性。注意不是 OJ 通过截图。
-
回答思考题。