{"id":215,"date":"2012-06-20T13:51:24","date_gmt":"2012-06-20T13:51:24","guid":{"rendered":"http:\/\/Ascenten.net\/tech-notes\/?p=215"},"modified":"2018-10-26T12:51:08","modified_gmt":"2018-10-26T12:51:08","slug":"fpga-bridge","status":"publish","type":"post","link":"https:\/\/ascenten.net\/tech-notes\/fpga-bridge\/","title":{"rendered":"FPGA Bridge"},"content":{"rendered":"<h2><strong>FPGA as a Bridge between 400 MSPS ADC and 10 MHz Throughput DSP<\/strong><\/h2>\n<p>&nbsp;<\/p>\n<p>When we talk of precision instrumentation, we are looking at a system that can manage highly complex math-intensive tasks, since the data collected from physical sensors need a complex degree of calculations to be measured. Although a DSP is well suited for extremely complex math-intensive tasks, it cannot process high sampling rate applications due to its serial architecture.<\/p>\n<p>&nbsp;<\/p>\n<p>ASIC does meet all the constraints of digital signal processing, however, it lacks flexibility and requires long design cycles. FPGA overcomes the disadvantages of ASIC and DSP with flexibility, time-to-market, risk-mitigation and lower system costs. <span class=\"GINGER_SOFATWARE_correct\">FPGA<\/span> \u00a0is ideal for implementing data formatting, timing, and specialized glue logic needed to connect real-time peripherals like modems, A\/D converters and digital receivers to programmable processors.<\/p>\n<p>&nbsp;<\/p>\n<p>Now what exactly is an FPGA Bridge and why is it an important design <span class=\"GINGER_SOFATWARE_correct\">aid<\/span>? To put this case in point, let me elaborate a design challenge I recently encountered while trying to interface an ADS5474EVM ADC Board and a TMS320C6455 DSK DSP Kit. The\u00a0DSP required data from an analog sensor for processing. It activated the sensor by providing a capture pulse to it. The sensed analog data was digitized by <span class=\"GINGER_SOFATWARE_correct\">ADS5474EVM ADC Board<\/span> at 400 MSPS rate. TMS320C6455 DSK DSP Kit which required this digitized data from ADC for further processing was not able to sample the incoming data at such a high rate. So a need arose to implement a bridge circuit, that could sample data at 400 MSPS and store data equivalent to 20 ms (approx. 8 million samples) from the captured signal. The FPGA Bridge was designed to provide <span class=\"GINGER_SOFATWARE_correct\">seamless interface<\/span> between <span class=\"GINGER_SOFATWARE_correct\">ADS5474EVM ADC Board<\/span> and TMS320C6455 DSK DSP Kit.\u00a0The FPGA bridge was a proof of concept that data at 400MSPS from ADC can be sampled at 200 MHz DDR rate by a Spartan 3a DSP (maximum operating frequency is 250 MHz), suitably stored and provided to <span class=\"GINGER_SOFATWARE_correct\">DSP processor<\/span> for further processing.<\/p>\n<p>&nbsp;<\/p>\n<h2><strong>Features Implemented in FPGA Bridge<\/strong><\/h2>\n<p>&nbsp;<\/p>\n<ul class=\"list\">\n<li>Sampling of 14 data bits + 1 Over <span class=\"GINGER_SOFATWARE_correct\">Range<\/span> (OVR) bit at 400 MSPS at double data rate (DDR) of Data Ready (DRY) signal.<\/li>\n<li>32 bit Asynchronous EMIF interface with TI-DSP.<\/li>\n<li>To collect data from ADC on request from TI-DSP at 400MSPS (200MHz DDR rate) and transfer it to DDR2 memory<\/li>\n<li>Designed to store <span class=\"GINGER_SOFATWARE_correct\">maximum<\/span> of 40 <span class=\"GINGER_SOFATWARE_noSuggestion GINGER_SOFATWARE_correct\">msec<\/span> (approximately 16 million samples) of ADC data to DDR2 memory.<\/li>\n<li>Data stored in the DDR2 memory passed by FPGA <span class=\"GINGER_SOFATWARE_correct\">to<\/span> DSP.<\/li>\n<li>Clock domain crossing handled between ADC interface operating at 200 MHz and <span class=\"GINGER_SOFATWARE_correct\">rest<\/span> logic operating at 125 MHz.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h2><strong>Design Flow<\/strong><\/h2>\n<p>&nbsp;<\/p>\n<ul class=\"list\">\n<li>DSP acts as master and maintains the communication between ADC, FPGA and itself.<\/li>\n<li><span class=\"GINGER_SOFATWARE_correct\">FPGA<\/span> has dedicated 5 write only and 2 read only registers. DSP controls the whole data transfer process by providing appropriate address writes and reads to these control registers thus indicating the start, stop and no of samples to be captured of maximum 40 ms.<\/li>\n<li>On detection of synchronized hard start capture and soft start capture from DSP, FPGA starts sampling data from ADC.<\/li>\n<li>FPGA captures 1 zero bit + 14 data bits + 1 Over <span class=\"GINGER_SOFATWARE_correct\">Range<\/span> (OVR) bit on both rising and falling <span class=\"GINGER_SOFATWARE_correct\">edge<\/span> of the DRY signal through its IOB\u2019s DDR (Double Data Rate) Flip Flops. Thus sampling data at 400 MHz.<\/li>\n<li>16 bit data captured on rising and falling edge are combined <span class=\"GINGER_SOFATWARE_correct\">to<\/span> 32 bit data and transferred to <span class=\"GINGER_SOFATWARE_correct\">ADC capture FIFO<\/span>.<\/li>\n<li>When the ADC capture FIFO has 4k of data samples that is half of the ADC FIFO, Memory Controller starts transferring data from <span class=\"GINGER_SOFATWARE_correct\">FIFO<\/span> to DDR2 memory at <span class=\"GINGER_SOFATWARE_correct\">DDR rate<\/span> (64 bits at a time) through MIG interface.<\/li>\n<li>It stops transferring data to DDR2 when 128 samples are left to be read from <span class=\"GINGER_SOFATWARE_correct\">Fifo<\/span>. It then once again waits until <span class=\"GINGER_SOFATWARE_correct\">FIFO<\/span> is half full, after which memory controller resumes transferring data from <span class=\"GINGER_SOFATWARE_correct\">ADC FIFO<\/span> to DDR2.<\/li>\n<li>This ping <span class=\"GINGER_SOFATWARE_correct\">pong<\/span> mechanism continues until the desired count of data are captured and dumped into the DDR2 memory. As in FIFO, data <span class=\"GINGER_SOFATWARE_correct\">is dumped<\/span> at 200 MHz and fetched at 250 MHz so in order to prevent underflow; this ping <span class=\"GINGER_SOFATWARE_correct\">pong<\/span> mechanism is implemented.<\/li>\n<li>Once the data gets captured in DDR2 memory, FPGA interrupts DSP.<\/li>\n<li>On demand from DSP, FPGA starts transferring 64 <span class=\"GINGER_SOFATWARE_correct\">bits<\/span> data to the EMIF FIFO through MIG interface.<\/li>\n<li>DSP starts capturing data from EMIF FIFO through <span class=\"GINGER_SOFATWARE_correct\">32 bit EMIF interface<\/span> until whole data transfer gets complete.<\/li>\n<li>FPGA stops transferring data to the EMIF FIFO if the FIFO has 128 <span class=\"GINGER_SOFATWARE_correct\">write<\/span> samples left to FIFO full. It then once again starts transferring data to EMIF FIFO when the no of write samples in the FIFO are 128.<\/li>\n<li>This ping <span class=\"GINGER_SOFATWARE_correct\">pong<\/span> mechanism continues until all the data in the DDR2 are fetched by DSP. As the data is fetched at 10 MHz throughput by DSP while data is dumped by Memory controller at 250 MHz, this ping <span class=\"GINGER_SOFATWARE_correct\">pong<\/span> mechanism is implemented so that FIFO never overflows.<\/li>\n<li>Both ADC and EMIF FIFO are implemented such that neither of them will either overflow or underflow.<\/li>\n<li>FPGA clears the ADC FIFO, EMIF FIFO, and all the internal registers and FSM after every <span class=\"GINGER_SOFATWARE_correct\">capture<\/span>.<\/li>\n<\/ul>\n<h2><strong>Block Diagram of System Level Interface<\/strong><\/h2>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-297\" title=\"tlbd-img1\" src=\"http:\/\/ascenten.net\/tech-notes\/wp-content\/uploads\/2012\/06\/tlbd-img1-1.jpg\" alt=\"\" width=\"648\" height=\"278\" srcset=\"https:\/\/ascenten.net\/tech-notes\/wp-content\/uploads\/2012\/06\/tlbd-img1-1.jpg 648w, https:\/\/ascenten.net\/tech-notes\/wp-content\/uploads\/2012\/06\/tlbd-img1-1-300x129.jpg 300w\" sizes=\"auto, (max-width: 648px) 100vw, 648px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>The above block diagram shows the top level interface diagram from ADS-5474 kit to FPGA Kit to TI-DSP 6455.<\/p>\n<p>&nbsp;<\/p>\n<h2><strong>Functional Block Diagram of FPGA Kit and its Interfaces<\/strong><\/h2>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-298\" title=\"idp-img1\" src=\"http:\/\/ascenten.net\/tech-notes\/wp-content\/uploads\/2012\/06\/idp-img1-1.jpg\" alt=\"\" width=\"648\" height=\"430\" srcset=\"https:\/\/ascenten.net\/tech-notes\/wp-content\/uploads\/2012\/06\/idp-img1-1.jpg 648w, https:\/\/ascenten.net\/tech-notes\/wp-content\/uploads\/2012\/06\/idp-img1-1-300x199.jpg 300w\" sizes=\"auto, (max-width: 648px) 100vw, 648px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h2><strong>Internal Architecture<\/strong><\/h2>\n<p>&nbsp;<\/p>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol start=\"1\">\n<li>RESET_CLK modules generate <span class=\"GINGER_SOFATWARE_correct\">synchronous reset<\/span> and skew free clocks to the respective modules.<\/li>\n<li>ADC_CAP_IF: LVDS data capture module used to capture ADC sample and transfer 2 samples to Asynchronous FIFO.<\/li>\n<li>ADC_CAP_FIFO: Asynchronous FIFO with Dual Port BLOCK RAM, the block ram size is 8K x 32 bits at <span class=\"GINGER_SOFATWARE_correct\">write<\/span> side and 4K x 64 read side.<\/li>\n<li>MEMORY_CTRL: Memory Controller Module transfers data from ADC_CAP_FIFO to MIG DDR2 controller and also performs data transfer from MIG DDR2 controller to EMIF_FIFO.<\/li>\n<li>MIG DDR2 controller transfers data to and from DDR2 memory based on the command-data from Memory Controller.<\/li>\n<li>EMIF_FIFO: Asynchronous FIFO with Dual Port Block Ram, the block RAM size is 2K x 64 bits at <span class=\"GINGER_SOFATWARE_correct\">write<\/span> side and 4k x 32 bits at <span class=\"GINGER_SOFATWARE_correct\">read<\/span> side.<\/li>\n<li>EMIF_IF: 32bits EMIF Interface with Interrupt to TI-DSP and controlling the entire data transfer by generating appropriate control signals to and reception of status signals from ADC capture and Memory controller.<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<table class=\"tbl1\" border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"156\"><strong>Module Name<\/strong><\/td>\n<td valign=\"top\" width=\"157\"><strong>Clock Domain<\/strong><\/td>\n<td valign=\"top\" width=\"166\"><strong>Input Data Width<\/strong><\/td>\n<td valign=\"top\" width=\"202\"><strong>Output Data Width<\/strong><\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"156\">ADC CAPTURE Module<\/td>\n<td valign=\"top\" width=\"157\">In: adc_cap_clkOut: adc_cap_clk<\/td>\n<td valign=\"top\" width=\"166\">14Bits data + OVR from ADC IC<\/td>\n<td valign=\"top\" width=\"202\">32 Bits (2 Samples of ADC Inputs)<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"156\">ADC_CAP_FIFO<\/td>\n<td valign=\"top\" width=\"157\">In: adc_cap_clkOut: core_clk<\/td>\n<td valign=\"top\" width=\"166\">32 Bits (2 Samples of ADC Input)<\/td>\n<td valign=\"top\" width=\"202\">64 Bits\u00a0 to Memory Controller<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"156\">Memory Controller<\/td>\n<td valign=\"top\" width=\"157\">In: core_clkOut: core_clk<\/td>\n<td valign=\"top\" width=\"166\">64 Bits Data from ADC_CAP FIFO<\/td>\n<td valign=\"top\" width=\"202\">MIG controller\u00a0 (64Bits)<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"156\">Memory Controller<\/td>\n<td valign=\"top\" width=\"157\">In: core_clkOut: core_clk<\/td>\n<td valign=\"top\" width=\"166\">64 Bits Data from MIG controller<\/td>\n<td valign=\"top\" width=\"202\">64 <span class=\"GINGER_SOFATWARE_correct\">Bits<\/span> data to EMIF FIFO<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"156\">MIG controller\u00a0 (DDR2 Controller Core)<\/td>\n<td valign=\"top\" width=\"157\">In: core_clkOut: core_clk<\/td>\n<td valign=\"top\" width=\"166\">64 <span class=\"GINGER_SOFATWARE_correct\">Bits<\/span> data to\/from Memory Controller<\/td>\n<td valign=\"top\" width=\"202\">32 bits DDR data to DDR2 Memory<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"156\">EMIF FIFO<\/td>\n<td valign=\"top\" width=\"157\">In: core_clkOut: core_clk<\/td>\n<td valign=\"top\" width=\"166\">64 bits data from Memory Controller<\/td>\n<td valign=\"top\" width=\"202\">32 bits data to EMIF Controller<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"156\">EMIF Interface<\/td>\n<td valign=\"top\" width=\"157\">In: core_clkOut: core_clk<\/td>\n<td valign=\"top\" width=\"166\">32 Bit Data from EMIF FIFO<\/td>\n<td valign=\"top\" width=\"202\">32 Bit Data to TI-DSP using EMIF Protocol.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<h2><strong>Controlling FSM<\/strong><\/h2>\n<p>&nbsp;<\/p>\n<p align=\"center\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-299\" title=\"r656-img1\" src=\"http:\/\/ascenten.net\/tech-notes\/wp-content\/uploads\/2012\/06\/r656-img1-1.jpg\" alt=\"\" width=\"549\" height=\"543\" srcset=\"https:\/\/ascenten.net\/tech-notes\/wp-content\/uploads\/2012\/06\/r656-img1-1.jpg 549w, https:\/\/ascenten.net\/tech-notes\/wp-content\/uploads\/2012\/06\/r656-img1-1-300x297.jpg 300w, https:\/\/ascenten.net\/tech-notes\/wp-content\/uploads\/2012\/06\/r656-img1-1-50x50.jpg 50w, https:\/\/ascenten.net\/tech-notes\/wp-content\/uploads\/2012\/06\/r656-img1-1-60x60.jpg 60w\" sizes=\"auto, (max-width: 549px) 100vw, 549px\" \/><\/p>\n<p align=\"center\">Main <span class=\"GINGER_SOFATWARE_correct\">controlling<\/span> FSM<\/p>\n<p>&nbsp;<\/p>\n<h3><strong>Idle State:<\/strong><\/h3>\n<p>Whenever FPGA is reset or powered up just completes a data transfer, FSM is in this state. FSM remains in this state until<\/p>\n<ol>\n<li>DDR2 is initialized<\/li>\n<li>Soft Start capture set to 1 in the control register<\/li>\n<li><span class=\"GINGER_SOFATWARE_correct\">Rising edge<\/span> of the hard capture is detected<\/li>\n<\/ol>\n<p>When all the above three conditions are satisfied, FSM moves to Capture state and generates capture enable signal for <span class=\"GINGER_SOFATWARE_correct\">ADC Capture module<\/span> to start capturing the samples. In this state status register is updated on every clock.<\/p>\n<p>&nbsp;<\/p>\n<h3><strong>Capture State:<\/strong><\/h3>\n<p>FSM remains in the capture state until it receives capture done signal indicating that the required number of samples have been captured. If capture done was due to forced stop then an interrupt is generated to DSP. Capture <span class=\"GINGER_SOFATWARE_correct\">enable<\/span> is made zero and FSM jumps to ADC_transfer state. In this state status register is updated on every clock.<\/p>\n<p>&nbsp;<\/p>\n<h3><strong>ADC Transfer State<\/strong>:<\/h3>\n<p>FSM remains in the ADC Transfer state until it receives transfer done signal indicating that the required number of samples have been transferred to DDR2 memory. An interrupt is generated to DSP if a bit corresponding to transfer done is set in <span class=\"GINGER_SOFATWARE_correct\">Interrupt mask register<\/span>. FSM jumps to Read Request state. In this state status register is updated on every clock.<\/p>\n<p>&nbsp;<\/p>\n<h3><strong>Read Request State:<\/strong><\/h3>\n<p>FSM waits for DSP to write Read Request bit in the control register indicating that DSP is now ready to fetch data. When the Read Request bit is set to 1, FSM jumps to FIFO Ready state and generates the DDR Emif Transfer Enable signal to Memory module to start dumping data from DDR2 memory to EMIF FIFO. In this state, actual <span class=\"GINGER_SOFATWARE_correct\">samples<\/span> count register is written.<\/p>\n<p>&nbsp;<\/p>\n<h3><strong>FIFO Ready State:<\/strong><\/h3>\n<p>FSM waits until EMIF FIFO has 64 samples of data. FSM updates the status register indicating to <span class=\"GINGER_SOFATWARE_correct\">DSP<\/span> that data is in the FIFO to be fetched and also generates an interrupt if a bit corresponding to it is 1 in Interrupt mask register. In this state status register is updated on every clock.<\/p>\n<p>&nbsp;<\/p>\n<h3><strong>Read Sample Data State:<\/strong><\/h3>\n<p>FSM waits for DSP to write Read Sample Data bit in the control register indicating that the DSP has acknowledged FIFO Ready and FSM should continue to dump data from DDR2 memory to EMIF FIFO. FSM remains in this state until it receives DDR EMIF Transfer Done signal indicating that all the samples stored in the DDR2 memory has been transferred to EMIF FIFO. In this state status register is updated on every clock.<\/p>\n<p>&nbsp;<\/p>\n<h3><strong>Complete State:<\/strong><\/h3>\n<p>FSM waits until all the samples entered in <span class=\"GINGER_SOFATWARE_correct\">samples count register<\/span> has been fetched by ADC and then jumps to <span class=\"GINGER_SOFATWARE_correct\">Idle state<\/span>. FSM generates an interrupt indicating process complete if a bit corresponding to it is 1 in Interrupt mask register. In this state status register is updated on every clock.<\/p>\n<p>&nbsp;<\/p>\n<p>FPGA acting as a bridge was not only able to sample data from ADC at 400 MSPS but was also simultaneously able to transfer and store that data, of maximum 16 million samples to DDR2 memory. Thus in this way DSP was able to process that large chunk of data without loss of any information by fetching it from DDR2 memory through <span class=\"GINGER_SOFATWARE_correct\">FPGA EMIF interface<\/span>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>FPGA as a Bridge between 400 MSPS ADC and 10 MHz Throughput DSP &nbsp; When we talk of precision instrumentation, we are looking at a system that can manage highly complex math-intensive tasks, since the data collected from physical sensors need a complex degree of calculations to be measured. Although&#8230;<\/p>\n","protected":false},"author":1,"featured_media":906,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-215","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-mansi"],"_links":{"self":[{"href":"https:\/\/ascenten.net\/tech-notes\/wp-json\/wp\/v2\/posts\/215","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ascenten.net\/tech-notes\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ascenten.net\/tech-notes\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ascenten.net\/tech-notes\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ascenten.net\/tech-notes\/wp-json\/wp\/v2\/comments?post=215"}],"version-history":[{"count":1,"href":"https:\/\/ascenten.net\/tech-notes\/wp-json\/wp\/v2\/posts\/215\/revisions"}],"predecessor-version":[{"id":939,"href":"https:\/\/ascenten.net\/tech-notes\/wp-json\/wp\/v2\/posts\/215\/revisions\/939"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ascenten.net\/tech-notes\/wp-json\/wp\/v2\/media\/906"}],"wp:attachment":[{"href":"https:\/\/ascenten.net\/tech-notes\/wp-json\/wp\/v2\/media?parent=215"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ascenten.net\/tech-notes\/wp-json\/wp\/v2\/categories?post=215"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ascenten.net\/tech-notes\/wp-json\/wp\/v2\/tags?post=215"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}