Перейти к содержанию
    

Переход триггера в Z-состояние при приеме бита

Описываю поведение простого UART-передатчика на Verilog в среде Xiling Vivado 2018.2.

При присваивании D-триггеру значения с входного порта, он переходит в Z-состояние. Также при попытке присвоить этот сигнал цепи через оператор непрерывного присваивания assign, цепь также принимает высокоимпедансное состояние. В чем может быть причина такого поведения/симуляции, и как это можно исправить?

Описание модуля следующее:

Скрытый текст

`timescale 1ns / 100ps

module UART_rx
#(parameter FREQ = 24_000_000,
            BAUD_RATE = 9600)
(
    input wire clk, //reset,
    input wire DATA_serial,
    
    output reg data_bit, 
    output reg data_bit2,
    output reg [2:0] STATE,
    output reg [11:0] clk_counter,
    
    output reg done_tick = 0,
    output wire [7:0] DATA_byte

    );
    
//signal declaration
//reg [11:0] clk_counter = 0;
//reg data_bit, data_bit2;
reg [2:0] bit_index = 0;
reg [7:0] byte_bit = 0;
//reg [2:0] STATE = 0;

//dowble register body
always @(posedge clk)
  begin
    data_bit2 <= DATA_serial;
    data_bit <= data_bit2;
  end

    


//state declaration
localparam [2:0] IDLE = 3'b000,
                 START_BIT = 3'b001,
                 DATA_TRANSFER = 3'b010,
                 STOP_BIT = 3'b011,
                 CLEAN_UP = 3'b100;
                 
//------------FSM BODY---------------
always @(posedge clk)
  begin
    case (STATE) IDLE: begin
                       //waiting start_bit
                       done_tick <= 0;
                       clk_counter <= 0;
                       bit_index <= 0;
                         if (data_bit == 0) 
                           STATE <= START_BIT;
                         else
                           STATE <= IDLE;
                       end
                       
           START_BIT: begin
                      //check the midle of start_bit
                      done_tick <= 0;
                      clk_counter <= 0;
                      bit_index <= 0;
                        if (clk_counter == ((FREQ/2/BAUD_RATE)-1)) 
                          if (data_bit == 0) begin 
                            clk_counter <= 0; //midle of input_bit duration
                            STATE <= DATA_TRANSFER; end
                          else 
                            STATE <= IDLE; 
                        
                        else begin
                          clk_counter <= clk_counter + 1;
                          STATE <= START_BIT;
                        end
                      end
                      
       DATA_TRANSFER: begin
                      // receive 8 bit of data
                      done_tick <= 0;
                      bit_index <= 0;
                        if (clk_counter < ((FREQ/BAUD_RATE)-1)) begin
                          clk_counter <= clk_counter + 1;  
                          STATE <= DATA_TRANSFER; end
                        else begin
                          clk_counter <= 0;
                          byte_bit[bit_index] <= data_bit;
                            if (bit_index < 7) begin
                              bit_index <= bit_index + 1;
                              STATE <= DATA_TRANSFER; end
                            else begin
                              bit_index <= 0;
                              STATE <= STOP_BIT; end
                        end
                     end
                     
           STOP_BIT: begin
                     // receive stop-bit
                       if (clk_counter < ((FREQ/BAUD_RATE)-1)) begin
                         clk_counter <= clk_counter + 1;
                         STATE <= STOP_BIT; end
                       else begin
                         done_tick <= 1;
                         clk_counter <= 0;
                         STATE <= CLEAN_UP; end
                     end
                     
           CLEAN_UP: begin
                     //waiting 1 clk cycle
                     done_tick <= 0;
                     STATE <= IDLE;
                     end
                     
             default: STATE <= IDLE;
  endcase
end
   
   
assign DATA_byte = byte_bit;   
                                            
    
endmodule

 

 

Снимок.PNG

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А код тестбенча можете привести?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, KRUTOMER said:

Описываю поведение простого UART-передатчика на Verilog в среде Xiling Vivado 2018.2.

При присваивании D-триггеру значения с входного порта, он переходит в Z-состояние. Также при попытке присвоить этот сигнал цепи через оператор непрерывного присваивания assign, цепь также принимает высокоимпедансное состояние. В чем может быть причина такого поведения/симуляции, и как это можно исправить?

 

Причина может быть в метастабильности

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 minutes ago, =AK= said:

Причина может быть в том, что входной сигнал и клок находятся в разных time domains.

В симуляторе нет понятия мета-стабильность.  Скорее всего проблемы в самой логике  модуля или TB. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Описываю поведение простого UART-передатчика...


// receive 8 bit of data


Может для начала в schematic-е? Для ясности ;-)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 часов назад, Raven сказал:

А код тестбенча можете привести?

Вот код самого тестбенча:

`timescale 1ns / 1ps

