pdf-Version

Behavioral Modeling and Synthesis of a DCF77 Decoder in Verilog

Bernd Laquai, July 30, 2004


Introduction

This document describes the behavioral modeling of a hardware decoder for the time code broadcasted by DCF77 in Verilog. The resulting decoder displays the minute and hour information contained in the transmitted time string and can easily be extended to also display the date. The Verilog description was created for educational purposes and is therefore not tweaked for performance and efficiency. It rather should provide a simple and intuitive example for behavioral modeling in Verilog.

This model can further be optimized and finally converted into a more efficient gate level model. However, the behavioral model was already developed in a way that it can be used for synthesis using the software provided with FPGAs and CPLDs. The code was tested to work correctly with an Altera MAX7000S Series CPLD (EPM7128SLC84 ). A test board as described in [5] was used for evaluation together with a receiver module and a 4-digit seven segment LED display. A hardware synthesis from Verilog is an alternative to the typical implementation of such a decoder with SW-code executed on a microcontroller.

DCF77 is a longwave transmitter operated by the "Physikalisch-Technische Bundesanstalt" (PTB) in Braunschweig, Germany at a frequency of 77.5kHz. The transmitter is located in Mainflingen close to Frankfurt/Main. The PTB is the official authority in Germany responsible for the dissemination of the reference time and is used by the majority of the radio controlled clocks. The time code is based on the Caesium reference clocks of the PTB that are permanently synchronized with the reference clocks of other countries in order to distribute the "Coordinated Universal Time" UTC.

The DCF signal

The signal emitted from DCF77 is shown in fig. 1. The clock information is transmitted using a binary string representing a time code of 60 bit length. The binary time string carries information such as the current minute, hour and date. The bits are transmitted at a pace of 1 second. The pace is indicated with a 25% amplitude reduction of the RF carrier signal at each start of a second, except for the 59th second. The 59th bit is considered to be the "sync bit" indicating that a new minute starts with the next bit. A pulse width modulation is used to represent the logical value of a bit. The carrier is either reduced for a length of 100ms indicating a logic low or for a length of 200ms indicating a logic high. The start of the next time code is indicated by omitting the carrier reduction for this one second representing the 59th sync bit.

Fig. 1
Fig. 1: The DCF77 signal and its encoding

The numeric time information carried in the binary time string is represented with BCD encoded digits. The information is additionally secured with parity bits that complement the BCD code to an even number of bits.

The meaning of the bits is described in table 1. More detailed information on the encoding is available from the PTB [1], [2].

Bit no. Meaning
0 Minute mark
1:14 PTB private data
15 Antenna status
16 Announce of daylight savings time
17:18 Timezone
19 Announcement of leap second
20 Start of date info
21:24 Minute ones
25:27 Minute tens
28 Parity(min ones, min tens)
29:32 Hour ones
33:34 Hour tens
35 Parity(hour ones, hour tens)
36:41 Calendar day
42:44 Week day
45:50 Calendar month
51:57 Calendar year
58 Parity (cal day, week day, cal month, cal year)
59 Sync bit (no modulation)

Table 1: Meaning of the bits in the DCF77 time string

The receiver module

The decoder described in this document does not contain the actual DCF77 receiver. Highly integrated and cheap receiver modules are readily available e.g. from Conrad Electronic [4]. Such a receiver module contains a ferrite antenna, a chip on small PCB with connectors for power and the output signals. The chip demodulates the carrier signal and presents the binary modulation signal at a non-inverted and an inverted output. The non-inverted output signal goes high when the carrier is reduced and goes low for the rest of the second. During the 59th second when carrier reduction is suppressed and no bit (the "sync bit") is sent, the non-inverted output stays low. Such a module is assumed to provide the input signal to the DCF decoder described here.

Module "dcfDecoder"

Fig. 2 shows a block diagram of the DCF77 decoder module "dcfDecoder". The module contains 4 sub-modules for the processing of the DCF77 modulation signal:

In addition to these signal processing modules it also contains a module "clockGen" for the generation of the local clock.

The clock generator module generates a local clock from the crystal attached to the decoder. The crystal is connected to the "oscIn" and "oscOut" ports. The local clock generated has a 10ms period (100Hz) and is available at "divClkOut". This signal is externally looped back into the main clock input "locMsClk". The reason for external loop is the option to clock the "dcfDecoder" module also from an externally provided clock for test purposes.

