问题描述
我真的不知道如何很好地表达这个问题,这是我关于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中提取并以较慢的时钟进行发送。 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被按下!”,我有:
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
但是上面使用了大量的逻辑元素!所有LE(“ LC Combinationals”)中几乎有70%来自此模块。更不用说一次分配一个字符是可怕的编程风格...我在其他编程语言中有着很深的背景,但是Verilog开始挑战我。
- 如何将准备好的“字符串”复制到缓冲区中,以便随后通过串行接口发送?
- 存储其中几个字符串的最佳方法是什么?内部块ROM并将字节从其中移出到缓冲区中?常量,localparams?
- 很明显,如果同时按下button0和button1,结果将是不可预测的!这使我认为“
请帮助!!干杯
解决方法
您可以使用@Light所建议的长打包字符串,而不是添加字符串,并在整个字符串上使用shift运算符,如下所示。
reg [8 * 128 - 1:0] response_message,tmp;
...
always @(negedge clk) begin
response_message <= response_message | ("Button 0!\n" << (response_message_end * 8));
...
此外,请确保在一个always块中分配“ start” /“ end”值,以避免多个驱动程序。