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

📄 serial.v

📁 PS2的源代码VHDL语言实现
💻 V
📖 第 1 页 / 共 2 页
字号:

parameter m1_idle = 0;
parameter m1_start = 1;
parameter m1_shift = 3;
parameter m1_over_run = 2;
parameter m1_under_run = 4;
parameter m1_all_low = 5;
parameter m1_extra_1 = 6;
parameter m1_extra_2 = 7;
parameter m2_data_ready_flag = 1;
parameter m2_data_ready_ack = 0;


// I/O declarations
input clk; 
input rx_clk; 
input reset;
input rxd;
input read;

output [DATA_BITS_PP-1:0] data;
output data_ready;
output error_over_run;
output error_under_run;
output error_all_low;

reg [DATA_BITS_PP-1:0] data;
reg data_ready;
reg error_over_run;
reg error_under_run;
reg error_all_low;

// Local signal declarations
`define TOTAL_BITS START_BITS_PP + DATA_BITS_PP + STOP_BITS_PP

wire word_xfer_l;
wire mid_bit_l;
wire start_bit_l;
wire stop_bit_l;
wire all_low_l;

reg [3:0] intrabit_count_l;
reg [`TOTAL_BITS-1:0] q;
reg shifter_preset;
reg [2:0] m1_state;
reg [2:0] m1_next_state;
reg m2_state;
reg m2_next_state;


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

  always @(m1_state 
           or reset
           or rxd
           or mid_bit_l
           or all_low_l
           or start_bit_l
           or stop_bit_l
           )
  begin : m1_state_logic
  
    // Output signals are low unless set high in a state condition.
    shifter_preset <= 0;
    error_over_run <= 0;
    error_under_run <= 0;
    error_all_low <= 0;
  
    case (m1_state)

      m1_idle :
        begin
          shifter_preset <= 1'b1;
          if (~rxd) m1_next_state <= m1_start;
          else m1_next_state <= m1_idle;
        end

      m1_start :
        begin
          if (~rxd && mid_bit_l) m1_next_state <= m1_shift;
          else if (rxd && mid_bit_l) m1_next_state <= m1_under_run;
          else m1_next_state <= m1_start;
        end

      m1_shift :
        begin
          if (all_low_l) m1_next_state <= m1_all_low;
          else if (~start_bit_l && ~stop_bit_l) m1_next_state <= m1_over_run;
          else if (~start_bit_l && stop_bit_l) m1_next_state <= m1_idle;
          else m1_next_state <= m1_shift;
        end

      m1_over_run :
        begin
          error_over_run <= 1;
          shifter_preset <= 1'b1;
          if (reset) m1_next_state <= m1_idle;
          else m1_next_state <= m1_over_run;
        end
      
      m1_under_run :
        begin
          error_under_run <= 1;
          shifter_preset <= 1'b1;
          if (reset) m1_next_state <= m1_idle;
          else m1_next_state <= m1_under_run;
        end
        
      m1_all_low :
        begin
          error_all_low <= 1;
          shifter_preset <= 1'b1;
          if (reset) m1_next_state <= m1_idle;
          else m1_next_state <= m1_all_low;
        end
        
      default : m1_next_state <= m1_idle;
    endcase 
  end 
  assign word_xfer_l = ((m1_state == m1_shift) && ~start_bit_l && stop_bit_l);

  // State register
  always @(posedge clk)
  begin : m2_state_register
    if (reset) m2_state <= m2_data_ready_ack;
    else m2_state <= m2_next_state;
  end 

  // State transition logic
  always @(m2_state or word_xfer_l or read)
  begin : m2_state_logic
    case (m2_state)
      m2_data_ready_ack:
            begin
              data_ready <= 1'b0;
              if (word_xfer_l) m2_next_state <= m2_data_ready_flag;
              else m2_next_state <= m2_data_ready_ack;
            end
      m2_data_ready_flag:
            begin
              data_ready <= 1'b1;
              if (read) m2_next_state <= m2_data_ready_ack;
              else m2_next_state <= m2_data_ready_flag;
            end
      default : m2_next_state <= m2_data_ready_ack;
    endcase 
  end 

  // This counts within a bit-time.
  always @(posedge clk)
  begin
    if (shifter_preset) intrabit_count_l <= 0;
    else if (rx_clk)
    begin
      if (intrabit_count_l == (CLOCK_FACTOR_PP-1)) intrabit_count_l <= 0;
      else intrabit_count_l <= intrabit_count_l + 1;
    end
  end
  // This signal gets one "rx_clk" at the middle of the bit time.
  assign mid_bit_l = ((intrabit_count_l==(CLOCK_FACTOR_PP / 2)) && rx_clk);

  // This is the shift register
  always @(posedge clk)
  begin : rxd_shifter
    if (shifter_preset) q <= -1; // Set to all ones.
    else if (mid_bit_l) q <= {rxd,q[`TOTAL_BITS-1:1]};
  end
  // Note: The definitions of "start_bit_l" and "stop_bit_l" could
  //       well be updated to include _all_ of the start and stop bits.
  assign start_bit_l = q[0];
  assign stop_bit_l = q[`TOTAL_BITS-1];
  assign all_low_l = ~(| q); // Bit-wise or of the entire shift register


  // This is the output buffer
  always @(posedge clk)
  begin : rxd_output
    if (reset) data <= 0;
    else if (word_xfer_l) 
      data <= q[START_BITS_PP+DATA_BITS_PP-1:START_BITS_PP];
  end

endmodule

//`undef TOTAL_BITS


//-----------------------------------------
// This block takes care of framing up an RS232 output word,
// and sending it out the "txd" line in a serial fashion.
// The user is responsible for providing appropriate clk
// and clock enable (tx_clk) to achieve the desired Baudot interval
// (a new bit is transmitted each (tx_clk/clock_factor) pulses)
// (NOTE: the state machine operates at "clock_factor" times the
//   desired BAUD rate.  Set it to anything between 2 and 16,
//   inclusive.  It may be useful to adjust the clock_factor in order to
//   generate good BAUD clocks from odd Fclk frequencies on your board.)
// A load operation may be performed at any time.  If two consecutive loads
// are performed while the transmitter is operating, the second load will
// overwrite the contents of the first load operation.
// Each time the "load_request" line becomes high the unit has finished
// sending its previous character.  One clk after the rising edge of
// "load_request", the tx shift register is loaded with a new character from
// the holding buffer.  The holding buffer may also be loaded at this time,
// that is, on the first clk following the assertion of "load_request"
//
// Once the new data is loaded, the "load_request" line will drop low again,
// acknowledging receipt of the next character to be transmitted.
//
// If the "load_request" line is tied to "load," the unit will send
// data characters continuously, with no gaps in between transmissions.
//
// Note that support is not provided for 1.5 stop bits, only integral
// numbers of stop bits are allowed.  A selection of more than 2 for
// number of stop bits will still work fine, it will simply introduce
// a delay between characters being transmitted, although the length
// of the transmitter shift register will also grow to include one
// stage for each stop bit requested...

`timescale 1ns/100ps
module rs232tx (
                clk,
                tx_clk,
                reset,
                load,
                data,
                load_request,
                txd
                );

  parameter START_BITS_PP  = 1;
  parameter DATA_BITS_PP  = 8;
  parameter STOP_BITS_PP  = 1;
  parameter CLOCK_FACTOR_PP  = 16;
  parameter TX_BIT_COUNT_BITS_PP = 4;  // = ceil(log(total_bits)/log(2)));

// State encodings, provided as parameters
// for flexibility to the one instantiating the module
  parameter m1_idle = 0;
  parameter m1_waiting = 1;
  parameter m1_sending = 3;
  parameter m1_sending_last_bit = 2;


// I/O declarations
  input clk;
  input tx_clk;
  input reset;
  input load;
  input[DATA_BITS_PP-1:0] data;
  output load_request;
  output txd;

  reg load_request;

// local signals
  `define TOTAL_BITS START_BITS_PP + DATA_BITS_PP + STOP_BITS_PP
  
  reg [`TOTAL_BITS-1:0] q;                 // Actual tx shifter
  reg [DATA_BITS_PP-1:0] data_in_waiting;  // Data waiting to be sent next
  reg [TX_BIT_COUNT_BITS_PP-1:0] tx_bit_count_l;
  reg [3:0] prescaler_count_l;
  reg [1:0] m1_state;
  reg [1:0] m1_next_state;

  wire [`TOTAL_BITS-1:0] tx_word = {{STOP_BITS_PP{1'b1}},
                                   data_in_waiting,
                                   {START_BITS_PP{1'b0}}};
  wire begin_last_bit;
  wire start_sending;
  wire tx_clk_1x;


  // This is a prescaler to produce the actual transmit clock.
  always @(posedge clk)
  begin
    if (reset) prescaler_count_l <= 0;
    else if (tx_clk)
    begin
      if (prescaler_count_l == (CLOCK_FACTOR_PP-1)) prescaler_count_l <= 0;
      else prescaler_count_l <= prescaler_count_l + 1;
    end
  end
  assign tx_clk_1x = ((prescaler_count_l == (CLOCK_FACTOR_PP-1) ) && tx_clk);

  // This is the transmitted bit counter
  always @(posedge clk)
  begin
    if (start_sending) tx_bit_count_l <= 0;
    else if (tx_clk_1x)
    begin
      if (tx_bit_count_l == (`TOTAL_BITS-2)) tx_bit_count_l <= 0;
      else tx_bit_count_l <= tx_bit_count_l + 1;
    end
  end
  assign begin_last_bit = ((tx_bit_count_l == (`TOTAL_BITS-2) ) && tx_clk_1x);

  // This is the holding register.  It can be reloaded at any time.
  always @(posedge clk)
  begin
    if (load) data_in_waiting <= data;
  end

  assign start_sending = ((tx_clk_1x && load_request && load)
                           ||(tx_clk_1x && (m1_state==m1_waiting)));


  // This state machine handles sending out the transmit data
  
  // State register.
  always @(posedge clk)
  begin : state_register
    if (reset) m1_state <= m1_idle;
    else m1_state <= m1_next_state;
  end

  // State transition logic
  always @(m1_state or tx_clk_1x or load or begin_last_bit)
  begin : state_logic
    // Signal is low unless changed in a state condition.
    load_request <= 0;
    case (m1_state)
      m1_idle :
            begin
              load_request <= 1;
              if (tx_clk_1x && load) m1_next_state <= m1_sending;
              else if (load) m1_next_state <= m1_waiting;
              else m1_next_state <= m1_idle;
            end
      m1_waiting :
            begin
              if (tx_clk_1x) m1_next_state <= m1_sending;
              else m1_next_state <= m1_waiting;
            end
      m1_sending :
            begin
              if (begin_last_bit) m1_next_state <= m1_sending_last_bit;
              else m1_next_state <= m1_sending;
            end
      m1_sending_last_bit :
            begin
              load_request <= tx_clk_1x;
              if (load & tx_clk_1x) m1_next_state <= m1_sending;
              else if (tx_clk_1x) m1_next_state <= m1_idle;
              else m1_next_state <= m1_sending_last_bit;
            end
      default :
            begin
              m1_next_state <= m1_idle;
            end
    endcase
  end


  // This is the transmit shifter
  always @(posedge clk)
  begin : txd_shifter
    if (reset) q <= -1;  // set to all ones
    else if (start_sending) q <= tx_word;
    else if (tx_clk_1x) q <= {1'b1,q[`TOTAL_BITS-1:1]};
  end
  
  assign txd = q[0];

endmodule

//`undef TOTAL_BITS

⌨️ 快捷键说明

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