The DCF77 modulation signal from the receiver module is provided to the main input "sigIn" of the module "dcfDecoder" which is directly connected to the synchronization stage "syncStage". This synchronization stage samples the signal with the locally generated clock (100x oversampling) to provide a synchronous input to the following stages. Due to the synchronous sampling, the signal output "syncSig" of the synchronization stage changes its value only at the edges of the local clock "locMsClk".

The synchronously sampled signal is routed to the pulse width decoder module "pwDecoder". This module extracts the bit values, a bit clock and a minute clock from the signal by analyzing the pulse width. The bit values "bit" are output synchronously with "bitClk" for the duration of a whole second. The clock signal "minClk" indicates the 59th second and therefore marks the change of the minute. It goes high synchronously with "bitClk" only at the start of the 59th second.

The bits are extracted from the DCF77 signal as they arrive and are supplied to the serial input "serIn" of the following shift register module "shiftReg". The data are clocked into the register "srWord" sequentially, a bit each second, using the bit clock "bitClk". The data are clocked in from the side of the most significant bit of the register. The register is 60 bits wide and represents the bit values of the last 60 seconds. Since the shift register is updated each second, it also changes its value each second. "dataOut" is another 60 bit wide register that gets loaded with the shift register content only once per minute using "minClk". Therefore, the data value of "dataOut" register holds the complete DCF77 time code stable for a whole minute.

Fig. 2

Fig. 2: Block diagram of the DCF77 decoder embedded in a test bench

Four seven segment decoder modules "ssDecoder" are attached to the specific individual bit values of the time code register "dataOut". These bits represent the BCD values for the minutes and hours. Identical seven segment decoders are used for the four digits indicating the ones and tens of the minutes and hours. The number of bits representing the tens of minutes and tens of hours are coded with less than 4 bits in contrast to the ones of hours and minutes. Therefore, the 4 bit input "dataIn" of the seven segment decoder needs to be padded with zeros in these cases. The outputs "ssMinOne", "ssMinTen", ssHourOne" and "ssHourTen" of the individual seven segment decoders drive the 4 respective LED displays, each displaying one digit.

The code of the main module "dcfDecoder" has no major functionality, except for instantiation of the sub-modules. The parameter "nrSec" is introduced for test purposes in order to optionally adapt to a reduced length of the date code from the test bench.

The buses for the BCD coded bits that represent the digits for ones and tens of minutes and hours are branched off from the "dataOut" register by indexing the position as given in table 1 with an offset of 2. This offset results from the particular timing used in the pulse width decoder and shift register module for latching the bits. This aspect will be explained along with the description of the shift register module later.

The following always block updates the register "dataOut" once per minute with the content of the shift register and is described along with the operation of the shift register module.

The decoder module "dcfDecoder" was developed with the goal to verify it with an implementation on a CPLD. The programming software uses the input and output port declarations as I/O pins. The verification of the code with a Verilog simulator suggests to use the CPLD I/O-pins as a port interface for testing. This is the purpose of the test bench "dcfTb". It stimulates the inputs and compares the result at the outputs of the decoder. The test bench therefore emulates the system in which the decoder is used and additionally allows the analysis of internal nodes in the decoder design. The test bench is described separately in more detail in a dedicated paragraph below.

The clock generator module "clkGen"

The clock generator module contains two major functional units. The first is a simple inverter (first always block) and a counter (second always block). The inverter is used in conjunction with an external crystal to form a feedback loop. The feedback loop generates a high frequency clock signal and therefore acts as clock oscillator. The frequency of the oscillator is determined by the crystal frequency.

The high frequency clock signal driven by the inverter is also used as an input to the counter. The counter increments the register content "Q". When "maxCnt" is reached, the register "Q" is reset. The counter parameters "maxCnt" and "wid" are adapted to a crystal frequency of 10MHz (100ns period). With a "maxCnt" value of 99999 (plus the reset state 0), the counter reset is executed all 10ms yielding the oversampling factor of 100. As a consequence, the highest bit of the register "Q" shows a signal with a periodicity of 10ms and a more or less balanced duty cycle. The signal generated from the MSB of the "Q"-register is output and serves as local clock for the other sub-modules.

The synchronization stage "syncStage"

The DCF77 signal supplied by the receiver module appears asynchronously to the local 10ms clock that is used by the pulse width decoder for extraction of the DCF77 bit information. Due to the asynchronous input, a situation may happen where the setup and hold times of the input latch are violated. In such a case a transition of the input signal coincidences with the local clock used for latching. This may result in a metastable state of the respective flip-flop causing an excessive settling time and an uncertainty of the final outcome. To minimize the occurrence of such situations a synchronization stage is introduced in the incoming signal path.

