上一节中,我们遵循uart协议,它发送一次只能发送6/7/8位数据,我们不能随意更改位数(虽然在代码上可行),不然就不遵循uart协议了,会造成接收端无法接收。
在现实生活中,我们有时候要发的数据不止8位,这时候就得多次发送了。分多段发送,就是说发送一次数据的时间里发送系统有多个状态,这便是状态机。即有限状态自动机,通常体现为一张流程图。一般包含state(状态),event(事件),action(动作),transition(转换)四个要素。
如在此情景下,有以下几个状态:

像这种有多个状态的情景,我们可以设置状态变量state,使能端enable,结束位tx_done(一般在底层)来控制状态的转换。
所以关键的点在于,把问题逻辑抽象化。最好是画出一个流程图来,大部分问题便迎刃而解了。
注意:
1.仿真时给的脉冲20ns可能会使判断条件无效,设置为21ns即可。或者给个200ns的延迟后再给20ns的脉冲。
2.通过观察其他变量的波形,来设置tx_done变化的判定条件,从而优化了tx——done的持续时间。
3.可以加入一个signal信号来控制仿真合适结束(通过@(negedge signal))
4.隐式例化:例化时不改变端口的数量,顺序,便是隐式例化,只需要定义端口的reg类型即可。
不足:
1.状态太多,代码很长。
2.适应范围不广。
思考:
1.如何优化状态机,做到只用3个状态就能实现上述功能。
2.优化代码使得可以十分简单的修改代码从而达到发送任意字节的数据的功能(字节有上限)。
module uart_4_nbyte(//用ifelse的方法传送五个字节的数据
clk,
reset,
data40,
send_pulse,
uart_tx,
sign
);
input clk ;
input reset ;
input send_pulse ;
input [39:0]data40 ;
output uart_tx ;
output sign ;
reg send_en ;
wire tx_done ;
reg [7:0]data ;
uart_1_1 uart_4_nbyte1( //设计输入
.clk(clk),//时钟
.reset(reset),//复位
.data(data),//数据
.send_en(send_en),//使能
.baud_rate(3'd5),//波特率
.uart_tx(uart_tx),//串口输出
.tx_done(tx_done)//结束信号
);
reg [2:0]state ;
reg sign ;
always@(posedge clk or negedge reset)
if (!reset)
begin
state <= 1'b0 ;
sign <= 1'b0 ;
data <= 0 ;
end
else if(send_pulse == 1'b1)
begin
state <= 1'b1 ;
send_en <= 1'b1 ;
sign <= 1 ;
end
else if (state == 1 )
begin
if(!tx_done)
begin
data <= data40[7:0] ;
send_en <= 1 ;
end
else if(tx_done)
begin
state <= 2 ;
send_en <= 0 ;
end
end
else if (state =

该博客探讨了在UART通信协议下,如何处理发送超过8位数据的情况。通过引入状态机,将数据分段发送,文章详细描述了状态机的设计思路,包括状态、事件、动作和转换,并提供了Verilog代码示例。同时,提出了状态机的优化思考,如减少状态数量和增强代码的灵活性,以适应不同字节数据的发送需求。此外,还提到了仿真时需要注意的脉冲宽度问题以及如何控制仿真结束。
最低0.47元/天 解锁文章
3044

被折叠的 条评论
为什么被折叠?



