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

📄 auto_baud_with_tracking.v

📁 This build is for developing a "binary-to-BCD" converter for use in // displaying numerals in base-
💻 V
📖 第 1 页 / 共 2 页
字号:


// 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 time (when the new candidate baud rate clock is being tested)
// 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.
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)
    begin
      if (main_count_rollover) main_count <= 0;
      else main_count <= main_count + 1;
    end
  end
end
// This is the "verify" baud clock signal... not the final output one.
assign main_count_rollover = (main_count == measurement);


// This is the BAUD counter.  Once a measurement has been verified, it is
// stored in "baud" and the signal "run" goes high.  From then on, this
// counter is allowed to run freely, advancing once each clk_i, but being
// reset when it reaches a total count of "baud" clock cycles.  This
// counter's reset signal is the output baud rate clock.
always @(posedge clk_i or posedge reset_i)
begin
  if (reset_i) baud_count <= 0;
  else // must have been clk_i edge
  begin
    // If running, advance freely
    if (run)
    begin
      if (baud_count_rollover) baud_count <= 0;
      else baud_count <= baud_count + 1;
    end
  end
end
assign baud_count_rollover = (baud_count == baud);

// 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 for the baud clock
// generated during verify, but a different register holds the actual value
// being used to generate output.
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 the BAUD storage latch.  The final verified time count
// from the "measurement" register is stored in this register after a good
// verify.  The value stored in this latch is used in conjunction with
// baud_count to produce the baud clock which is sent to the output.
always @(posedge clk_i or posedge reset_i)
begin
  // Set to all ones during reset (asynchronous).
  if (reset_i) baud <= -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 (verify_good) baud <= measurement;
end

// This is a flip-flop used to keep track of whether the unit is producing
// a baud clock or not.  Initially following reset, there is no baud clock
// being produced.  But, once a single measurement is verified, then the
// clock is produced and tracking changes are made over time.  Thus, this
// bit goes high as a result of the first "verify_good" pulse, and it remains
// high forever, until the unit is reset.
always @(posedge clk_i or posedge reset_i)
begin
  if (reset_i) run <= 0;
  else  // Must have been a clock edge
  begin
    if (verify_good) run <= 1;
  end
end

assign baud_clk_o = baud_count_rollover;


// 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;
  verify_good <= 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 tracking unit, the "run" output is used as a pulse
    // to store the now verified rate.
    m1_run :       
      begin
        verify_good <= 1'b1;
        m1_next_state <= m1_idle;
      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 + -