Backward Up Forward

4.1 Hardware Simulation

The example design implements the logic required to allow the flow of two data streams between a 16-bit processor and a 16-bit codec via a pair of FIFOs implemented using SRAM. This design has been nicknamed "codec_on_a_stick", as the design provides a simple interface between the processor and the codec.

Figure 4.1: System Components

The design converts data streams between the serial format accepted by the codec and the parallel format accepted by the processor. It also provides intermediate data buffering. The design supports two data channels, a transmit channel and a receive channel, named from the processors point of view. The transmit channel is the path by which data flows from the processor to the codec. The receive channel is the path by which data flows from the codec to the processor. To send data via the transmit channel, the processor writes data words into a transmit FIFO. This data is subsequently read by the on-chip control logic which converts it into a serial format and transmits it over a serial bus to the codec. To receive data via the receive channel, serial data words sent by the codec are read by the control logic which converts them into a parallel format before writing them into the receive FIFO. The processor then reads the receive channel data from this FIFO. In both cases, rather than continuously polling the FIFOs state, the processor can elect to receive an interrupt whenever a FIFO reaches a given state.

4.1.1 Testbench

Simulation: tb_codec_on_a_stick
Module: tb
Design Under Test: codec_on_a_stick
Clock Domains: clock All signals switch on posedge "clock" unless stated otherwise.
Reset Lines: resetj asynchronous, active low
SMI Models: processor(processor) 16 bit processor connected to the processor bus of the ASIC.
codec(codec) Serial codec connected to the serial codec bus of the ASIC.
SRAM(transmit_fifo) Memory used to implement the transmit FIFO.
SRAM(receive_fifo) Memory used to implement the receive FIFO.

The hardware simulation testbench connects the instances of the processor and codec models to the ASIC, generates clock and reset, and pulls up the bi-directional data bus.

Figure 4.1.1: System Connectivity

Source: tb_codec_on_a_stick.v

The testbench generates the chip select for the "codec_on_a_stick" ASIC by decoding the address bus. The logic maps the "codec_on_a_stick" ASIC registers to processor addresses 0 to 3.

The clock and reset signals are generated by a module called "test_services", which also implements the simulation exit procedure. The dump file "tb_codec_on_a_stick.dmp" used to view signals. This file is flushed by the "test_services" module before the simulation exits so that the last cycles of the simulation will appear in the dump file. This is particularly important as tests often exit just after a simulation error has occurred, so the final cycles may contain vital debugging information.

4.1.2 Test Services

Module: test_services
Parameter: HALF_PERIOD Duration of half the clock period in # time.
RESET_TIME Duration of active (low) reset in # time.
Clock Domains: clock All signals switch on posedge "clock" unless stated otherwise.
Outputs: clock Clock signal.
resetj Active low asynchronous reset signal.

This module generates a clock and a reset signal. The module also implements the simulation exit procedure which must occur once (and only once) in every SMI simulation. Control-C is trapped by SMI.

Source: test_services.v

4.1.3 ASIC Implementation

Module: codec_on_a_stick
Clock Domains: clock All signals switch on posedge "clock" unless stated otherwise.
Inputs: clock Clock signal.
resetj Active low asynchronous reset signal.
Processor Bus
Inputs: up_pi_cs Chip select signal. If this signal is not asserted, the read and write command signals are ignored.
up_pi_addr[2] Address bus. Stable during bus operations.
up_pi_write Write command. Asserted during bus write operations.
up_pi_read Read command. Asserted during bus read operations.
Inouts: up_pi_data[16] Data bus, defaults to input. Stable input during bus write operations. Stable output during ready cycle of bus read operation.
Outputs: pi_up_ready Ready signal. Asserted to acknowledge completion of the current bus operation.
pi_up_int Interrupt. When asserted, the processor to jumps to an interrupt service routine.
Serial Codec Bus
Outputs: ci_sc_clock Serial clock. (Equal to "clock").
ci_sc_sync Serial synchronization pulse. Serial data transfers begin one clock after this pulse is asserted.
ci_sc_data Serial data output. Used to transmit data from the transmit FIFO. Data is sent MSB to LSB beginning one clock after the synchronization pulse (ci_sc_sync) is asserted.
Inputs: sc_ci_data Serial data input. Used to receive data for storage in the receive FIFO. Data is sent MSB to LSB beginning one clock after the synchronization pulse (ci_sc_sync) is asserted.

The ASIC connects to a 16-bit processor via a processor bus and connects to a 16-bit codec via a serial codec bus. The ASIC also requires two additional inputs, a clock signal and an active low reset signal.