The synchronization stage employs a second flip-flop also clocked from the local clock to latch in the output of the first latch with the subsequent clock edge. This eliminates metastability for all the cases where the first stage is able to settle within one local clock cycle of 10ms. Since a longer settling time is pretty unlikely, the output of the sync stage can be assumed to change its state only with the local clock and thus operates synchronously.

The pulse width decoder module "pwDecoder"

The pulse width encoded binary information contained in the modulation signal is decoded by means of a counter "timCnt" that is operated with the local 10ms clock. The absence of the 59th bit for synchronization is also detected with the same counter. The timing of the synchronized DCF77 signal and the counter operation is shown in fig. 3.

Fig. 3
Fig. 3: Decoding of the pulse width with a counter

A full second would result in 100 counts of the "timCnt" counter, giving enough granularity to distinguishing a 100ms pulse from a 200ms pulse or to sense a missing bit. In order to combine sync pulse detection and evaluation of the pulse width, only the clock cycles in the gap between pulses are counted. Four cases may appear:

100ms pulse, 900ms gap
count = 90 --> logical 0

200ms pulse, 800ms gap
count = 80 --> logical 1

100ms pulse, 1900ms gap
count > 130 --> sync bit

200ms pulse, 1800ms gap
count > 130 --> sync bit

Fig. 4 illustrates the decisions to be made for decoding of bits and detection of the sync bit in a flow graph. The decisions are made at the pace of the local 10ms clock.

Fig. 4

Fig. 4: Flowgraph for the decoding of bits and detection of the sync bit

The first decision to be made is if a bit interval (1 second) is completed. This is indicated by either an input signal transition or if the regular bit interval is exceeded. The presence of a signal edge is detected by forming a delayed replica of the input signal and a logical AND with the inverted replica. The exceeding of a bit interval is sensed by the time counter having exceeded the threshold for a sync bit "thSync". The value for the parameter "thSync" is a compromise between sensing the situation as fast as possible and generating a signal that indicates the start of a minute as late as possible with respect to the start of the 59th bit (see also next paragraph). In both cases (branch 1a in the flow) a pulse "bitClk" is generated that indicates the start of a bit interval (the begin of a second). If neither of the above conditions is met, the clock cycle is assumed to be a regular cycle, somewhere in midst of the bit interval (branch 1b).

The second decision is made in case of the branch 1a (start of a bit interval). When the previous bit interval was exceeded (branch 2a) it is assumed that the sync bit (missing 59th bit) occurred and a pulse "minClk" is generated. This marks the end of the current time string. This pulse however is also used to indicate the start of the next minute. This basically introduces an error because the next minute does not start before the full sync bit interval is completed. For reasons of simplicity this aspect is ignored. This means that the start of the minute occurs a little bit too early. The error introduced is (200-thSync)*10ms. For a value of "thSync" = 130 the error will therefore be 700ms and the information for the next minute will be updated 700ms before the actual start of the minute. The correction of this deficiency is left for future versions.

