⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 auto_baud.v

📁 VGA/LCD Corev2.0Specifications
💻 V
📖 第 1 页 / 共 2 页
字号:
reg idle;                 // Indicates state
reg run;                  // Indicates state
reg measure;              // Indicates state
reg clear_counters;       // Pulses once when measurement is done.
reg verify;               // Indicates state
reg character_miscompare; // Indicates character did not verify
reg [`LOG2_MAX_CLOCK_FACTOR-1:0] clock_count; // Clock_factor prescaler,
                                              // and mid_bit counter.
reg [LOG2_MAX_COUNT_PP-1:0] main_count;       // Main counter register
reg [LOG2_MAX_COUNT_PP-1:0] measurement;      // Stored measurement count
reg [`BITS_PER_CHAR:0] target_bits;           // Character bits to compare
// (lsb is not needed, since it is used up during measurement time,
//  but the stop bit and possible parity bit are needed.)

    // For the state machine
reg [3:0] m1_state;
reg [3:0] m1_next_state;



//--------------------------------------------------------------------------
// Instantiations
//--------------------------------------------------------------------------


//--------------------------------------------------------------------------
// Module code
//--------------------------------------------------------------------------


// This is the CLOCK_FACTOR_PP prescaler and also mid_bit_count counter
assign enable_clock_count = measure || (verify && main_count_rollover);
always @(posedge clk_i or posedge reset_i)
begin
  if (reset_i) clock_count <= 0;
  else if (clear_counters) clock_count <= 0;
  else if (enable_clock_count)
  begin  // Must have been clk_i edge
    if (clock_count_rollover) clock_count <= 0;
    else clock_count <= clock_count + 1;
  end
end
// Counter rollover condition
assign clock_count_rollover = (clock_count == (CLOCK_FACTOR_PP-1));
// This condition signals the middle of a bit time, for use during the
// verify stage.  Also, this signal is used to advance the main count,
// instead of "clock_count_rollover."  This produces an effective "rounding"
// operation for the measurement (which would otherwise "truncate" any
// fraction of time contained in this counter at the instant the measurement
// is finished.
// (The "enable_clock_count" is included in order to make the pulse narrow,
//  only one clock wide...)
assign mid_bit_count = (
                        (clock_count == ((CLOCK_FACTOR_PP>>1)-1))
                        && enable_clock_count
                        );

// This is the main counter.  During measurement, it advances once for
// each CLOCK_FACTOR_PP cycles of clk_i.  This accumulated measurement
// is then latched into "measurement" when the state machine determines that
// the measurement interval is finished.
// During verify and idle_run times (whenever the baud rate clock is used)
// this counter is allowed to run freely, advancing once each clk_i, but being
// reset when it reaches a total count of "measurement" clock cycles.  The
// signal that reset the counter during this type of operation is the baud
// rate clock.
always @(posedge clk_i or posedge reset_i)
begin
  if (reset_i) main_count <= 0;
  else // must have been clk_i edge
  begin
    // Clear main count when measurement is done
    if (clear_counters) main_count <= 0;
    // If measuring, advance once per CLOCK_FACTOR_PP clk_i pulses.
    else if (measure && mid_bit_count) main_count <= main_count + 1;
    // If verifying or running, check reset conditions, 
    // otherwise advance always.
    else if (verify || run)
    begin
      if (main_count_rollover) main_count <= 0;
      else main_count <= main_count + 1;
    end
  end
end

// This is a shift register used to provide "target" character bits one at
// a time for verification as they are "received" (sampled) using the
// candidate baud clock.
always @(posedge clk_i or posedge reset_i)
begin
  if (reset_i) target_bits <= `TEMPLATE_BITS;
  else // must have been a clock edge
  begin
    if (~verify) target_bits <= `TEMPLATE_BITS;
    if (verify && mid_bit_count) target_bits <= {0,(target_bits>>1)};
  end
end
// It is done when only the stop bit is left in the shift register.
assign verify_done = (
                       (target_bits == 1)
                       && verify
                       && mid_bit_count
                      );

// This is a flip-flop used to keep track of whether the verify operation
// is succeeding or not.  Any target bits that do not match the received
// data at the sampling edge, will cause the verify_failed bit to go high.
// This is what the state machine looks at to determine whether it passed
// or not.
always @(posedge clk_i or posedge reset_i)
begin
  if (reset_i) character_miscompare <= 0;
  else  // Must have been a clock edge
  begin
    if (idle) character_miscompare <= 0;
    if (verify && mid_bit_count
        && (target_bits[0] ^ serial_dat_i)) character_miscompare <= 1;
  end
end


// This is the measurement storage latch.  The final measured time count
// from main_count is stored in this latch upon completion of the measurement
// interval.  The value stored in this latch is used whenever the baud clock
// is being generated, to reset the main count (causing a "rollover").
always @(posedge clk_i or posedge idle)
begin
  // Set to all ones during idle (asynchronous).
  if (idle) measurement <= -1;
  // Otherwise, there must have been a clk_i edge
  // When the measurement is done, the counters are cleared, and the time
  // interval must be stored before it is cleared away...
  // This also causes a store following a failed verify state on the way back
  // into idle, but the idle state clears out the false measurement anyway.
  else if (clear_counters) measurement <= (main_count>>1);