Figure 4.1.3: Inside the "codec_on_a_stick" ASIC

Figure 4.1.3 shows the blocks and signals within the "codec_on_a_stick" ASIC core. Note that clock, reset and bus widths are not shown. This module connects the four main functional units; the processor interface, the codec interface, the transmit and receive FIFOs, and provides bi-directional control for the processor data bus. Each blocks and external bus has been given a two letter code. The following two letter identification codes have been used:

Code Block/Model
up Processor Model
pi Processor Interface Unit
tf Transmit FIFO
rf Receive FIFO
ci Codec Interface Unit
sc Serial Codec Model

Signals connecting the blocks and external busses are named by concatenating the source and destination codes with a simple descriptive word.

Typically the core would be embedded in a pad ring to complete the design, in this example the pad ring has been omitted.

Source: codec_on_a_stick.v

4.1.4 Processor Interface

Module: processor_interface
Clock Domains: clock All signals switch on posedge "clock" unless stated otherwise.
Inputs: clock Clock signal.
resetj Active low asynchronous reset signal.
Processor Bus
Inputs: up_pi_cs Chip select signal. If this signal is not asserted, the read and write command signals are ignored.
up_pi_addr[2] Address bus. Stable during bus operations.
up_pi_write Write command. Asserted during bus write operations.
up_pi_read Read command. Asserted during bus read operations.
up_pi_data[16] Data bus. Stable during bus write operations.
Outputs: pi_up_data[16] Data bus. Stable during ready cycle of bus read operation.
pi_up_ready Ready signal. Asserted to acknowledge completion of the current bus operation.
pi_up_int Interrupt. When asserted, the processor to jumps to an interrupt service routine.
Transmit FIFO Interface
Outputs: pi_tf_write Indicates that data (pi_up_data) should be written to the transmit FIFO. The signal is asserted until one clock cycle after the FIFO acknowledges that the write has been performed (by asserting tf_pi_ready).
pi_tf_data[16] Data written to the transmit FIFO when pi_tf_write is asserted.
Inputs: tf_pi_size[7] The number of free words in the transmit FIFO.
tf_pi_ready Pulsed when the write operation has completed.
Receive FIFO Interface
Outputs: pi_rf_read Indicates that data (rf_pi_data) should be read from the receive FIFO. The signal is asserted until one clock cycle after the FIFO acknowledges that the read has been performed (by asserting rf_pi_ready).
Inputs: rf_pi_data[16] Data read from the receive FIFO when pi_rf_read is asserted.
rf_pi_size[7] The number of data words in the receive FIFO.
rf_pi_ready Pulsed when the read operation has completed.
Channel Control Bus
Inputs: pi_ci_enable[2] Enable serial transmit (bit 0) and receive (bit 1). These signals are independently sampled in word boundaries. If neither bit is set, the codec interface will not generate a serial sync pulse.

The processor interface unit has four main interfaces; a processor bus, a transmit FIFO interface, a receive FIFO interface and a channel control bus. The module implements four programmable I/O registers accessible via the processor bus. The processor uses these registers to transfer data to and from the FIFOs and to control the operation of the ASIC as a whole.

The processor interface unit also interfaces to both the transmit and receive FIFOs. The module converts processor operations on the "Data" register into data read and write operations on the receive and transmit FIFOs respectively. These read and write operations occur via the FIFO interfaces. FIFO access is not guaranteed, so a ready signal is returned by the FIFO to indicate when a FIFO operation has successfully completed. The processor interface unit automatically extends the processor I/O bus operation to cope with any delay accessing the FIFOs.

The processor interface unit generates two control signals used by the codec interface unit; a transmit enable and a receive enable signal. These signals control the flow of data between the FIFOs and the serial codec. Note that the enable signals do not operate on a cycle by cycle basis; a channel may temporarily continue to transfer data after the enable signal has been reset.

The processor interface unit can also assert an interrupt signal to interrupt the processor when the appropriate conditions have occurred and interrupts are enabled.

Name Off. Field Bits R/W Description
Data 0x00 15:0 R/W Write data to the transmit FIFO. Read data from the receive FIFO.
Level 0x01 13:0 R/W Level is compared with the transmit and receive Size fields to generate an interrupt.
Transmit 0x02 Enable 15 R/W Enable the serial transmit channel.
Interrupt 14 R/W Generate an interrupt when Size>Level.
Size 13:0 R Number of free words in the transmit FIFO.
Receive 0x03 Enable 15 R/W Enable the serial receive channel.
Interrupt 14 R/W Generate an interrupt when Size>Level.
Size 13:0 R Number of data words in the receive FIFO.

