(Part 4 of this series is here: Part 4)
But before I begin, let me again acknowledge Dick Benson, W1QG. Dick is the father of this design, and although I've made some modifications to the FPGA logic, the underlying architecture and the vast majority of the Simulink implementation is Dick's.
Control Interface:
The Control Interface circuitry (also known as the Serial Interface, and sometimes even called the Command Interface by me) is the serial interface through which the FPGA can be controlled by an external processor, for example a PIC or an Arduino.
Let's call this external processor the Control Processor.
This Control Interface consists of 4 signals (plus a fifth, the Interrupt/Overload signal, which will be discussed later in this blog):
The serial data words are 32 bits long, and so 32 clocks are required to complete a word-transfer to or from the FPGA.
RFD identifies when the FPGA's Serial Interface circuitry is ready to receive (or send) the first bit of a thirty-two bit data word. It ensures that the FPGA's internal Control Interface circuitry and the external Control Processor remain in sync. (If they should get out of sync, the Control Processor can force the interface to reset using the FPGA's external nRST signal).
The thirty-two bit Cntrl_Data word sent to the FPGA is divided into two fields:
The 32-bit Cntrl_Data word is clocked into the FPGA MSB first. Therefore, the address bits are the last bits to arrive into the FPGA.
Upon reception of all 32 bits, the 26 bits representing the Data field will be automatically clocked into the FPGA register addressed by the 6-bit Address field.
A thirty-two bit data word, Serial_Out, is also sent from the FPGA to the Control Processor. This word contains information such as the revision of the FPGA's configuration code, Overload status, and the state of FPGA General-Purpose inputs.
Because there is only one 32-bit Serial_Out data word, then strictly speaking, no address is required. In fact, this word is clocked out simultaneously whenever any Cntrl_Data word is written to the FPGA. However, to allow the Control Processor to read the Serial_Out data word without also having to simultaneously write to an existing register, address 63 (0x3F) has been defined to be a dummy address with no writable register.
Therefore, to receive the Serial_Out data word without worry of updating an FPGA register, the Control Processor can simply write to address 63.
Unlike the Cntrl_Data word, which is clocked into the FPGA MSB first, the Serial_Out word is clocked out of the FPGA LSB first.
Both Cntrl_Clk and Cntrl_Data, as inputs into the FPGA, are sampled and synchronized within the FPGA to an internal clock of 10 MHz (80 MHz divided by 8). Therefore, the Control Processor should ensure that Cntrl_Clk runs at a slower clock rate so that its transitions can be detected by the FPGA.
One final note: Cntrl_Data is clocked into the FPGA on the rising edge of Cntrl_Clk. And Serial_Out output data will also change on the rising edge of Cntrl_Clk.
Let's look more closely at the Control Interface circuitry. It is contained within the "Serial_Interface1" subsystem of the Simulink Model. I have highlighted it below, in yellow.
Opening up the Serial_Interface1 subsystem, we see:
Let's look more closely at these subsystems. I will highlight each subsystem in turn...
Serial_In_Parallel_Out:
The Serial_In_Parallel_Out subsystem is highlighted below.
This subsystem receives the incoming Cntrl_Data serial data stream and converts it into parallel format. It also counts the serial bits as they arrive, and this same counter selects which bit of the 32-bit Serial_Out output word to present (as serial data) at the FPGA's Serial_Out pin.
Opening up Serial_In_Parallel_Out subsystem and the subsystems contained within it:
Notes:
Address Decode:
The Address Decode block is highlighted in yellow, below.
The Address Decode block decodes the 6 address bits contained within the 32 bit Cntrl_Data word and generates a Write Enable signal for each address.
General-Purpose Outputs:
The General Purpose Outputs block is highlighted in yellow, below.
The register in this block is loaded when its Write Enable, WR_GP_REG, is high. The 26-bit data field is divided into the following subfields:
Interrupt Generator:
The Interrupt Generator is highlighted in yellow, below:
The Interrupt Generator can generate an interrupt signal to interrupt the external Control Processor.
There are five possible interrupt sources. Four are the General Purpose FPGA inputs, and the fifth interrupt goes active upon a transition of any of five Overload conditions.
The five interrupts can be individually enabled or disabled. If enabled, any change in a signal's state (from high to low or low to high) will generate an interrupt.
If the Control Processor receives an interrupt, it should read the Interrupt Status via address 63 (data format is described later, below). At the completion of this read any interrupt that is set will be reset.
Parallel-to-Serial Output:
The Parallel-to-Serial block is highlighted below, in yellow:
This block creates the 32-bit Serial_Out serial data stream that is sent from the FPGA to the Control Processor.
This serial-data stream is sent to the Control Processor whenever the Control Processor writes to an FPGA register (note that a write to address 63 sends this stream to the Control Processor without an actual register being written to).
The 32-bit field of the Serial_Out word has the following subfields:
o Bits 7-0: FPGA Code Version (set by the user in the Top Level of the Simulink Model, and it is used to identify the revision of the FPGA code).
The Control Interface circuitry (also known as the Serial Interface, and sometimes even called the Command Interface by me) is the serial interface through which the FPGA can be controlled by an external processor, for example a PIC or an Arduino.
Let's call this external processor the Control Processor.
This Control Interface consists of 4 signals (plus a fifth, the Interrupt/Overload signal, which will be discussed later in this blog):
- Cntrl_Data (Serial Data, Input to FPGA)
- Serial_Out (Serial Data, Output from FPGA)
- Cntrl_Clk (Serial Clock, Input to FPGA)
- RFD (Request for Data, Output from FPGA)
Data is transferred serially between the FPGA and the Control Processor, and the Control Processor is the master of this data transfer, clocking the data synchronously via Cntrl_Clk.
The serial data words are 32 bits long, and so 32 clocks are required to complete a word-transfer to or from the FPGA.
RFD identifies when the FPGA's Serial Interface circuitry is ready to receive (or send) the first bit of a thirty-two bit data word. It ensures that the FPGA's internal Control Interface circuitry and the external Control Processor remain in sync. (If they should get out of sync, the Control Processor can force the interface to reset using the FPGA's external nRST signal).
The thirty-two bit Cntrl_Data word sent to the FPGA is divided into two fields:
- Address Field, 6 bits -- these are the 6 LSB's of the Cntrl_Data word.
- Data Field, 26 bits -- these are the 26 MSB's of the Cntrl_Data word.
The 32-bit Cntrl_Data word is clocked into the FPGA MSB first. Therefore, the address bits are the last bits to arrive into the FPGA.
Upon reception of all 32 bits, the 26 bits representing the Data field will be automatically clocked into the FPGA register addressed by the 6-bit Address field.
A thirty-two bit data word, Serial_Out, is also sent from the FPGA to the Control Processor. This word contains information such as the revision of the FPGA's configuration code, Overload status, and the state of FPGA General-Purpose inputs.
Because there is only one 32-bit Serial_Out data word, then strictly speaking, no address is required. In fact, this word is clocked out simultaneously whenever any Cntrl_Data word is written to the FPGA. However, to allow the Control Processor to read the Serial_Out data word without also having to simultaneously write to an existing register, address 63 (0x3F) has been defined to be a dummy address with no writable register.
Therefore, to receive the Serial_Out data word without worry of updating an FPGA register, the Control Processor can simply write to address 63.
Unlike the Cntrl_Data word, which is clocked into the FPGA MSB first, the Serial_Out word is clocked out of the FPGA LSB first.
Both Cntrl_Clk and Cntrl_Data, as inputs into the FPGA, are sampled and synchronized within the FPGA to an internal clock of 10 MHz (80 MHz divided by 8). Therefore, the Control Processor should ensure that Cntrl_Clk runs at a slower clock rate so that its transitions can be detected by the FPGA.
One final note: Cntrl_Data is clocked into the FPGA on the rising edge of Cntrl_Clk. And Serial_Out output data will also change on the rising edge of Cntrl_Clk.
Let's look more closely at the Control Interface circuitry. It is contained within the "Serial_Interface1" subsystem of the Simulink Model. I have highlighted it below, in yellow.
(Click on image to enlarge)
Opening up the Serial_Interface1 subsystem, we see:
(Click on image to enlarge)
Let's look more closely at these subsystems. I will highlight each subsystem in turn...
Serial_In_Parallel_Out:
The Serial_In_Parallel_Out subsystem is highlighted below.
(Click on image to enlarge)
This subsystem receives the incoming Cntrl_Data serial data stream and converts it into parallel format. It also counts the serial bits as they arrive, and this same counter selects which bit of the 32-bit Serial_Out output word to present (as serial data) at the FPGA's Serial_Out pin.
Opening up Serial_In_Parallel_Out subsystem and the subsystems contained within it:
(Click on image to enlarge)
(Click on image to enlarge)
(Click on image to enlarge)
(Click on image to enlarge)
Notes:
- The Valid bit goes high for one clock after all 32 bits of a data word have been clocked into (or out of) the FPGA. It is used to create the appropriate Write Enable to load the addressed FPGA register (see Address Decode block, below).
- Par_26 is the 26-bit Data field (in parallel format).
- Address_6 is the 6-bit address field.
- Index is a 5-bit value to select which bit of the 32-bit Serial_Out word should be inserted into the output serial data stream.
Address Decode:
The Address Decode block is highlighted in yellow, below.
(Click on image to enlarge)
The Address Decode block decodes the 6 address bits contained within the 32 bit Cntrl_Data word and generates a Write Enable signal for each address.
(Click on image to enlarge)
General-Purpose Outputs:
The General Purpose Outputs block is highlighted in yellow, below.
(Click on image to enlarge)
The register in this block is loaded when its Write Enable, WR_GP_REG, is high. The 26-bit data field is divided into the following subfields:
- Bits 11-0: DOUT_0to11: Output bits sent to FPGA General Purpose output pins. They can be used for driving external relays, etc.
- Bits 16-12: IRPT_EN0to4: Interrupt Enables which enable any of five possible interrupt inputs to generate an Interrupt to the Control Processor.
- Bit 17: P23_SEL: Selects if FPGA Pin 23 (an FPGA output, sent to the Control Processor) represents an Interrupt or an Overload condition.
(Click on image to enlarge)
Interrupt Generator:
The Interrupt Generator is highlighted in yellow, below:
(Click on image to enlarge)
The Interrupt Generator can generate an interrupt signal to interrupt the external Control Processor.
There are five possible interrupt sources. Four are the General Purpose FPGA inputs, and the fifth interrupt goes active upon a transition of any of five Overload conditions.
The five interrupts can be individually enabled or disabled. If enabled, any change in a signal's state (from high to low or low to high) will generate an interrupt.
If the Control Processor receives an interrupt, it should read the Interrupt Status via address 63 (data format is described later, below). At the completion of this read any interrupt that is set will be reset.
(Click on image to enlarge)
(Click on image to enlarge)
Parallel-to-Serial Output:
The Parallel-to-Serial block is highlighted below, in yellow:
(Click on image to enlarge)
This block creates the 32-bit Serial_Out serial data stream that is sent from the FPGA to the Control Processor.
This serial-data stream is sent to the Control Processor whenever the Control Processor writes to an FPGA register (note that a write to address 63 sends this stream to the Control Processor without an actual register being written to).
The 32-bit field of the Serial_Out word has the following subfields:
o Bits 7-0: FPGA Code Version (set by the user in the Top Level of the Simulink Model, and it is used to identify the revision of the FPGA code).
o Bits 11-8: Four General Purpose Inputs, to allow the Control Processor to monitor external signals via the FPGA.
o Bits 16-12: Five Interrupt-Status bits. Four Interrupts are generated by the four General Purpose Inputs, and the fifth is generated by any of the Overload bits within the FPGA.
o Bits 19-17: Not used (set to 0).
o Bits 24-20: State of the five Overload bits. These Overload bits are:
- Bit 20: ADC/DAC Overload
- Bit 21: Codec Overload
- Bit 22: AM Overmod
- Bit 23: CIC Overload
- Bit 24: DA Overload
o Bits 31-25: Not used (set to 0)
(Click on image to enlarge)
Pin 23:
The FPGA's pin 23 (called "P23 in the Simulink Model) is an output pin that can be considered a "fifth" signal of the Control Interface. Its circuitry is highlighted in yellow, below:
(Click on image to enlarge)
This pin can have two meanings:
1. If the P23_SEL signal from the GP_Outputs block is low, then Pin 23 simply represents an "NOR'ing" of the 5 Overload bits -- that is, if Pin 23 is low, then one (or more) of the five overload bits is high (i.e. in the state of overload).
2. If P23_SEL is high, then Pin 23 represents the Interrupt signal from the Interrupt_Generator block, and it is used to interrupt the Control Panel's processor.
The final Simulink FPGA SDR logic block to discuss is the Clock Divider, highlighted below, in yellow:
(Click on image to enlarge)
The Clock Divider simply divides down the 80 MHz clock to create three clocks that, driving FPGA output pins, can be used to clock external circuity, should the need arise. These three clocks are: 20 MHz, 10 MHz, and 5 MHz.
(Click on image to enlarge)
Dick originally added this circuitry so that he could create an external phase-locked loop to lock the radio's clock to an external frequency reference. Per Dick...
Since day 1, I have used the divide-by-sixteen that produces the 5MHz. The 80 MHz Crystal Oscillator that generates the FPGA clock is locked to a 5MHz TCXO using this signal.
The only thing I have not done is put in way to switch out the internal 5 MHz TCXO with an external 5 or 10 MHz Frequency Reference input from the back panel.
The TCXO is so good (a few Hz +/- at 28 MHz) the external reference is just not justified.
Background Notes:
SDR Notes: Weaver Modulation and Demodulation
SDR Notes: The Mixer Mathematics of Digital Down Conversion
Posts in this Series:
Part 1: Overview
Part 2: FPGA Modulation and Demodulation
Part 3: Interpolation and Decimation Filters
Part 5: Control Interface, Etc.
Standard Caveat:
I or Dick might have made a mistake in our designs, equations, schematics, models, etc. If anything looks confusing or wrong to you, please feel free to comment below or send me an email.
Also, I will note:
This design and any associated information is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1 comment:
Thanks so much for posting this series of articles. I have a Digilent Arty board that I hope to use as a platform for SDR development, so the descriptions of what you've done will be invaluable.
Post a Comment