end

// This is effectively the baud clock signal
// But it is prevented from reaching the output pin during verification...
// It is only allowed out of the module during idle_run state.
assign main_count_rollover = (main_count == measurement);
assign baud_clk_o = (main_count_rollover && run);


// This is state machine m1.  It checks the status of the serial_dat_i line
// and coordinates the measurement of the time interval of the first two
// bits of the received character, which is the "measurement interval."
// Following the measurement interval, the state machine enters a new
// phase of bit verification.  If the measured time interval is accurate
// enough to measure the remaining 8 bits of the character correctly, then
// the measurement is accepted, and the baud rate clock is driven onto
// the baud_clk_o output pin.  Incidentally, the process of verification
// effectively filters out all characters which are not the desired target
// character for measurement.  In this case, the target character is the
// carriage return.


// State register
always @(posedge clk_i or posedge reset_i)
begin : m1_state_register
  if (reset_i) m1_state <= m1_idle;          // asynchronous reset
  else m1_state <= m1_next_state;
end

// State transition logic
always @(m1_state
         or mid_bit_count
         or serial_dat_i
         or verify_done
         or character_miscompare
         )
begin : m1_state_logic

  // Default values for outputs.  The individual states can override these.
  idle <= 1'b0;
  run <= 1'b0;
  measure <= 1'b0;
  clear_counters <= 1'b0;
  verify <= 1'b0;

  case (m1_state) // synthesis parallel_case

    m1_idle :
      begin
        idle <= 1'b1;
        if (serial_dat_i == 0) m1_next_state <= m1_measure_0;
        else m1_next_state <= m1_idle;
      end

    m1_measure_0 :
      begin
        measure <= 1'b1;
        // Check at mid bit time, to make sure serial line is still low...
        // (At this time, "mid_bit_count" is simply CLOCK_FACTOR_PP>>1 clk_i's.)
        if (mid_bit_count && ~serial_dat_i) m1_next_state <= m1_measure_1;
        // If it is not low, then it must have been a "glitch"...
        else if (mid_bit_count && serial_dat_i) m1_next_state <= m1_idle;
        else m1_next_state <= m1_measure_0;
      end

    m1_measure_1 :
      begin
        measure <= 1'b1;
        // Look for first data bit (high).
        if (serial_dat_i) m1_next_state <= m1_measure_2;
        // If it is not high keep waiting...
        // (Put detection of measurement overflow in here if necessary...)
        else m1_next_state <= m1_measure_1;
      end

    m1_measure_2 :
      begin
        measure <= 1'b1;
        // Check using mid bit time, to make sure serial line is still high...
        // (At this time, "mid_bit_count" is simply CLOCK_FACTOR_PP>>1 clk_i's.)
        if (mid_bit_count && serial_dat_i) m1_next_state <= m1_measure_3;
        // If it is not high, then it must have been a "glitch"...
        else if (mid_bit_count && ~serial_dat_i) m1_next_state <= m1_idle;
        else m1_next_state <= m1_measure_2;
      end

    m1_measure_3 :
      begin
        measure <= 1'b1;
        // Look for end of measurement interval (low)
        if (!serial_dat_i) m1_next_state <= m1_measure_4;
        // If it is not high keep waiting...
        // (Put detection of measurement overflow in here if necessary...)
        else m1_next_state <= m1_measure_3;
      end

    // This state outputs a reset pulse, to clear counters and store the
    // measurement from main_count.
    m1_measure_4 :
      begin
        clear_counters <= 1'b1; // Clears counters, stores measurement
        m1_next_state <= m1_verify_0;
      end

    m1_verify_0 :  // Wait for verify operations to finish
      begin
        verify <= 1'b1;
        if (verify_done) m1_next_state <= m1_verify_1;
        else m1_next_state <= m1_verify_0;
      end

    // NOTE: This "extra" state is needed because the character_miscompare
    //       information is not valid until 1 cycle after verify_done is
    //       active.
    m1_verify_1 :  // Checks for character miscompare
      begin
        if (character_miscompare) m1_next_state <= m1_verify_failed;
        else m1_next_state <= m1_run;
      end

    m1_verify_failed : // Resets counters on the way back to idle
      begin
        clear_counters <= 1'b1;
        m1_next_state <= m1_idle;
      end

    // This state is for successful verification results!
    // Since this is a single measurement unit, only reset can exit this
    // state.
    m1_run :       
      begin
        run <= 1'b1;
        m1_next_state <= m1_run;
      end

    default : m1_next_state <= m1_idle;
  endcase
end


assign auto_baud_locked_o = run;


endmodule

//`undef LOG2_MAX_CLOCK_FACTOR

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -