ai_abus.v 5.44 KB
 /************************************************************************\
 |                                                                        |
 |               Copyright (C) 1994, Silicon Graphics, Inc.               |
 |                                                                        |
 |  These coded instructions, statements, and computer programs  contain  |
 |  unpublished  proprietary  information of Silicon Graphics, Inc., and  |
 |  are protected by Federal copyright  law.  They  may not be disclosed  |
 |  to  third  parties  or copied or duplicated in any form, in whole or  |
 |  in part, without the prior written consent of Silicon Graphics, Inc.  |
 |                                                                        |
 \************************************************************************/

// $Id: ai_abus.v,v 1.1.1.1 2002/05/17 06:14:57 blythe Exp $

// modified 10/7/94 to reset on bit_rate = 0
// modified 10/10/94: changed (bit_rate == 0) to be a synchronous reset
// modified 12/07/94, inverted left-right signal, source clean-up
// modified 12/12/94: changed for even abus_word high and low times

//  The ai_abus module generates
//	the audio sample bit clock, abus_clk,
//	and the combined left right select and DAC clock, abus_wsel,
//    given the video dot clock and 2 ratios:
//      bit_rate is the divider ratio for 1/2 of the bit clock period,
//      and dac_rate is the divider ratio for the DAC clock.
//
//    32 bits of data need to be shifted out for each DAC sample.
//	16 bits left channel  - abus_wsel low,
//	16 bits right channel - abus_wsel high,
//	msb first.
//    34 clocks per sample are used because 
//      the DAC triggers on the clocked transitions of abus_wsel
//	AFTER the 16th and 32nd data clocks.
//
//    Serial data and abus_wsel are sampled by the DAC on
//	the rising edge of abus_clk.

module ai_abus(
	clk,
	reset_l,
	bit_rate,
	dac_rate,
	data_word,
	dac_cntr_out,
	abus_data,
	abus_clk,	
	abus_wsel );

  `include "ai.vh"

  input		clk;
  input		reset_l;	// reset low
  input [3:0]	bit_rate;	// 1/2 bit time
  input [DAC_RATE_SIZE-1:0] dac_rate;	// DAC sample time
  input [31:0]	data_word;	// audio data word 

  output [15:0]	dac_cntr_out; 	//   output for test only
  output	abus_data;	// bit data output
  output	abus_clk; 	// bit clock
  output	abus_wsel; 	// left right select and DAC clock

  reg   [DAC_RATE_SIZE-1:0] dac_cntr;
  reg   [DAC_RATE_SIZE-1:0] dac_cntr_decr;
  reg		abus_data;
  reg		abus_clk;
  reg		abus_wsel;

  reg   [5:0]	state;		// state register
  reg   [3:0]	bit_cntr;	// down counters
  reg   [5:0]	state_incr;
  reg   [3:0]	bit_cntr_decr;

  wire [15:0] dac_cntr_out;

  // counter test coverage outputs
  assign dac_cntr_out[15:DAC_RATE_SIZE+1] = 0;
  assign dac_cntr_out[DAC_RATE_SIZE:1]    = dac_cntr;
  assign dac_cntr_out[0]                  = state[0];

  // dac_clock free running counter

  always @( dac_cntr ) begin
    dac_cntr_decr = dac_cntr - 1;
  end

  always @(posedge clk or negedge reset_l) begin
    if ( reset_l == 0 ) begin
          dac_cntr	<= 0;		// reset
    end
    else begin
      if (bit_rate == 0) begin
	  dac_cntr	<= 0;		// soft reset
      end
      else begin
        if (dac_cntr != 0) begin
	  dac_cntr	<= dac_cntr_decr;	// decrement to zero
        end
        else begin	 		// and then reload
	  dac_cntr	<= { 1'b0, dac_rate[DAC_RATE_SIZE-1:1] };
	    // ignore lsb of dac_rate for compatibility
        end
      end
    end
  end

  // state machine to generate 34 bit clocks

  always @( state ) begin
    state_incr = state + 1;
  end

  always @( bit_cntr ) begin
    bit_cntr_decr = bit_cntr - 1;
  end

  always @(posedge clk or negedge reset_l) begin
    if ( reset_l == 0 ) begin
      state		<= 0;			// reset
      bit_cntr		<= 0;
    end
    else begin
      if ( dac_cntr == 0 ) begin		// on dac_cntr zero
	    state	<= 0;			// reset state
      end
      else begin
        if ( bit_cntr != 0 || bit_rate == 0  || state == 34 ) begin
	    state	<= state;		// hold
	end
	else begin
	    state	<= state_incr;		// inc state
	end
      end

      if ( bit_rate == 0 ) begin
          bit_cntr	<= 0;			// soft reset
      end
      else begin
        if ( bit_cntr == 0  || state == 34 ) begin
	  bit_cntr	<= bit_rate;		// hold bit clock
        end
        else begin
	  bit_cntr	<= bit_cntr_decr; 	// decr bit clock
        end
      end
    end	     // not reset
  end

  // generate outputs

  always @(posedge clk or negedge reset_l) begin
    if (reset_l == 0) begin
      abus_clk		<= 0;
      abus_wsel		<= 1;
    end
    else begin
      abus_clk 		<= state[0];		// bit clock = lsb of state

      begin
        if ( state == 31 && bit_cntr == 0 ) begin
	  // if( abus_wsel == 1 ) $display("lr low  %d",$time);
	  // if( abus_wsel == 0 ) $display("lr high %d",$time);
	  abus_wsel	<= !(abus_wsel);
        end
        else begin
	  abus_wsel	<= abus_wsel;
        end
      end
    end	     // not reset
  end

  always @(posedge clk or negedge reset_l) begin
    if (reset_l == 0) begin
        abus_data	<= 1'b0;		// data output low at reset
    end
    else begin
      if (bit_rate == 0) begin
        abus_data	<= 1'b0;
      end
      else begin
	if ( state[5] == 0 ) begin
	  if ( abus_wsel == 1 ) begin
            abus_data	<= data_word[ 31 - state[4:1] ]; // output mux L
	  end
	  else begin
	    abus_data	<= data_word[ 15 - state[4:1] ]; // output mux R
	  end
	end
	else begin
	    abus_data	<= abus_data;
	end
      end
    end
  end  // always

endmodule  // ai_abus

// eof