Verilog:关于FPGA的仿真和模拟行为的差异

时间:2017-09-22 13:27:33

标签: verilog fpga uart

编辑:删除了一些冗余,将所有分配移动到非阻塞,插入一个重置映射为我的FPGA的输入按钮之一...但是当我实现代码时,它开始传输相同的错误字符并被卡住在我的机器的单一状态。

后期综合和实施后模拟是相同的,按时间计算

    module UART (reset_button, sysclk_p, sysclk_n,TxD, Tx_busy, Tx_state_scope_external);
    input reset_button, sysclk_p, sysclk_n;
    output wire TxD, Tx_busy;
    output wire [1:0]Tx_state_scope_external;

    //internal communications signals


    wire clk_internal;

    //buffer unit control signals
    wire [7:0]TxD_data_internal;
    wire Tx_start_internal;
    wire Tx_busy_internal;
    wire reset_flag;

    reset_buf RESET_BUFF (.reset_internal (reset_flag), .reset (reset_button));

    differential_CK CK_GENERATION (.sysclk_p (sysclk_p), .sysclk_n(sysclk_n), .clk(clk_internal));

    output_Dbuffer OB1 (.reset (reset_flag), .RTS_n (Tx_busy_internal), .clk(clk_internal), .TX_trigger (Tx_start_internal), .TX_data(TxD_data_internal));

    async_transmitter TX1 (.reset (reset_flag), .clk (clk_internal), .TxD_data(TxD_data_internal), .Tx_start (Tx_start_internal), .TxD(TxD), .Tx_busy_flag(Tx_busy_internal), .Tx_state_scope(Tx_state_scope_external));

    obuf_TX O_TX1( .Tx_busy(Tx_busy), .Tx_busy_flag(Tx_busy_internal));


   endmodule

    module reset_buf (
    output reset_internal,
    input reset
    );