module UART_test;

reg clk; //reset;
reg DATA_serial;
wire done_tick, data_bit, data_bit2;
wire [2:0] STATE;
wire [7:0] DATA_byte;
wire [11:0] clk_counter;

UART_rx UART_uut
(.clk(clk),/* .reset(reset),*/ .done_tick(done_tick), .DATA_byte(DATA_byte),
.data_bit(data_bit), .data_bit2(data_bit2), .STATE(STATE), .clk_counter(clk_counter));

initial begin
clk = 0;
//reset = 1;
DATA_serial = 1'b1;
end
always #40 clk = ~clk;

initial begin
//#100 reset = 0;
#10000
#100_000 DATA_serial = 1'b1;
#100_000 DATA_serial = 1'b0; //start-bit
#100_000 DATA_serial = 1'b1; //0
#100_000 DATA_serial = 1'b0; //1
#100_000 DATA_serial = 1'b0; //2
#100_000 DATA_serial = 1'b0; //3
#100_000 DATA_serial = 1'b0; //4
#100_000 DATA_serial = 1'b0; //5
#100_000 DATA_serial = 1'b0; //6
#100_000 DATA_serial = 1'b0; //7
#100_000 DATA_serial = 1'b1; //stop-bit
#100_000
$stop;
end

endmodule

 

7 часов назад, Obam сказал:

 


Может для начала в schematic-е? Для ясности ;-)

 

Снимок.PNG

schematic.pdf

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

 

12 hours ago, KRUTOMER said:

Описание модуля следующее:

1 hour ago, KRUTOMER said:

Вот код самого тестбенча:

Если уж  в модуле UART  есть вход  DATA_serial то  почему  в TB вы  его  не подключаете в модуль?  Висящий  в "воздухе" вход  имеет неопределённой состояние которое и распространяется по логике модуля. :cray:

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

24 минуты назад, RobFPGA сказал:

 

Если уж  в модуле UART  есть вход  DATA_serial то  почему  в TB вы  его  не подключаете в модуль?  Висящий  в "воздухе" вход  имеет неопределённой состояние которое и распространяется по логике модуля. :cray:

 

Да, и вправду по невнимательности не добавил DATA_serial и инстанс. Сбасибо большое

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

11 hours ago, RobFPGA said:

В симуляторе нет понятия мета-стабильность.

может придираюсь к словам, я же сейчас в timing simulation засел. Там если симулятор без спец ключа запустить, то при первом же слаке сигнал впадает в X. Не знаю, называется ли это мета-стабильность. Ну и понятно, что тут не этот случай, просто к слову

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 minute ago, new123 said:

может придираюсь к словам, я же сейчас в timing simulation засел. Там если симулятор без спец ключа запустить, то при первом же слаке сигнал впадает в X. Не знаю, называется ли это мета-стабильность

В симе, при желании, можно симулировать поведение триггера при условиях возникновения  мета-стабильности. Но для этого нужны  специальные модели. Как раз для этого и служат библиотеки примитивов которые используются для timing simulation. Но в функциональной симуляции (и вообще в симе) как таковой мета-стабильности нет, так как значение триггеру присваивается за 0 время. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так всё-таки это приёмник УАППа (но до чего hardware "жирный") и проблема разрешиась?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Еще раз спасибо большое всем, кто помог решить проблему и написал код ревью на мой UART-приемник. Все-таки решил чуть переписать модуль по заветам Понг П. Чу, а именно конечный автомат

Модуль:

