如何为以后的串行传输编写字符串?
How do I compose strings for later serial transmission?
我真的不知道如何表达这个问题,这是我第一次 post 在 Whosebug 上,所以我提前道歉。
这一切都在 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 pressed!”,我有:
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 Combinationals”)都来自这个模块。更不用说一次分配一个字符是一种可怕的编程风格......我在其他编程语言方面有很强的背景,但 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));
...
此外,请确保在单个始终块中分配 'start'/'end' 值以避免多个驱动程序。
我真的不知道如何表达这个问题,这是我第一次 post 在 Whosebug 上,所以我提前道歉。
这一切都在 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 pressed!”,我有:
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 Combinationals”)都来自这个模块。更不用说一次分配一个字符是一种可怕的编程风格......我在其他编程语言方面有很强的背景,但 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));
...
此外,请确保在单个始终块中分配 'start'/'end' 值以避免多个驱动程序。