Beruflich Dokumente
Kultur Dokumente
Range if MSB=0
Count
Time
Display
Once the counter rolls over, the RunDisp flag is set to 1 causing the display to start counting. The display counter consists of 4 decade counters, with a value 9 in a display digit, causing that digit to be set to 0 on the next input to that display bit counter. The output from the 4 decade counters are connected to the seven segment displays to display the value of these decade counters. The stop button clears the RunDisp variable to 0, thus holding the display value. If the stop button is not pressed, then the counter counts to 9999 and halts there. The block diagram for the whole system is shown in Figure 2. The 2 KHz clock is firstly divided by 2, to give a 1kHz clock, which then drives the Least significant digit of the display. The reaction time is thus displayed in milliseconds.
Maximum Count
Divide by 2
Decade Counter
Decade Counter
Decade Counter
Decade Counter
Start
Stop
ABEL Code
To reduce the length of the program, the seven segment display is implemented as a functional block, to avoid it having to be duplicated 4 times. Those functional blocks are then used four times in the main program to drive all the four display elements. The ABEL code corresponding to the above block diagram is shown below. Firstly, the functional block for the seven segment display is as follows:
MODULE SevSeg TITLE 'Seven Segment Display One Element, C. J. Kikkert April 2005' " Seven Segment Display component for driving one digit "Input D0, D1, D2, D3 "Output LA, LB, LC, LD, LE, LF, LG pin istype 'com'; Count = [D3..D0]; Truth_Table ([Count] -> [!LA,!LB,!LC,!LD,!LE,!LF,!LG]) [0 ] -> [1, 1, 1, 1, 1, 1, 0 ]; "0 [1 ] -> [0, 1, 1, 0, 0, 0, 0 ]; "1 [2 ] -> [1, 1, 0, 1, 1, 0, 1 ]; "2 [3 ] -> [1, 1, 1, 1, 0, 0, 1 ]; "3 [4 ] -> [0, 1, 1, 0, 0, 1, 1 ]; "4 [5 ] -> [1, 0, 1, 1, 0, 1, 1 ]; "5 [6 ] -> [1, 0, 1, 1, 1, 1, 1 ]; "6 [7 ] -> [1, 1, 1, 0, 0, 0, 0 ]; "7 [8 ] -> [1, 1, 1, 1, 1, 1, 1 ]; "8 [9 ] -> [1, 1, 1, 1, 0, 1, 1 ]; "9 [10] -> [1, 1, 1, 0, 1, 1, 1 ]; "10 [11] -> [0, 0, 1, 1, 1, 1, 1 ]; "11 [12] -> [1, 0, 0, 1, 1, 1, 0 ]; "12 [13] -> [0, 1, 1, 1, 1, 0, 1 ]; "13 "MSBSeven segment display element pin istype 'com';
A b C d
"14 "15
E F
That functional block is now used in the Main module, which is as follows:
MODULE ReactT TITLE 'Reaction Timer CC2510 2005 assignement' " Author C. J. Kikkert 20 April 2005.' " Operation: Press Start (SW1) clears the display and stops it incrementing " it also clears the MSB of the 14 bit random time counter 'Count', " resulting in a 4 to 8 second time before the counter rolls over. " This counter runs as long as the circuit is powered up, giving a random time " between the powering up of the circuit and the start button being pressed. " The counter rolling over starts the display incrementing " Pressing the Stop button stops the display incrementing and holds the displayed value " If no stop button is pressed, the display stops at the largest value 9999, " corresponding to 9.999 seconds. The accuracy of the timer is determined by the "RC values of the oscillator and is within about 5%. "Inputs Clock pin 11; Start pin 9; Stop pin 31; "Outputs Seven segment display digits [SA6..SA0] pin 36,37,38,39,40,41,42; [SB6..SB0] pin 24,25,26,27,28,29,30; [SC6..SC0] pin 14,15,16,17,18,19,20; [SD6..SD0] pin 2,3,4,5,6,7,8; "Variables WaitRan, RunDisp node istype'reg'; [C13..C0] node istype'reg'; Count=[C13..C0]; [CD03..CD00] node istype'reg'; CountD0 = [CD03..CD00]; [CD13..CD10] node istype'reg'; CountD1 = [CD13..CD10]; [CD23..CD20] node istype'reg'; CountD2 = [CD23..CD20]; [CD33..CD30] node istype'reg'; CountD3 = [CD33..CD30]; "Timer Counter "LSB Bit0 decade counter for display "Bit1 decade counter for display "Bit2 decade counter for display "MSB Bit3 decade counter for display "Seven "Seven "Seven "Seven Segment Segment Segment Segment Display Display Display Display Outputs Outputs Outputs Outputs pins pins pins pins
"Sub-module connections SevSeg interface (D3=0,D2=0,D1=0,D0=0 -> LA, LB, LC, LD, LE, LF, LG); "Sub-module instances Sevenseg1 functional_block Sevenseg2 functional_block Sevenseg3 functional_block Sevenseg4 functional_block @DCSET Equations SevSeg; SevSeg; SevSeg; SevSeg;
"Control Logic Equations, check buttons When (Start == 0) then "Start button pushed { "Initialise settings these must all be istype'reg' WaitRan := 1; "Wait for random starting time RunDisp := 0; "do not increment the display C13 := 0; "Clear the MSB of the counter to set the 4 to 8 "second delay bofore it rolls over } Else When (Stop == 0) then "Stop button pushed Hold the display { "Initialise settings these must all be istype'reg' RunDisp := 0; "do not increment the display WaitRan := 0 } Else "No Button Pushed { When ((WaitRan == 1) & (RunDisp == 0) & (C13 == 1)) then "Toggle RunDisp wait for C13 to go low { "Initialise settings these must all be istype'reg' WaitRan := 1; "Disable Wait for random starting time RunDisp := 1; "Increment the counter } Else When ((WaitRan == 1) & (RunDisp == 1) & (C13 == 0)) then "Start Counting { "Initialise settings these must all be istype'reg' WaitRan := 0; "Disable Wait for random starting time RunDisp := 1; "Increment the counter } Else When((CountD0 == 9) & (CountD1==9) & (CountD2==9) & (CountD3==9)) then { "Counter Limit Reached go to Hold WaitRan := 0; "Disable Wait for random starting time RunDisp := 0; "Stop the counter } Else { WaitRan := WaitRan; "Keep the existing values (will ->0 without this line) RunDisp := RunDisp; "Keep the existing values (will ->0 without this line) } } " End of Counter Control Equations "7 Segment Display Counter Equations When (WaitRan == 1) then "Counter stopped after start pressed. { CountD0 := 0; "Clear the display CountD1 := 0; "Clear the display CountD2 := 0; "Clear the display CountD3 := 0; "Clear the display } Else When (RunDisp == 0) then "WaitRan = 1 ie run or hold the display { CountD0 := CountD0; "Hold the display CountD1 := CountD1; "Hold the display CountD2 := CountD2; "Hold the display CountD3 := CountD3; "Hold the display } Else "Run the seven segment Display counter { When ((RunDisp == 1) & (C0 == 1)) then { " Run 4 digit decade Counter once every second clock pulse When (CountD0 == 9) then { CountD0 := 0; When (CountD1 == 9) then { When (CountD2 == 9) then
{ CountD2 := 0; When (CountD3 == 9) then CountD3 := 0; Else CountD3 := CountD3 +1; } Else { CountD3 := CountD3; CountD2 := CountD2 +1; } } Else { CountD3 := CountD3; CountD2 := CountD2; CountD1 := CountD1 +1; } } Else { CountD3 CountD2 CountD1 CountD0 := := := := CountD3; CountD2; CountD1; CountD0 +1;
} } Else "C0 = 0 ie odd clockpulse { "Hold values CountD3 := CountD3; CountD2 := CountD2; CountD1 := CountD1; CountD0 := CountD0; } } "End of seven Segment Display counter equations "Display equations "Seven Segment Display inputs Sevenseg1.[D3..D0] = [CD03..CD00]; Sevenseg2.[D3..D0] = [CD13..CD10]; Sevenseg3.[D3..D0] = [CD23..CD20]; Sevenseg4.[D3..D0] = [CD33..CD30]; "Seven Segment Display outputs [SA6..SA0] = Sevenseg1.[LA,LB,LC,LD,LE,LF,LG]; [SB6..SB0] = Sevenseg2.[LA,LB,LC,LD,LE,LF,LG]; [SC6..SC0] = Sevenseg3.[LA,LB,LC,LD,LE,LF,LG]; [SD6..SD0] = Sevenseg4.[LA,LB,LC,LD,LE,LF,LG]; CountD0.clk = Clock; "C0 is a 2kHz clock CountD1.clk = Clock; CountD2.clk = Clock; CountD3.clk = Clock; Count.clk = Clock; "Clock is a 2kHz clock WaitRan.clk = Clock; RunDisp.clk = Clock; Test_Vectors ([Clock, Start, Stop] -> [Count]) @repeat 10 {[.c., 0, 1] -> [.x.];} @repeat 95 {[.c., 1, 1] -> [.x.];}
@repeat 10 {[.c., 0, 1] -> [.x.];} @repeat 100 {[.c., 1, 1] -> [.x.];} @repeat 10 {[.c., 1, 0] -> [.x.];} END
The resulting fitter report shows that this code occupies 93% of the available logic cells.
Design_Summary ~~~~~~~~~~~~~~ Total Input Pins : Total Output Pins : Total Bidir I/O Pins : Total Flip-Flops : Total Product Terms : Total Reserved Pins : Total Reserved Blocks :
3 28 0 32 173 0 0
Device_Resource_Summary ~~~~~~~~~~~~~~~~~~~~~~~ Total Available Used Available Utilization Dedicated Pins Input-Only Pins .. .. .. --> .. Clock/Input Pins 2 1 1 --> 50% I/O Pins 32 30 2 --> 93% Logic Macrocells 64 60 4 --> 93% Input Registers 32 0 32 --> 0% Unusable Macrocells .. 0 .. CSM Outputs/Total Block Inputs 132 Logical Product Terms 320 Product Term Clusters 64 81 176 50 51 144 14 --> --> --> 61% 55% 78%
The screenshot below shows the counting of the random time counter.
Second Solution
The second solution does not use two separate counters, but only uses one counter and uses control of the lights to hide the random timing before the display is to show the counting. This is done by adding a DON (Display ON) control to the seven segment display module. The truth table will thus have 32 states, with half of them being the Display OFF code. To still show that the unit is powered up, a - - - - is shown on the display. To provide the random delay of 4 to 8 seconds, the MSB of the display counter is rapidly cycled through the range between 2 and 5. The second MSB is cycled through the range 0 to 9, to randomly set the two most significant bits of the counter. To provide some further randomness the two least significant bits are not changed. If needed, they could also be set by rapidly cycling them, but the number of counts will need to be different otherwise the relationship between the three LSBs of the counter is fixed. This can be achieved by making the LSB cycle through all 16 possible states and the second LBS cycle through 12 states. Firstly, the functional block for the seven segment display is as follows:
MODULE SevSegON TITLE 'Seven Segment Display One Element, C. J. Kikkert April 2005' " Seven Segment Display component for driving one digit "Input DON, D0, D1, D2, D3 pin istype 'com'; "Output LA, LB, LC, LD, LE, LF, LG pin istype 'com'; "MSBSeven segment display element Count = [!DON,D3..D0]; Truth_Table ([Count] -> [!LA,!LB,!LC,!LD,!LE,!LF,!LG]) [0 ] -> [1, 1, 1, 1, 1, 1, 0 ]; "0 [1 ] -> [0, 1, 1, 0, 0, 0, 0 ]; "1 [2 ] -> [1, 1, 0, 1, 1, 0, 1 ]; "2 [3 ] -> [1, 1, 1, 1, 0, 0, 1 ]; "3 [4 ] -> [0, 1, 1, 0, 0, 1, 1 ]; "4 [5 ] -> [1, 0, 1, 1, 0, 1, 1 ]; "5 [6 ] -> [1, 0, 1, 1, 1, 1, 1 ]; "6 [7 ] -> [1, 1, 1, 0, 0, 0, 0 ]; "7 [8 ] -> [1, 1, 1, 1, 1, 1, 1 ]; "8 [9 ] -> [1, 1, 1, 1, 0, 1, 1 ]; "9 [10] -> [1, 1, 1, 0, 1, 1, 1 ]; "10 A [11] -> [0, 0, 1, 1, 1, 1, 1 ]; "11 b [12] -> [1, 0, 0, 1, 1, 1, 0 ]; "12 C [13] -> [0, 1, 1, 1, 1, 0, 1 ]; "13 d [14] -> [1, 0, 0, 1, 1, 1, 1 ]; "14 E [15] -> [1, 0, 0, 0, 1, 1, 1 ]; "15 F [16] -> [0, 0, 0, 0, 0, 0, 1 ]; "Display OFF (Minus) [17] -> [0, 0, 0, 0, 0, 0, 1 ]; "Display OFF (Minus) [18] -> [0, 0, 0, 0, 0, 0, 1 ]; "Display OFF (Minus) [19] -> [0, 0, 0, 0, 0, 0, 1 ]; "Display OFF (Minus) [20] -> [0, 0, 0, 0, 0, 0, 1 ]; "Display OFF (Minus) [21] -> [0, 0, 0, 0, 0, 0, 1 ]; "Display OFF (Minus) [22] -> [0, 0, 0, 0, 0, 0, 1 ]; "Display OFF (Minus) [23] -> [0, 0, 0, 0, 0, 0, 1 ]; "Display OFF (Minus) [24] -> [0, 0, 0, 0, 0, 0, 1 ]; "Display OFF (Minus) [25] -> [0, 0, 0, 0, 0, 0, 1 ]; "Display OFF (Minus) [26] -> [0, 0, 0, 0, 0, 0, 1 ]; "Display OFF (Minus) [27] -> [0, 0, 0, 0, 0, 0, 1 ]; "Display OFF (Minus) [28] -> [0, 0, 0, 0, 0, 0, 1 ]; "Display OFF (Minus) [29] -> [0, 0, 0, 0, 0, 0, 1 ]; "Display OFF (Minus) [30] -> [0, 0, 0, 0, 0, 0, 1 ]; "Display OFF (Minus) [31] -> [0, 0, 0, 0, 0, 0, 1 ]; "Display OFF (Minus)
END
"Variables DON, RunCount, Clock2 node istype'reg'; "DON Display is ON when DON=1 "RunCount: Run the counter when RunCount = 1 [CD03..CD00] node istype'reg'; CountD0 = [CD03..CD00]; [CD13..CD10] node istype'reg'; CountD1 = [CD13..CD10]; [CD23..CD20] node istype'reg'; CountD2 = [CD23..CD20]; [CD33..CD30] node istype'reg'; CountD3 = [CD33..CD30];
"LSB Bit0 decade counter for display "As a variable "Bit1 decade counter for display "As a variable "Bit2 decade counter for display "As a variable "MSB Bit3 decade counter for display "As a variable
" Use sub-modules to minimise the amount of code required " Sub-module connections SevSegON interface (DON=0,D3=0,D2=0,D1=0,D0=0 -> LA, LB, LC, LD, LE, LF, LG); " Sub-module instances Sevenseg1 functional_block Sevenseg2 functional_block Sevenseg3 functional_block Sevenseg4 functional_block SevSegON; "Functional block declarations SevSegON; SevSegON; SevSegON;
"Counter Equations "Check buttons for correct conditions control states, can use State diagrams here if required When (Start == 0) then "Start button pushed { "Initialise settings these must all be istype'reg' RunCount := 0; "Increment Display time counter at fast rate only DON := 0; "Display OFF } Else When (Stop == 0) then "Stop button pushed Hold the display if display is running { "Initialise settings these must all be istype'reg' When (DON == 0) then { "Display OFF still waiting for the end of wait time. reset wait time (same as start) RunCount := 0; "Increment Display time counter at fast rate only DON := 0; "Display OFF } Else { "Display is running properly, ie time reaction time and stop the counter. RunCount := 0; "do not increment the display counter DON := 1; "Display ON } } Else "No Button Pushed { When ((RunCount ==0) & (DON == 0)) then "Start button released { "Start the display counting but keep the lights OFF RunCount := 1; "Increment counter DON := 0; "Display Blank } Else When ((DON == 0) & (CountD0 == 0) & (CountD1==0) & (CountD2==0) & (CountD3==0)) then { "Random wait time has eleapse, Turn Display ON to show time incrementing RunCount := 1; "Increment the counter DON := 1; "Turn Display ON } Else When((DON == 1) & (CountD0 == 9) & (CountD1==9) & (CountD2==9) & (CountD3==9)) then { "Counter Limit Reached go to Hold RunCount := 0; "Stop the counter DON := 1; "Turn Display ON } Else { " No changes required to DON and RunCount, keep the last value DON := DON; "Keep the existing values (will ->0 without this line) RunCount := RunCount; "Keep the existing values (will ->0 without this line) } } " End of Counter Control Equations "7 Segment Display Counter Equations When((RunCount == 0) & (DON == 0)) then "Start button pushed increment two MSB's fast { When (CountD3 == 5) then "increment MSB of display numbers 2 to 5 to give >4 sec and <8 sec to start CountD3 := 2; "reset MSB Else CountD3 := CountD3 + 1; When (CountD2 == 9) then "increment bit 2 of display numbers 0 to 9 CountD2 := 0; "reset second SB Else CountD2 := CountD2 + 1; CountD1 := CountD1; CountD0 := CountD0; "Hold the counter value "Hold the counter value
} Else When ((RunCount == 0) & (DON == 1)) then "hold the display stop pressed or max count reached { CountD0 := CountD0; "Hold the display CountD1 := CountD1; "Hold the display CountD2 := CountD2; "Hold the display CountD3 := CountD3; "Hold the display } Else "RunCount == 1. Run the seven segment Display counter { When (RunCount == 1) then "increment counter at 1 kHz rate { When (Clock2 == 1) then "only do this at 1 kHz rate { " Run 4 digit decade Counter once every second clock pulse When (CountD0 == 9) then "Check LSB for overflow { CountD0 := 0; "Clear LSB When (CountD1 == 9) then "Check 2LSB for overflow { CountD1 := 0; "Clear 2LSB When (CountD2 == 9) then "Cleck 2MSB for overflow { CountD2 := 0; "Clear 2MBS When (CountD3 == 9) then CountD3 := 0; Else CountD3 := CountD3 +1; "Increment counter } Else { CountD3 := CountD3; "Hold MSB CountD2 := CountD2 +1; "Increment counter } } Else { CountD3 := CountD3; "Hold MSB CountD2 := CountD2; "Hold 2MSB CountD1 := CountD1 +1; "Increment counter } } Else { CountD3 := CountD3; "Hold MSB CountD2 := CountD2; "Hold 2MSB CountD1 := CountD1; "Hold 2LSB CountD0 := CountD0 +1; "Increment counter } } Else "C0 = 0 ie odd clockpulse of 2kHz clock do nothing { "Hold counter values values CountD3 := CountD3; CountD2 := CountD2; CountD1 := CountD1; CountD0 := CountD0; } } } "End of seven Segment Display counter equations "Display equations "Seven Segment Display inputs Sevenseg1.[DON,D3..D0] = [DON,CD03..CD00];
Sevenseg2.[DON,D3..D0] = [DON,CD13..CD10]; Sevenseg3.[DON,D3..D0] = [DON,CD23..CD20]; Sevenseg4.[DON,D3..D0] = [DON,CD33..CD30]; "Seven Segment Display outputs [SA6..SA0] = Sevenseg1.[LA,LB,LC,LD,LE,LF,LG]; [SB6..SB0] = Sevenseg2.[LA,LB,LC,LD,LE,LF,LG]; [SC6..SC0] = Sevenseg3.[LA,LB,LC,LD,LE,LF,LG]; [SD6..SD0] = Sevenseg4.[LA,LB,LC,LD,LE,LF,LG]; Clock2 := !Clock2; "1 kHz Clock variable Clock2.clk = Clock; CountD0.clk = Clock; "C0 is a 2kHz clock CountD1.clk = Clock; CountD2.clk = Clock; CountD3.clk = Clock; DON.clk = Clock; RunCount.clk = Clock; Test_Vectors ([Clock, Start, Stop] -> [CountD3, CountD2, CountD1, CountD0]) @repeat 50 {[.c., 0, 1] -> [.x.,.x.,.x.,.x.];} @repeat 1025 {[.c., 1, 1] -> [.x.,.x.,.x.,.x.];} @repeat 10 {[.c., 1, 0] -> [.x.,.x.,.x.,.x.];} @repeat 50 {[.c., 1, 1] -> [.x.,.x.,.x.,.x.];} @repeat 50 {[.c., 0, 1] -> [.x.,.x.,.x.,.x.];} END
The resources used can be checked by doing a fitter report and are as follows:
Design_Summary ~~~~~~~~~~~~~~ Total Input Pins : Total Output Pins : Total Bidir I/O Pins : Total Flip-Flops : Total Product Terms : Total Reserved Pins : Total Reserved Blocks : 3 28 0 19 147 0 0
Device_Resource_Summary ~~~~~~~~~~~~~~~~~~~~~~~ Total Available Used Available Utilization Dedicated Pins Input-Only Pins .. .. .. --> Clock/Input Pins 2 1 1 --> I/O Pins 32 30 2 --> Logic Macrocells 64 47 17 --> Input Registers 32 0 32 --> Unusable Macrocells .. 0 .. CSM Outputs/Total Block Inputs 132 Logical Product Terms 320 Product Term Clusters 64 80 162 44 52 158 20 --> --> -->
Note that this solution requires less resources that the first solution. 16 Flip-flops are required for the counter, and another 3 for the control variables DON, RunCount, Clock2, and 28 macrocells are required for the seven segment display, so that a minimum of 47 macrocells are required for this circuit. The above solution uses the minimum possible resources.
The screenshot below shows the rapid counting when the start button is pressed.