The registers supported by the processor interface unit and their fields are declared and defined in the files "cos.h" and "cos.cc" respectively.

To set up a data transmission stream, the processor begins by writing data to the transmit FIFO in order to ensure that the FIFO does not immediately underflow when the serial transmit channel is enabled. To do this, the processor writes data samples to the "Data" register. The processor can enable serial transmission by setting the "Enable" bit of the "Transmit" register. Serial data will now be transmitted to the Codec from the transmit FIFO, which slowly drains. To prevent FIFO underflow, the processor must periodically re-supply the transmit FIFO with new data. The processor can monitor the number of data words remaining in the FIFO by reading the "Size" field of the "Transmit" register and subtracting the number returned from the FIFO size. The processor can either poll this register on a regular basis or program the chip to generate an interrupt whenever the FIFO contains less than a specified number of samples. The level at which interrupts are generated is specified by writing the number of samples to the "Level" register. Interrupts are enabled by setting the "Interrupt" field of the "Transmit" register. From that point on, the processor will be interrupted whenever the contents of the transmit FIFO fall below the programmed level. Whenever the processor receives an interrupt, it should read the "Size" field of "Transmit". It can then ensure that the transmit FIFO caused the interrupt, and also to take note of how many new samples may be written to the FIFO. The interrupt service routine is expected to either write enough samples to clear the interrupt condition or to disable the interrupt mechanism.

The process of receiving data is very similar to the process or transmitting it. In this case, the processor begins by enabling the serial receiver after ensuring that the receive FIFO is empty. The processor may need to read and discard any data currently in the FIFO. The receive FIFO then slowly fills as data is read from the codec. The processor must then either poll the FIFO status or enable interrupts using a method similar to that used for the transmission channel. The procedure uses "Receive" rather than "Transmit" and reads rather than writes new data.

Data transmission is terminated when the transmission channel is disabled and the last sample has been read from the FIFO. The codec interface will continue to transmit data in the FIFO despite that fact that the "Enable" bit of the "Transmit" register has been reset. The codec interface will not add new data into the receive FIFO after "Enable" bit of the "Receive" register has been reset.

Source: processor_interface.v
cos.h
cos.cc

4.1.5 Transmit FIFO

Module: transmit_fifo
Parameter: SIZE Sets the number of words stored by the FIFO to 2^SIZE.
WIDTH The bit width of the words stored by the FIFO.
Clock Domains: clock All signals switch on posedge "clock" unless stated otherwise.
Inputs: clock Clock signal.
resetj Active low asynchronous reset signal.
Write Interface
Inputs: pi_tf_write Indicates that data (pi_tf_data) should be written to the transmit FIFO. The signal is asserted until one clock cycle after the FIFO acknowledges that the write has been performed (by asserting tf_pi_ready).
pi_tf_data[16] Data written to the transmit FIFO when The write operation has completed.
Outputs: tf_pi_size[7] The number of free words in the transmit FIFO.
tf_pi_ready Pulsed when the write operation has completed.
Read Interface
Inputs: ci_rf_read Indicates that data (tf_ci_data) has been read from the transmit FIFO.
Outputs: tf_ci_data[16] Data read from the transmit FIFO when ci_rf_read is asserted.

The transmit FIFO interfaces to both the processor and the codec interface units. The processor interface writes data into the transmit FIFO which is subsequently read by the codec interface. The codec interface is given priority over the processor interface should both units request a data transfer with at the same time.

The FIFO is implemented using a dedicated SRAM. Two independent pointers are used to address SRAM data for read and write operations. If the transmit FIFO is written to when full, the ready signal will remain low until space is available. Data read from the transmit FIFO when empty is invalid.

Source: transmit_fifo.v

4.1.6 Receive FIFO

Module: receive_fifo
Parameter: SIZE Sets the number of words stored by the FIFO to 2^SIZE.
WIDTH The bit width of the words stored by the FIFO.
Clock Domains: clock All signals switch on posedge "clock" unless stated otherwise.
Inputs: clock Clock signal.
resetj Active low asynchronous reset signal.
Read Interface
Inputs: pi_rf_read Indicates that data (rf_pi_data) should be read from the receive FIFO. The signal is asserted until one clock cycle after the FIFO acknowledges that the read has been performed (by asserting rf_pi_ready).
Outputs: rf_pi_data[16] Data read from the receive FIFO when the read operation has completed.
rf_pi_size[7] The number of data words in the receive FIFO.
rf_pi_ready Pulsed when the read operation has completed.
Write Interface
Inputs: ci_rf_write Indicates that data (ci_rf_data) should be written to the receive FIFO.
ci_rf_data[16] Data to be written to the receive FIFO when ci_rf_write is asserted.

