Menu Close

UART波特率设计与控制寄存器

当完成所有uart功能后, 有时,需要将uart模块连接到这个系统中去。 这时,就需要使用寄存器接口来配置uart的不同工作模式。 比如波特率,奇偶校验, 停止位等等信息。这些信息可能在不同的应用场景中动态更改。在这种情况下, 就不能在使用parameter 参数,需要使用模块端口进行动态配置。在cpu设计中,往往使用总线与各个外设进行连接,比如axi 总线,RISCV 的RIB总线,以及自主设计的其他总线等等。不论使用何种总线,在总线中都有data, address,read,write,等信号。本文将已自主设计总线方式,对uart 模块进行设计。

 

1 系统设计框架

UART波特率设计与控制寄存器

图1

如图1 所示:

1)将PLL 模块从uart module 中移出,放到顶层模块中

2)将parameter更改为模块端口

3)增加uart 寄存器模块,用来连接系统总线和寄存器接口(uart_reg_if.v)

4)增加测试cpu模块,用来验证寄存器相关的读写操作(cpu_test_if.v)

图2

图2中显示各个模块之间详细连接图。

2 uart 模块

uart 模块在之前的文章中都有介绍,在本文中只对接口做了更改。 将parameter 转变为端口输入信号。

 

3 uart_reg_if 模块

uart_reg_if 模块将接收cpu总线发过来的命令,同时解析cpu命令,确定寄存器地址,读写操作,以及读写的数据。目前在这个模块中设计了2个寄存器,用户可以根据需求,继续增加寄存器。

地址 寄存器名称 注释
32’he000_0000 UART_CTRL_REG uart 模块配置寄存器
32’he000_0004 UART_BAUD_REG uart模块波特率设计寄存器
  • UART_CTRL_REG
x check_sum x parity_type parity stop_bit
bit31-bit5 bit4 bit3 bit2 bit1 bit0
no used 0 => no check sum

1 => enable check sum

no used 0 = > even parity

1=> odd parity

0 => no parity

1 => has parity

0 => 1 stop bit

1 => 2 stop bit

  • UART_BAUD_REG
baud tick count
bit 31 – 0
default: 625

baud tick count = 72_000_000/baud_rate:

for example:

625 = 72_000_000/ 115200

3750 = 72_000_000/ 19200

7500 = 72_000_000/9600

…….

 

uart_reg_if.v 代码:


 

端口介绍:

input  sys_clk,                          // 系统时钟
input   [31:0] cpu_addr,        // cpu 地址总线
input   [3:0] cpu_wr,              // 4bit cpu 写信号, 适用于32bit 数据总线,每一个bit对应一个数据byte
input   cpu_rd,                         // cpu 读信号
input   [31:0] cpu_din,           // cpu 写数据到外设
output [31:0] cpu_dout,        // cpu 从外设中读取数据

output [31:0] ctrl_reg,           // uart 控制寄存器
output [31:0] baud_reg,        // 波特率计数器

cpu 写 外设寄存器:

always @ (posedge sys_clk or posedge rst)
if(rst) baud_reg_r <= TX_DIV_COE;
else if(cpu_addr == UART_BAUD_REG)
begin
if(cpu_wr[0]) baud_reg_r[07:00] <= cpu_din[07:00];
if(cpu_wr[1]) baud_reg_r[15:08] <= cpu_din[15:08];
if(cpu_wr[2]) baud_reg_r[23:16] <= cpu_din[23:16];
if(cpu_wr[3]) baud_reg_r[31:24] <= cpu_din[31:24];
end

1)选中寄存器地址,

2)根据不同的写信号 cpu_wr[3:0] ,决定那些数据写入到外设的寄存器中。

 

cpu 读外设寄存器:

// read register
reg [31:0] cpu_dout_r = 0;
always @ (posedge sys_clk or posedge rst)
if(rst) cpu_dout_r <= 0;
else if(cpu_rd)
begin
case(cpu_addr)
UART_BAUD_REG: cpu_dout_r <= baud_reg_r;
UART_CTRL_REG: cpu_dout_r <= ctrl_reg_r;
default: cpu_dout_r <= 0;
endcase
end
assign cpu_dout = cpu_dout_r;

根据cpu总线地址,将外设寄存器的内容返回给cpu。

 

4 cpu_test_if 模块

模拟cpu 总线,发送地址,读写命令,发送写外设数据,或者读取外设数据。本模块模拟cpu 设置uart_ctrl, uart_baud 寄存器。同时可以读取这2个寄存器。

流程图:

图3

状态机详解:

初始化:rst对模块进行初始化操作

状态0:给出写寄存器地址,写使能,写数据,跳转到状态1

状态1:给出第二个需要写的寄存器地址,写使能,写数据,跳转到状态2

状态2:写使能,写数据清0,开始计数,当计数到4的时候给读使能;计数到6的时候给读使能及读寄存器地址,跳转到状态3

状态3:对各种变量清0,保持状态3

cpu_test_if.v 代码:


 

5 仿真及下载调试

图4

测试波形,模拟cpu端发送, 波特率115200, 8bit, no parity, 1 stop bit。 test1: 04 01 02 f8(截断测试)   test2: 06 00 01 aa bb 92  test3: 05 00 01 aa bb 93 (截断测试)

图5

下板测试 04 01 02 f8 (截断测试) 整个数据包完整,读取波段开关只需要3 个字节。 即: 03 01 02 即可。 使用4 个字节,FPGA 可以截断有效字节。

图6

测试06 00 01 aa bb 92 ,完整数据包, 在pra006 上显示正确。

 

quartus 工程代码:

[content_control]

uart_fifo_checksum_cputest.zip

[/content_control]

Posted in FPGA, FPGA 教材教案, Verilog, 教材与教案, 文章