Verilog Reg数组

时间:2017-10-11 02:26:47

标签: verilog fpga mojo

在循环访问1D reg数组时遇到一些麻烦。

最终我试图完成以下任务。

  1. 在“Listen”状态下,rx_values填充一个读缓冲区(4个8位字符)来存储在控制台中输入的字符,并通过将tx_data设置为最后一个字符来回显该字符(这有效)

  2. 当按下回车键时,状态切换到“读取”,每次迭代将tx_data设置为读缓冲,直到达到第4个字符,此时状态重置为空闲。 (这不起作用)

  3. 我进入读取状态;但是,计数器无法按预期工作。

    任何帮助将不胜感激。

    module receiver (
    input clk,
    input rst,
    output reg [7:0] tx_data,
    output reg new_tx_data,
    input tx_busy,
    input [7:0] rx_data,
    input new_rx_data
    );
    localparam idle = 4'h0 ,listen = 4'h1 ,read = 4'h2, write = 4'h3; 
    reg [3:0] state = idle;
    reg [7:0] readbuff[3:0];
    integer buffdex;
    
    always @* begin
    end
    
    
    always @(posedge clk) begin
    new_tx_data = 1'b0;
    
    case (state) 
      idle: begin 
        if(new_rx_data) begin
          state<=listen;
        end
      end
      listen: begin
        new_tx_data = 1'b1;
        readbuff[buffdex] = rx_data;
        tx_data = readbuff[buffdex];
        //tx_data = buffdex;
        buffdex = buffdex + 1';
        if(rx_data == 8'h0D) begin
          tx_data = "\n";
          buffdex = 0;
          state <= read;
        end else begin
          state<=idle;
        end
      end
      read: begin
        new_tx_data = 1'b1;
        tx_data = readbuff[buffdex];
        buffdex = buffdex + 1;
        if (buffdex == 3) begin
          state <= idle;
        end
        //tx_data = state;
      end
    
    endcase
    end
    
    endmodule
    

2 个答案:

答案 0 :(得分:1)

很抱歉使用&#34;回答&#34;功能而不是评论,但我还没有足够的分数。这是一个&#34;评论&#34;。既然你想要any help,我希望这适合。

1)您的代码在功能和可读性方面都需要一些改进(空组合块,将BA与NBA混合 - &gt;混合组合与顺序逻辑,复位输入但没有复位逻辑,注释逻辑线,FSM上的锁存器)。 / p>

考虑根据一些好的编码实践重写它,例如http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf

您还会遇到buffdex = buffdex + 1'buffdex = buffdex + 1等不一致的问题。 (因而没有精辟的编译)。

2)您能为此模块提供测试平台吗?您是否尝试过频闪信号来检查它们的值? buffdex状态read会增加吗? if语句是否可以访问?

3)由于这不是Mojo的第一个问题(似乎正在开发中),您可以考虑免费https://www.edaplayground.com/进行测试和编译/语法检查。

答案 1 :(得分:0)

所以我读了这篇论文(以及其他各种IEEE指令),最后得到了一个工作版本。下面是代码。和以前一样,我打开了关于如何使代码更高效或更有效的建议。我认为读取缓冲区是一个很大的锁存器,但不知道如何解决它。

module receiver (
    //inputs
    input clk,
    input rst,
    input tx_busy,
    input [7:0] rx_data,
    input new_rx_data,
    //outputs
    output reg [7:0] tx_data,
    output reg new_tx_data,
    output reg [0:4] LED
    );


    //local parameters
    localparam IDLE = 2'b00 , LISTEN = 2'b01 ,NEWLINE = 2'b10, READ = 2'b11;


    //fsm state reg and readbuff reg
    reg [1:0] stated, stateq;
    reg [3:0] cntrd,cntrq;
    reg [7:0] readbuff [15:0];
    reg nl;

    //on clock edge set flip-flop  - non-blocking assignments
    always @(posedge clk ) begin
      if(rst) begin
        stateq <= IDLE; 
        cntrq<=4'b0000;
      end else begin
       //update the state and readbuff index values to be current.
       stateq <= stated;
       cntrq <=cntrd;
      end
    end

    //sequential and combinational blocking assignments
    always @(*) begin
      //set default states to avoid latches.
      stated = stateq;
      cntrd = cntrq; 
      LED = cntrq;
      //set output defaults
      tx_data = 8'hxx;
      new_tx_data = 1'b0;

      case (stateq) 
        IDLE: begin
          //move to listen state
          cntrd=4'b0;
          stated = stateq + 1'b1;
        end
        LISTEN: begin
          if(new_rx_data) begin
            //set readbuffer[indx] to the rx data
            readbuff[cntrq] = rx_data;
            new_tx_data = 1'b1;
            tx_data = readbuff[cntrq];
            cntrd = cntrq + 1'b1;
            //if enter is pressed change states, otherwise, echo and increase the read buffer.
            if(rx_data == "\r" || rx_data == "\n") begin
              stated = stateq + 1'b1;
              cntrd=4'b0000;
            end
          end
        end
        NEWLINE: begin  
        if(!tx_busy) begin
               new_tx_data = 1'b1;
               tx_data = 8'h0A;
               nl = 1'b1;
               stated = stateq + 1'b1;
             end
        end
        READ: begin
          //check the value of cntrq for the enter statement 
          if(readbuff[cntrq] == "\r" || readbuff[cntrq] == "\n" ) begin
             stated = IDLE;
          //otherwise write out the value of the readbuff - tx busy should sync to avr clock
          end else begin    
            if (!tx_busy) begin
              new_tx_data = 1'b1;
              tx_data = readbuff[cntrq];
              cntrd = cntrq + 1'b1;
            end  
          end
        end    
      endcase
    end
    endmodule