The receive FIFO interfaces to both the processor and the codec interface units. The codec interface writes data into the receive FIFO which is subsequently read by the processor interface. The codec interface is given priority over the processor interface should both units request a data transfer at the same time.

The FIFO is implemented using a dedicated SRAM. Two independent pointers are used to address SRAM data for read and write operations. If the receive FIFO is read when empty, the ready signal will remain low until data has been written to the FIFO. Data written to the receive FIFO when full will be lost.

Source: receive_fifo.h

4.1.7 Codec Interface

Module: codec_interface
Clock Domains: clock All signals switch on posedge "clock" unless stated otherwise.
Inputs: clock Clock signal.
resetj Active low asynchronous reset signal.
Channel Control Bus
Inputs: ci_rf_write Indicates that data (ci_rf_data) should be written to the receive FIFO.
Transmit FIFO Interface
Outputs: ci_tf_read Indicates that the transmit FIFO data (tf_ci_data) has been read.
Inputs: tf_ci_data[16] Data from the transmit FIFO.
Receive FIFO Interface
Outputs: ci_rf_write Indicates that data (ci_rf_data) should be written to the receive FIFO.
ci_rf_data[16] Data to be written to the receive FIFO when ci_rf_write is asserted.
Serial Codec Bus
Outputs: ci_sc_clock Serial clock. (Equal to "clock").
ci_sc_sync Serial synchronization pulse. Serial data transfers begin one clock after this pulse is asserted.
ci_sc_data Serial data output. Used to transmit data from the transmit FIFO. Data is sent MSB to LSB beginning one clock after the synchronization pulse (ci_sc_sync) is asserted.
Inputs: sc_ci_data Serial data input. Used to receive data for storage in the receive FIFO. Data is sent MSB to LSB beginning one clock after the synchronization pulse (ci_sc_sync) is asserted.

The codec interface unit has four main interfaces; transmit and receive FIFO interfaces, a serial codec bus, and a channel control bus. The module transfers a stream of data read from the transmit FIFO via the transmit FIFO interface to a serial codec via the serial codec bus. The module also transfers a stream of data read from a serial codec via the serial codec bus to a receive FIFO via the receive FIFO interface. These transfers, which can operate concurrently, are enabled or disabled via the channel control bus. The serial codec bus is typically connected to a serial ADC/DAC codec that is receiving and transmitting data words periodically. It should be noted that data is read from the transmit FIFO without checking that the FIFO contains data to be read. Similarly, the data is written to the receive FIFO without checking that the FIFO has free space.

Source: codec_interface.v

4.2 Test Process

The codec_on_a_stick ASIC is tested by transmitting a small sequence of data words from a processor model to the transmit channel of a serial codec model, and by transmitting a small sequence of data words from receive channel of a serial codec model to the processor model. The data streams are checked to ensure that the transfer was successful.

Source: tb_codec_on_a_stick.cc

4.2.1 TB_Values Class

This class is used to store two sequences of data. The read sequence is initialized at the beginning of the simulation and is read over the course of the simulation. The write sequence is initialized empty at the beginning of the simulation and is written over the course of the simulation. If the read sequence is transfered without error by the design under test and then written into the write sequence, at the end of the simulation the two sequences should be identical.

The class provides methods for initializing the read sequence, reading and writing data, and comparing the final sequences.

Source: tb_values.h
tb_values.cc

4.2.2 TB_Codec Class

This class extends a simple SMI model of a serial codec. This definition is extended by providing methods that write and read channel data to and from storage objects. There are two storage objects, one for read (ADC) and one for write (DAC) channel data. Data is transfered between the model and these storage objects as the codec model receives or transmits serial data. The storage objects hold fixed length arrays of data, so it is only possible to read or write a fixed number of times to an object. If this limit is exceeded, writes are ignored and reads return 0.

Source: tb_codec.h
tb_codec.cc

4.2.3 TB_Processor Class

This class extends a simple SMI model of a processor. This definition is extended by providing methods that write and read channel data to and from storage objects. There are two storage objects, one for read (ADC) and one for write (DAC) channel data. Data is transfered between the model and these storage objects as the processor model receives or transmits data. The processor transfers channel data to and from the ASIC via programmable I/O i.e. by reading and writing the ASIC registers. The data flow control is interrupt driven. The ASIC generates an interrupt if data needs to be transfered. The class provides an interrupt service routine that performs all data transfers.

Source: tb_processor.h
tb_processor.cc

Backward Up Forward
© Copyright 2000-2001 Adrian Lewis