`timescale 1ns / 100ps

module UART_receiver
#(parameter FREQ = 24_000_000,
            BAUD_RATE = 9600)
(
    input wire clk, //reset,
    input wire DATA_serial,
    
    output reg data_bit = 0, 
    output reg data_bit2 = 0,
    output reg [2:0] STATE_reg = 0,
   output reg [11:0] clk_counter_reg = 0,
   output reg [2:0] bit_index_reg = 0,
    
    output reg done_tick = 0,
    output wire [7:0] DATA_byte

    );
    
//signal declaration
//reg [11:0] clk_counter_reg;
reg [11:0] clk_counter_next;
//reg data_bit, data_bit2;
//reg [2:0] bit_index_reg;
reg [2:0] bit_index_next;
reg [7:0] byte_bit = 0;
//reg [2:0] STATE_reg;
reg [2:0] STATE_next;

//dowble register body
always @(posedge clk)
  begin
    data_bit2 <= DATA_serial;
    data_bit <= data_bit2;
    STATE_reg <= STATE_next;
    clk_counter_reg <= clk_counter_next;
    bit_index_reg <= bit_index_next;
  end

//state declaration
localparam [2:0] IDLE = 3'b000,
                 START_BIT = 3'b001,
                 DATA_TRANSFER = 3'b010,
                 STOP_BIT = 3'b011,
                 DONE = 3'b100;
                 
//------------FSM BODY---------------
always @*
  begin
    done_tick = 0;
    clk_counter_next = clk_counter_reg;
    bit_index_next = bit_index_reg;
    STATE_next = STATE_reg;
  
  
      case (STATE_reg) IDLE: begin
                           //waiting start_bit
                               if (data_bit == 0) 
                                 STATE_next = START_BIT;
                               else
                                 STATE_next = IDLE;
                             end
                       
           START_BIT: begin
                      //check the midle of start_bit
                        if (clk_counter_next == ((FREQ/2/BAUD_RATE)-1)) 
                          if (data_bit == 0) begin 
                            clk_counter_next = 0; //midle of input_bit duration
                            STATE_next = DATA_TRANSFER; end
                          else 
                            STATE_next = IDLE; 
                        else begin
                          clk_counter_next = clk_counter_reg + 1;
                          STATE_next = START_BIT;
                        end
                      end
                      
       DATA_TRANSFER: begin
                      // receive 8 bit of data
                        if (clk_counter_next < ((FREQ/BAUD_RATE)-1)) begin
                          clk_counter_next = clk_counter_reg + 1;  
                          STATE_next = DATA_TRANSFER; end
                        else begin
                          clk_counter_next = 0;
                          byte_bit[bit_index_next] = data_bit;
                            if (bit_index_next < 7) begin
                              bit_index_next = bit_index_reg + 1;
                              STATE_next = DATA_TRANSFER; end
                            else begin
                              bit_index_next = 0;
                              STATE_next = STOP_BIT; end
                        end
                     end
                     
           STOP_BIT: begin
                     // receive stop-bit
                       if (clk_counter_next < ((FREQ/BAUD_RATE)-1)) begin
                         clk_counter_next = clk_counter_reg + 1;
                         STATE_next = STOP_BIT; end
                       else begin
                        // done_tick = 1;
                         clk_counter_next = 0;
                         STATE_next = DONE; end
                     end
                     
           DONE: begin
                     //waiting 1 clk cycle
                     done_tick = 1;
                     STATE_next = IDLE;
                     end
                     
             default: STATE_next = IDLE;
  endcase
end
   
   
assign DATA_byte = byte_bit;   
                                            
    
endmodule

Тестбенч:

`timescale 1ns / 1ps

module UART_test;

reg clk; //reset;
reg DATA_serial;
wire done_tick, data_bit, data_bit2;
wire [2:0] bit_index;
wire [2:0] STATE;
wire [7:0] DATA_byte;
wire [11:0] clk_counter;

UART_receiver UART_uut
(.clk(clk),/* .reset(reset),*/ .done_tick(done_tick), .DATA_byte(DATA_byte), .DATA_serial(DATA_serial),
.data_bit(data_bit), .data_bit2(data_bit2), .STATE_reg(STATE), .clk_counter_reg(clk_counter), .bit_index_reg(bit_index));

initial begin
clk = 0;
//reset = 1;
DATA_serial = 1'b1;
end
always #40 clk = ~clk;

initial begin
//#100 reset = 0;
#200_000
#200_000 DATA_serial = 1'b1;
#200_000 DATA_serial = 1'b0; //start-bit
#200_000 DATA_serial = 1'b0; //0
#200_000 DATA_serial = 1'b1; //1
#200_000 DATA_serial = 1'b1; //2
#200_000 DATA_serial = 1'b0; //3
#200_000 DATA_serial = 1'b0; //4
#200_000 DATA_serial = 1'b1; //5
#200_000 DATA_serial = 1'b0; //6
#200_000 DATA_serial = 1'b0; //7
#200_000 DATA_serial = 1'b1; //stop-bit
#200_000
$stop;
end

 

Снимок.PNG

 

Снимок2.PNG

22.01.2022 в 01:25, Obam сказал:

Так всё-таки это приёмник УАППа (но до чего hardware "жирный") и проблема разрешиась?

Просто для симуляции сделал дополнительные выходы

Изменено пользователем KRUTOMER

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, KRUTOMER said:

Все-таки решил чуть переписать модуль по заветам Понг П. Чу, а именно конечный автомат

Модуль:

Совет - лучше вставлять код  в фрейм  Code <>,  так не слетает форматирование. А если код длинный, то заодно и в фрейм Spoiler чтобы была удобнее навигация по топикам.  

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...