verilog - 如何为以后的串行传输编写字符串?
问题描述
我真的不知道如何很好地表达这个问题,这是我在stackoverflow上的第一篇文章,所以我提前道歉。
这一切都在 Cyclone IV FPGA 上。
首先,我有一个名为 UART 的模块连接到两个物理引脚,TX 和 RX。UART 运行良好,具有参数化的传输速率、停止位、奇偶校验等。
该 UART 模块周围是一个控制器模块,其中包括两个 FIFO,一个用于传出数据,一个用于传入数据。它被称为 UART_System 并包括用于发送和接收数据的辅助端口:
input clock,
input [7:0] tx_data,
input tx_req,
output tx_buffer_full,
output [7:0] rx_data,
input rx_req,
output rx_buffer_empty
当 rx_buffer_empty 为低电平时,您断言 rx_req 一个时钟,并从 rx_data 读取数据。类似的方法用于传输。这还没有通过线路发送数据,它只是与 FIFO 交互,UART 稍后会从中提取并以较慢的时钟进行传输。FIFO 是双时钟 Quartus IP。这一切都很好。
我仍然是 Verilog 的新手......那么我如何在一个时钟周期内对整条消息进行排队?显然,你不能,所以这就是我想出的。
首先,一些存储:
byte response_message [0:127];
reg [6:0] response_message_start;
reg [6:0] response_message_end;
在复位时,response_message_start
设置response_message_end
为 0。在每个时钟周期,
always @(negedge clock)
...
// Check for outgoing data
if(response_message_start != response_message_end) begin
tx_req <= 'b1;
tx_data <= response_message[response_message_start];
response_message_start <= response_message_start + 1;
end else begin
tx_req <= 'b0;
response_message_start <= 0;
response_message_end <= 0;
end
...
end
(忽略它现在不能优雅地处理 tx_buffer_full 的事实)。我相信上述方法效果很好。
这是我的问题。假设有一些用户事件我想发送一条消息,比如“Button1 was press!”,我有:
always (negedge clock) begin
...
if(~button0) begin
response_message[response_message_end+0] <= "B";
response_message[response_message_end+1] <= "u";
response_message[response_message_end+2] <= "t";
response_message[response_message_end+3] <= "t";
response_message[response_message_end+4] <= "o";
response_message[response_message_end+5] <= "n";
response_message[response_message_end+6] <= " ";
response_message[response_message_end+7] <= "0";
response_message[response_message_end+8] <= "!";
response_message[response_message_end+9] <= "\n";
response_message_end <= response_message_end + 10;
end
if(~button1) begin
response_message[response_message_end+0] <= "B";
response_message[response_message_end+1] <= "u";
response_message[response_message_end+2] <= "t";
response_message[response_message_end+3] <= "t";
response_message[response_message_end+4] <= "o";
response_message[response_message_end+5] <= "n";
response_message[response_message_end+6] <= " ";
response_message[response_message_end+7] <= "1";
response_message[response_message_end+8] <= "!";
response_message[response_message_end+9] <= "\n";
response_message_end <= response_message_end + 10;
end
...
end
但是上面使用了大量的逻辑元素!几乎 70% 的 LE(“LC 组合”)来自该模块。更不用说一次分配一个字符是一种可怕的编程风格......我在其他编程语言方面有很强的背景,但 Verilog 开始挑战我。
- 以后如何将准备好的“字符串”复制到缓冲区中以通过串行接口发送?
- 存储这些字符串的最佳方法是什么?内部块 ROM 并将其中的字节输出到缓冲区中?常量,局部参数?
- 很明显,如果 button0 和 button1 都被按下,结果将是不可预测的!这让我认为“<=”不是这种情况的正确分配。
请帮忙!!干杯
解决方案
正如@Light 所建议的那样,您可以使用长压缩字符串代替添加,并在整个字符串上使用移位运算符,如下所示。
reg [8 * 128 - 1:0] response_message, tmp;
...
always @(negedge clk) begin
response_message <= response_message | ("Button 0!\n" << (response_message_end * 8));
...
此外,请确保在单个始终块中分配“开始”/“结束”值以避免多个驱动程序。
推荐阅读
- ruby-on-rails - 在 Rails 上使用 ImageMagick 绘制不使用 PNG
- python - 从数组(频谱...)生成音频文件
- jquery - 使用 Apache 2.4.6 加载 magnific popup 时出现“无法加载内容” - 但不是 Apache 2.2.15
- c# - 在 lambda 表达式中使用局部属性的方法
- sql - 如何重命名系统生成的约束名称和主键索引
- c# - 为什么我从 Clipboard 类中得到 OutOfMemoryException?
- sql - 需要合并两个 SQL 查询
- jquery - ajax 响应在附加到元素时忽略换行符
- c# - 使用 ClosedXML C# 为数字添加掩码
- scala - 警告匹配可能并不详尽