At the time when the sync bit was detected, the time counter is not cleared but the count of the full sync bit interval (= 0'd100) is subtracted. This creates the situation as if the counter would have started with the end of the pulse in the previous bit interval (58th bit). This is illustrated in fig. 5.

When a signal edge was detected (branch 2b), the counter value of "timCnt" varies according to the length of the gap and is either 80 or 90. Therefore the 3rd decision uses the threshold "thBitVal" to separate between a short 100ms pulse (logical 0) and a long 200ms pulse (logical 1). This threshold is typically set to the center value of 85 (fig. 6). In the branches 3a (long gap, short pulse) and 3b (short gap, long pulse) the value of the currently received bit is set to 0 and 1 respectively. After assigning the bit value, the time counter is cleared to be incremented again with the next gap.

When the evaluation of the signal did not yield the start of a bit (branch 1b), both, the signal for the clock pulse that indicates the start of a second ("bitClk") and the start of a minute ("minClk") needs to be set back to zero. To avoid a very short pulse of the duration of one local clock cycle (10ms) only, the time counter is used again (decision 4) to determine the pulse width of "bitClk" and "minClk". The signal will not be set to low before the threshold "thClkWid" is reached (branch 4a). When the threshold is not yet reached (branch 4b) no change occurs and "bitClk" and "minClk" remain high.

Since the time counter should only be counting for the duration of the gaps, the signal value needs to be checked for any local clock event other than the start of a bit. This is accomplished with the decision 5. When the signal is low, a gap is assumed and the counter is incremented (branch 5a). If the signal is high, a signal pulse is assumed and the counter value is not changed and remains at 0 (branch 5b).
Fig. 5
Fig. 5: Counter values during sync

Fig. 6
Fig. 6: Counter values during regular bits

The details of the timing handshake is indicated in fig. 7. The graph shows a close-up to the time when a signal edge is received. The asynchronous signal is latched into the sync stage with the rising edge of the local clock and is delayed by one clock cycle in the internal stage for proper synchronization. The synchronized signal "syncSig" in module "dcfDecoder" is passed to module "pwDecoder" and latched in with the positive edge of the local clock. The pulse width decoder module forms the inverse of the delayed signal "delSig" to generate a short pulse that indicates the edge of the incoming pulse. The bit value "bit" as well as the "bitClk" and "minClk" pulses are started and stopped with the next positive edge of the local clock.
Fig. 7
Fig. 7: Detection of a signal transition

The shift register module "shiftReg"

The module implements a shift register for serial loading and parallel unloading with a default length of 16. The default length is overridden to the length of 60 during instantiation in "dcfDecoder" to provide enough space for all 60 bit values decoded from the received time string of a full minute.

Fig. 8
Fig. 8: Serial to parallel conversion of data bits

The bits supplied from the pulse width decoder are clocked in serially with the negative edge of the bit clock. For the bits before, during and after synchronization this is visualized in fig. 8. The alternating use of edge directions guarantees that a bit value that changes with the positive edge of a bit clock will be clocked in properly maintaining setup and hold times.

The internal 60-bit shift register "srWord" changes its value for each incoming serial bit. In order to maintain a stable information for the duration of a full minute, the main module "dcfDecoder" reads out the shift register in parallel with the next positive edge of "minClk". The content is transferred to a second 60-bit register "dataOut" that stores the decoded time string information for the duration of a full minute. This approach definitely consumes a large amount of flip-flops to create the two 60-bit registers but offers the option to enhance the solution easily by decoding further segments beyond the hours and minutes (e.g. the date code).

Since "minClk" occurs synchronously with "bitClk", the data transferred into "dataOut" are delayed by one bit interval. Together with the delay for decoding the pulse width into the logical bit value, an offset of two bit clocks is induced compared the event of the incoming pulse edge. This is reflected by the offset in the assignment statements for branching off the data from "dataOut" into the seven segment decoders as mentioned at the beginning.

The seven segment decoder "ssDecoder"

This module uses a simple case-statement based translation of the incoming BCD coded values to binary strings representing the data needed by a seven segment single digit LED display. The binary strings into which the BCD code is translated strongly depend on the way how the LED display pins are connected to the output pins representing the internal signals "ssHourOne", "ssHourTen", "ssMinOne" and ssMinTen". It therefore has to be adapted to the particular layout of the board and the interconnecting scheme taking into account the polarity required for turning a segment on.

The test bench module "dcfTb"

The test bench module is provided to simulate the DCF77 decoder module "dcfDecoder" outside of a CPLD/FPGA programming environment. It provides the stimulus that would normally be received from a DCF77 receiver module. It also performs a crude sanity check by comparing the BCD signals that go into the seven segment decoders with expected values obtained from the stimulus. This may help to quickly test the functionality with simple pass/fail criteria. It may also help to better understand the code.

The test bench module „DCFtb" emulates the received time string for a few arbitrarily chosen minutes and converts it into the pulse width modulated signal. It also emulates the clocks that appear in the real system. However, to speed up the simulation, the duration of a local clock period and the duration of a "second" do not scale with the clock from the crystal oscillator. To decouple the simulation of the decoder and the crystal oscillator, the output of the clock divider does not drive the DCF decoder. Instead the local clock for the decoder is generated separately from the test bench. The clock periods are controlled with the parameters "period" and "crystalPer".

The period "crystalPer" is used to emulate the crystal and should be chosen as small as possible, but just as small to not exceed the maximum iteration limit for the simulator. Since it drives the clock divider that needs at least 100k cycles to change its state, enough clock periods are required to verify the clock divider. As soon as the clock divider is verified, the parameter can be set to a higher value to speed up the simulation. The parameter "period" determines the duration of a "second" in the simulation. The value of 1000 is typically mapped to 1000ps if the timescale of the simulator is not explicitly set. Accordingly, the period of the local clock "locMsClkTb" needs to be smaller by a factor of 100 to achieve the correct oversampling factor.

The test bench keeps control of the index of the bits in the time string with the register "secCntTb". The register is counted up with the clock "secClkTb". Both are registers that are local to the test bench.

The DCF bits are stored in registers named according to their meaning in the DCF time string. Later, a bus "dcfDataBlk" is formed from these registers to assemble the 60-bit wide time string.

The simulation assumes a sequence of random time strings of one minute duration each, instead of a real sequence of consecutive minutes. In order to generate the pulse width modulated signal from several random strings in sequence, a task (a Verilog construct like a sub-routine) is repeatedly executed. The task "genBit" is called from the test bench with "dcfDataBlk" as parameter mapped internally to the bus "bitArray". For serial signal generation, the task accesses this 60-bit wide bus to retrieve the bits within a time string sequentially. It generates the signal waveform with the respective pulse width depending on the bit value for the bits 0 to 57. The waveform segment for the bit 58 is generated separately to advance the simulation only to the point where the pulse is set low 0.1*period or 0.2*period after the rising edge. For the rest of the bit interval as well as for the following interval of the 59th second the generated waveform stays low until the first bit in the next time string sets the signal high again. Therefore, the current execution of the task does not advance the simulation to the next signal change, but instead the clock cycles that follow until the next call of the task occurs do this job.

The assignment statements following the task declaration are done to group the signals from the registers containing a particular data element of the time string into a common bus. The bus line index indicates the position of the information in the time string.

In the first initial block the DCF data registers are initialised with an arbitrary time code. This block is also used to initialise those registers that produce the clock signals.

The following always blocks are executed concurrently and define the clock operation. Before the main section of the signal generation begins, a minute clock is obtained by counting up the register "secCntTb" for each "second". This always block toggles a register to form the test bench internal clock signal with a period of a minute. The minute clock "nextMinTb" finally triggers the generation of the time strings in the following initial block.

Starting with a reset for all registers in the DCF decoder, the task "genBit" is called with a delay upon the event of a rising edge in the minute clock. The delay ensures that the bus "dcfDataBlk" containing the next DCF time string has fully settled to avoid ambiguities. The task outputs the DCF signal and the decoder will decode it concurrently. When one time string is generated completely, the result is checked by comparing the decoder output with what was sent from the task "genBit". After the comparison is completed and the result is displayed, the DCF registers are overwritten to form a new time string. The task "genBit" is called again with a delay to send the next time string to the DCF decoder. This procedure is repeated for a few time strings until the simulation is stopped.

The comparison is done by checking internal DCF decoder registers that contain the BCD code of the four digits and not the seven segment decoder output because the data are easier to understand. However, the test can easily be extended to also compare the seven segment decoder output or other outputs against expected data.

The test bench module finally ends with the instantiations of the DCF decoder module as the top level cell to be tested.

Fig. 9

Fig. 9 Test board with a CPLD containing the synthesized DCF decoder

Literature

[1] Hetzel, P.: Der Langwellensender DCF77 auf 77,5 KHz: 40 Jahre Zeitsignale und Normalfrequenz - 25 Jahre kodierte Zeitinformation. PTB-Mitteilungen 109, Heft 1 (1999), S. 11-18

[2] 12. und 17. PTB-Seminar Zeit und Frequenz, Vorträge über DCF 77, Auszug aus PTB-Bericht PTB-Me-23 (März 1979)

[3] Hilberg, W.: Funkuhren, Zeitsignale, Normalfrequenzen: Technik und Anwendung. Verlag Sprache und Technik, Groß-Bieberau 1993

[4] Conrad: DCF Empfängerplatine Artikel-Nr.: 641138 - 14 (http://www.conrad.de)

[5] Elektor Heft Nr. 401 Mai 2004: „Entwerfen Sie Ihren eigenen Chip! Prototyping mit CPLDs" (http://www.elektor.de)

[6] D. E. Thomas, P. R.Moorby: The Verilog Hardware Description Language, fifth edition, Kluwer Academic Publishers, 2002

[7] S. Palnitkar: Verilog HDL, A Guide to Digital Design and Synthesis, Second Edition, Prentice Hall, 2003

[8] "The radio clock home page" / "Die Funkuhr Homepage" von Robert Heret (http://www.heret.de/funkuhr/index.htm)

Verilog Code

dcfDecoder
clockGen
syncStage
pwDecoder
shiftReg
ssDecoder
dcfTb

Disclaimer

Even though the code was tested thoroughly it may still be erronous. A clock or any other equipment based on the Verilog code listed or any other information contained on this website may not work correctly and bears the risk of damage and injury. The author does not assume any liability or responsibility for the the material posted on or accessible through this website. Reliance on any information is solely at your own risk.

For further questions: