THE VLSI HOMEPAGE

A Practical Guide to VLSI Design and Verification..

Serial to Parallel and Parallel to Serial conversion

Posted in Digital Design by Nigam on the October 3rd, 2007

Serial to Parallel conversion is common in designs where the clock runs at slower frequency than the incoming serial stream. To maintain the throughput, the serial data is converted to parallel data. Similarly, high speed parallel data can be converted to serial stream before output from a chip - as it is very hard to manage skew between different data lines.

We will look at verilog implementation of a simple serial to parallel converter and a parallel to serial converter in this post.

CODE:
  1. module serial_to_parallel ( parallel_out, serial_in, shift_enable, clock, reset_n);
  2.  
  3.   parameter SIZE = 4;
  4.   output [SIZE-1] parallel_out;
  5.   input                serial_in;
  6.   input                shift_enable;
  7.   input                clock;
  8.   input                reset_n;
  9.  
  10.   reg [SIZE-1] parallel_out;
  11.  
  12.   always @(posedge clock or negedge reset_n) begin
  13.     if (~reset_n)
  14.       parallel_out <= 0;
  15.     else if (shift_enable)
  16.       parallel_out <= {serial_in, parallel_out[SIZE-1:1]};
  17.     end
  18.  
  19. endmodule

CODE:
  1. module parallel_2_serial (serial_out, parallel_in, load_enable,shift_enable, clock, reset_n);
  2.  
  3.    parameter SIZE=5;
  4.    output serial_out;
  5.    input clock;
  6.    input reset_n;
  7.    input load_enable;
  8.    input shift_enable;
  9.    input [SIZE-1:0] parallel_in;
  10.  
  11.    reg [SIZE-1:0] parallel_r;
  12.  
  13.   always @(posedge clock or negedge reset_n) begin
  14.     if (~reset_n)
  15.       parallel_r <= 0;
  16.     else if (load_enable)
  17.       parallel_r <= parallel_in;
  18.     else if (shift_enable)
  19.       parallel_r <= {1'b0, parallel_r[SIZE-1:1]};
  20.     end
  21.    assign serial_out = parallel_r[0];
  22. endmodule

Sphere: Related Content

RTL coding guidelines - Doing it right the first time!

Posted in Digital Design by Nigam on the September 27th, 2007
  • Document in detail interface timing and signal descriptions, clock and reset strategy, modular view of the design and FSMs prior to RTL coding.
  • Have a comment "header" for each module with functionality description, version and a log of past changes. This can be managed using a revision control system like CVS.
  • Do not include more than one module in one file and the module name should match the filename in the design.
  • Be generous while adding comments where necessary - like inputs and outputs.
  • Split the design into separate modules based on clock domains.
  • Use separate always @ blocks for sequential and combinational logic. Always use non-blocking assignments for sequential logic and blocking assignments for combinational logic.
  • Avoid "parallel_case full_case" compiler directives and always add a default clause for case statements.
  • Do NOT assign the same variable in more than one always@ block.
  • Use "if-else" only for priority encoders and case statements for parallel states.
  • Avoid inferring latches in the design, clock gating and instantiating gates in the design to keep it technology independent.
  • Register all inputs and outputs in the design to ease timing closure.
  • Use dual stage synchronizer cells available in the library than two stage flops for synchronization.
  • Use reset synchronizers for asynchronous resets. Add DFT bypass muxes for reset and clock controllability where necessary.
  • Avoid combinational loops in the design to aid timing analysis and DFT
  • Avoid using clock as data for flop inputs for hassle free DFT insertion.
  • Do not mix posedge and negedge flops in the same module where possible.
  • Always separate the combinational and sequential logic in a FSM with two always@ blocks.
  • Always code with design reuse in mind - For example, FIFOs can be made generic and can be customized by passing parameters while being instantiated.
  • Remember the thumb rule - Be conservative in what you transmit and be generous in what you receive
  • Parenthesize all operations without depending on the reader to figure out the precedence of operators.
  • Lint your design for syntax/sematic checks and clock-reset policies.
Sphere: Related Content

FIFOs - Architecture and Design

Posted in Digital Design by Nigam on the September 20th, 2007

Introduction

A designer encounters FIFOs in speed matching or data width matching applications. An example of speed matching is when data is being transferred in bursts from a faster clock domain to a slower clock domain that is sampling the data. An example of data width matching is where the sampling clock domain is faster but the data width is narrower than the write side. FIFOs can be synchronous or asynchronous, i.e. the read and write clocks can be synchronous or asynchronous to each other.

Full and Empty flags

The FIFO full and empty status conditions are derived from the write and read pointers of the FIFO. The write pointer always points to the next word to be written and is incremented on a write to the FIFO. The read pointer points to the current word to be read and drives the valid data onto the output port to make the design efficient.

A FIFO can be full or empty when the read and write pointers are equal because of wraparound. To resolve this, an extra bit is added to the pointers - if the MSB of the pointers are different from each other, it indicates a full condition. If the MSB bits are the same, the FIFO is empty.

Pointer Synchronization

Synchronizing read and write pointers in an async FIFO is necessary since the write pointer is generated in write clock domain and read pointer is generated in read clock domain. To generate the empty and full status flags, it is necessary to transfer these pointers from one domain to the other.

Several techniques exist for synchronizing the pointers. One method is to synchronize the read and write strobes and use counters in read and write domains. The read counter tracks the number of valid data entries while the write counter tracks the number of entries to store data. The read counter is decremented on each read strobe, the read strobe is synchronized to write clock before incrementing the write counter. Similarly, the write strobe decrements the write counter and is synchronized to read clock before incrementing the read counter.

The strobes are synchronized using toggle synchronizers and indicate pessimistic empty/full status as there is latency in synchronization. The disadvantages of this method is that large counters are required for large FIFOs and also since there should be atleast two cycles spacing in strobes in slow clock domain (see toggle synchronizer), the data rate is inefficient.

Another method is to synchronize the read and write pointers but this is problematic in binary as more than one bit can change at a time and synchronization is unpredictable. The solution is to use Gray code counters that change one bit at a time, synchronize and generate the empty and full flags.

FIFO Depth

Calculating the depth of the FIFO requires the write and read clock frequency relation, burst rate on the write clock domain, synchronization latency and any idle cycles in the read domain.

Scenario 1:

Consider the case of a FIFO where the write clock frequency is 100 MHz and 50 words are written into the FIFO in 100 clocks while the read clock frequency is 50 MHz and one word is read out every clock.

In the worst case scenario, the 50 words are written into the FIFO as a burst in 500 ns. In the same time duration, the read side can read only 25 words out of the FIFO. The remaining 25 words are read out of the FIFO in the 50 idle write clocks. So the depth of the FIFO should be atleast 25 ( + synchronizer latency) = ~28.

The FIFO depth is calculated as

Depth = Burst_size * { 1 - (Frd/(Fwr * Idle_cycles)) }

Scenario 2:

Consider the case of a FIFO where the write clock frequency is 100 MHz and 80 words are written into the FIFO in 100 clocks while the read clock frequency is 80 MHz and 8 words are read out every 10 clocks. There is no feedback mechanism to throttle the writes to the FIFO.

In the worst case, the FIFO will write 80 words in a burst into the FIFO in 800 ns. In the same time, the read side can read only ~51 words ( (800/125) * 8 ) in that same time period. In the remaining 200 ns, only ~13 words ( (200/125) * 8 ) can be read out of the FIFO leaving 16 words on the floor. So the FIFO will need to be of infinite depth to make this design work!

For more details on FIFO design and Verilog code, the reader is recommended to read Cliff Cumming's paper on Asynchronous FIFOs

 

Sphere: Related Content

Next Page »

Close
E-mail It