如何为以后的串行传输编写字符串?

问题描述

我真的不知道如何很好地表达这个问题,这是我关于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_startresponse_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开始挑战我。

  1. 如何将准备好的“字符串”复制到缓冲区中,以便随后通过串行接口发送?
  2. 存储其中几个字符串的最佳方法是什么?内部块ROM并将字节从其中移出到缓冲区中?常量,localparams?
  3. 很明显,如果同时按下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”值,以避免多个驱动程序。