// IBUF: Single-ended Input Buffer
// 7 Series
// Xilinx HDL Libraries Guide, version 14.7
IBUF #(
.IBUF_LOW_PWR("TRUE"), // Low power (TRUE) vs. performance (FALSE) setting for referenced I/O standards
.IOSTANDARD("DEFAULT") // Specify the input I/O standard
) IBUF_inst (
.O(reset_internal), // Buffer output
.I(reset) // Buffer input (connect directly to top-level port)
);
// End of IBUF_inst instantiation

    endmodule

    module differential_CK(

    input sysclk_p,
    input sysclk_n,
    output clk    
    );

    // IBUFGDS: Differential Global Clock Input Buffer
    // 7 Series
    // Xilinx HDL Libraries Guide, version 14.7
    IBUFGDS #(
    .DIFF_TERM("FALSE"), // Differential Termination
    .IBUF_LOW_PWR("TRUE"), // Low power="TRUE", Highest performance="FALSE"
    .IOSTANDARD("DEFAULT") // Specify the input I/O standard
    ) IBUFGDS_inst (
    .O(clk), // Clock buffer output
    .I(sysclk_p), // Diff_p clock buffer input (connect directly to top-level port)
    .IB(sysclk_n) // Diff_n clock buffer input (connect directly to top-level port)
    );
    // End of IBUFGDS_inst instantiation


    endmodule

    module output_Dbuffer (
    input reset,
    input RTS_n, //TX_BUSY flag of the transmitter is my ready to send flag
    input clk, //ck needed for the FSM
    output wire TX_trigger, //TX_START flag of the transmitter now comes from THIS unit instead of Receiver
    output wire [7:0]TX_data //byte for transmission
    );

    //internal variables
    reg [7:0] mem [0:9]; //memory init, 10 * 8 bit locations
    integer m, n, i, j, k ; //M = row [a.k.a. bytes], N = column [a.k.a. single bits]

    reg TX_trigger_int;
    reg [7:0] TX_data_int, TX_complete;
    //reg sum256_ok;        
    reg [7:0]checksum_buff ;

    //buffer FSM required variables 
    localparam  //state enumeration declaration
        BUF_IDLE = 3'b000, 
        BUF_START = 3'b001,
        BUF_BYTES = 3'b010,  
        BUF_BUSY = 3'b011,
        BUF_TX_CHECKSUM = 3'b100;

    reg [2:0] buf_state; //2 bits for 4 states


    //static assignments of OUTPUTS : Transmission Flag and Transmission Data (content)
    assign TX_trigger = TX_trigger_int;
    assign TX_data = TX_data_int;

    //Block for transmitting [here I manage the TX_Data and TX_Trigger functionality]
    always @(posedge clk)
        begin
            if (reset) 
                begin
                    buf_state <= BUF_IDLE;
                    TX_trigger_int <= 0;
                    TX_data_int <= 8'b00000000;

                end
            else case (buf_state)
            BUF_IDLE:
                begin
                       TX_trigger_int <= 0;
                       TX_data_int <= 8'b00000000;
                       m <=0;
                       n <=0;
                       i <=0;
                       j <=0;                                     
                       mem[9] <= 8'b01010001; //81
                       mem[8] <= 8'b01000000; //64
                       mem[7] <= 8'b00110001; //49
                       mem[6] <= 8'b00100100; //36
                       mem[5] <= 8'b00011001; //25
                       mem[4] <= 8'b00010000; //16
                       mem[3] <= 8'b00001001; //9
                       mem[2] <= 8'b00000100; //4
                       mem[1] <= 8'b00000001; //1
                       mem[0] <= 8'b00000010;//2
                       checksum_buff <= 8'd31;
                            //check if the TX is not busy
                       if (RTS_n == 0) buf_state <= BUF_START;                                                                     
                end

            BUF_START:
                begin
                    TX_trigger_int <= 0;
                    if ((i == 0) || ( (j - i) > 1 )) buf_state <= BUF_BYTES;
                            else begin
                                $display ("BUFFER BUSY @time:", $time);
                                buf_state <= BUF_BUSY;   
                            end 
                end   


            BUF_BYTES:
                begin

                    //check if the TX is busy
                    if (RTS_n==0) 
                        begin
                         //   TX_trigger_int = 1; 21.09 MOVED THE TRIGGER INSIDE THE ELSE N LINE 498
                            if (j > 9) 
                                begin
                                        TX_trigger_int <= 0;
                                        buf_state <= BUF_TX_CHECKSUM;
                                    end
                            else begin
                                    TX_data_int <= mem[j];
                                    TX_trigger_int <= 1;
                                    j <= j+1;
                                    //TX_trigger_int =0;
                                    buf_state <= BUF_START;
                                end
                        end
                    else buf_state <= BUF_BYTES;

                end

            BUF_BUSY:
                begin
                    if (RTS_n == 0)
                        begin 
                            $display ("BUFFER AVAILABLE AGAIN @time:", $time);
                            buf_state <= BUF_START;
                        end
                end

            BUF_TX_CHECKSUM:
                begin

                    if (RTS_n==0) begin
                        TX_data_int <= checksum_buff;

                    //    sum256_ok = 0;
                        TX_trigger_int <= 1;
                        buf_state <= BUF_IDLE;
                        end
                end

            //default: buf_state <= BUF_IDLE;

            endcase
    end



    endmodule

    module async_transmitter(
    input clk,
    input reset,
    //differential clock pair
    input [7:0] TxD_data,
    input  Tx_start, // it is ==TX_TRIGGER

    output wire TxD, //bit being sent to the USB

    output reg Tx_busy_flag,
    output wire [1:0]Tx_state_scope
    );

      localparam  //state enumeration declaration
      TX_IDLE = 2'b00, 
      TX_START_BIT = 2'b01,
      TX_BITS = 2'b10,
      TX_STOP_BIT = 2'b11;

      parameter ClkFrequencyTx = 200000000; // 200MHz
      parameter BaudTx = 9600;
      reg [1:0] Tx_state; //2 bits for 4 states
      integer bit_counter;   //bit counter variable
      reg [7:0]TxD_data_int, TxD_int;
      integer i; //vector index for output data
      wire TXSTART_Trigger;

      StartDetectionUnitTX SDU_TX (.clk(clk), .state (Tx_state), .signal_in (Tx_start), . trigger (TXSTART_Trigger));

      wire BitTick;

      BaudTickGen #(ClkFrequencyTx, BaudTx) as (.clk(clk), .trigger (TXSTART_Trigger), .tick(BitTick));
      //BitTick is 16times the frequency generated during the RX portion

      assign TxD = TxD_int;

      always @(posedge clk) begin
            if (reset) 
                begin
                    Tx_state <= TX_IDLE;
                    TxD_int <= 1;
                    Tx_busy_flag <=0;
                end
            else case (Tx_state)

                TX_IDLE:
                    begin //reinitialization and check on the trigger condition

                        bit_counter <= 0;
                        TxD_data_int <= 8'b00000000;
                        i <= 0;
                        TxD_int <= 1; //idle state
                        Tx_busy_flag <= 0; 
                                if (TXSTART_Trigger) begin
                                         Tx_state <= TX_START_BIT;
                                         TxD_data_int <= TxD_data;
                                         Tx_busy_flag <= 1; 
                                         bit_counter <= 8;
                                     end                              

                    end

                TX_START_BIT:
                    begin
                        if (BitTick)
                            begin
                            TxD_int <= 0 ; //start bit is a ZERO logical value

                            Tx_state <= TX_BITS; 
                            end 
            end

                TX_BITS:
                    begin

                        if (BitTick) 
                            begin
                                bit_counter <= bit_counter -1;
                                TxD_int <= TxD_data_int[i];
                       //         $display ("ho trasmesso dalla UART un bit di valore %b al tempo: ", TxD, $time);
                                i <= i+1;
                                if (bit_counter < 1) Tx_state <= TX_STOP_BIT; 
                            end
                    end


                 TX_STOP_BIT:   
                               begin
                                   if (BitTick) begin
                                       TxD_int <= 1; //STOP BIT is a logical '1'
                                       Tx_busy_flag <= 0;
                                       Tx_state <= TX_IDLE;          
                                       end                                 
                               end


               // default: Tx_state <= TX_IDLE;

                endcase

             end 


            assign Tx_state_scope = Tx_state;

endmodule

module obuf_TX (
    output Tx_busy,
    input Tx_busy_flag
    );

// OBUF: Single-ended Output Buffer
// 7 Series
// Xilinx HDL Libraries Guide, version 14.7
OBUF #(
.DRIVE(12), // Specify the output drive strength
.IOSTANDARD("DEFAULT"), // Specify the output I/O standard
.SLEW("SLOW") // Specify the output slew rate
) OBUF_inst (
.O(Tx_busy), // Buffer output (connect directly to top-level port)
.I(Tx_busy_flag) // Buffer input
);
// End of OBUF_inst instantiation

endmodule

module StartDetectionUnitTX ( //detects a rising edge of the start bit == TRANSMISSION START, during the IDLE state = 0000
    input clk, [1:0]state, 
    input signal_in,
    output trigger
    );

    reg signal_d;

    always @(posedge clk)
            begin
            signal_d <= signal_in;
        end   

    assign trigger = signal_in & (!signal_d) & (!state);

endmodule  

module BaudTickGen (
        input clk, trigger, 
        output tick //generates a tick at a specified baud rate *oversampling
        );

        parameter ClkFrequency = 200000000; //sysclk at 200Mhz
        parameter Baud = 9600;
        parameter Oversampling = 1;
        //20832 almost= ClkFrequency / Baud, to make it an integer number
        integer counter = (20833/Oversampling)-1; //-1 so counter can get to 0

        reg out;

        always @(posedge clk)
                   begin
                    if (trigger) 
                        begin
                            counter <= (20833/Oversampling)-1; //-1 so counter can get to 0
                            out <= 1; 
                        end

                           if (counter == 0) 
                               begin
                                   counter <= (20833/Oversampling)-1; //-1 so counter can get to 0
                                   out <= 1; 
                               end
                               else begin

                                   counter <= counter-1;
                                   out <= 0;
                               end   
                    end     

            assign tick = out;
            endmodule

我的FPGA是Virtex-7 VC707,我使用Vivado作为我的设计流程。

这里我附上了循环错误的图像。

error image

1 个答案:

答案 0 :(得分:1)

你做了什么?你刚刚模拟了代码吗?你是说它在主板上失败了,但实现后的模拟卡是否正常?

  1. 执行前和执行后SIM卡之间的差异可能指向竞争条件。摆脱所有阻止分配,替换为NBAs(为什么使用阻止分配?)
  2. 不要去Chipscope - 这只是一面红旗,你不知道你在做什么
  3. 代码很乱 - 简化它。特定Xilinx的东西是无关紧要的 - 如果你想让任何人看一下它,解决它,修复注释( 2 -bit state ?!),修复你关于陷入'10'的声明,等
  4. 您是通过Vivado运行的吗?真的吗?您有各种信号的多个驱动程序。摆脱初始块,使用重置。以工具理解的方式初始化RAM。即使Vivado能够使用单独的初始块初始化东西,也不要这样做
  5. 删除TX_IDLE分支中的'else Tx_state = TX_IDLE'之类的语句 - 它们是多余的,只是添加详细程度
  6. 写一些单独失败的东西,然后重新发布。