You are on page 1of 9

Tue Oct 04 20:29:23 2011

frequency_counter.vhd
1
-- Reference design - Frequency counter for Spartan-3E Starter Kit (Rev.C).
2
-3
-- Ken Chapman - Xilinx Ltd - 7th March 2006
4
-5
-- *** This design contains an evaluation test feature of the DCM. ****
6
-- *** Before this design can be processed a special environment
****
7
-- *** needs to be set or the 'dcm_fixed_osc' module removed.
****
8
-- *** Please read the notes provided in 'dcm_fixed_osc.vhd' for
****
9
-- *** details of this special requirement.
****
10
-11
-12
-- Provides a frequency counter with resolution of 1Hz up to a maximum frequency of
13
-- approximately 200MHz (limited by maximum clock rate of design).
14
-15
-- The 50MHz on board oscillator is used to provide a 1 second time base and therefore
16
-- defines the accuracy of the measurement. If the frequency of the 50MHz oscillator can
17
-- be determined using a calibrated frequency counter or frequency generator then this
design
18
-- could be tuned to match the particular board.
19
-20
-- Slide switches SW0, SW1, SW2 and SW3 allow selection of the input signal or one of thr
test
21
-- signals. Only one switch should be selected and the LCD display will guide and confirm
the
22
-- selection process.
23
-24
-- SW0 selects SMA connector (J17) as the input signal to be analysed.
25
-- SW1 selects the 50MHz oscillator as a test signal and must yield a perfect result sinc
it is
26
-also the definition of the measurement time base..
27
-- SW2 selects a signal of approximately 145MHz which is generated by one of the DCMs
operating
28
-in a special test oscillator mode.
29
-- SW3 selects a ring oscillator implement using a combinatorial loop in the CLB fabric.
30
-31
-- LED indicate measurements in progress (1 second alternate flashing of 4 LEDs).
32
-33
-- PicoBlaze performs calculations and conversions as well as driving the LCD display.
34
-35
-----------------------------------------------------------------------------------36
-37
-- NOTICE:
38
-39
-- Copyright Xilinx, Inc. 2006.
This code may be contain portions patented by other
40
-- third parties. By providing this core as one possible implementation of a standard,
41
-- Xilinx is making no representation that the provided implementation of this standard
42
-- is free from any claims of infringement by any third party. Xilinx expressly
43
-- disclaims any warranty with respect to the adequacy of the implementation, including
44
-- but not limited to any warranty or representation that the implementation is free
45
-- from claims of any third party. Furthermore, Xilinx is providing this core as a
46
-- courtesy to you and suggests that you contact all third parties to obtain the
47
-- necessary rights to use this implementation.
48
-49
-----------------------------------------------------------------------------------50
-51
-- Library declarations
52
-53
-- Standard IEEE libraries
54
-55
library IEEE;
56
use IEEE.STD_LOGIC_1164.ALL;

Page 1

Tue Oct 04 20:29:23 2011


frequency_counter.vhd
57
use IEEE.STD_LOGIC_ARITH.ALL;
58
use IEEE.STD_LOGIC_UNSIGNED.ALL;
59
-60
-- The Unisim Library is used to define Xilinx primitives. It is also used during
61
-- simulation. The source can be viewed at %XILINX%\vhdl\src\unisims\unisim_VCOMP.vhd
62
-63
library unisim;
64
use unisim.vcomponents.all;
65
-66
-----------------------------------------------------------------------------------67
-68
-69
entity frequency_counter is
70
Port (
led : out std_logic_vector(7 downto 0);
71
sw : in std_logic_vector(3 downto 0);
72
strataflash_oe : out std_logic;
73
strataflash_ce : out std_logic;
74
strataflash_we : out std_logic;
75
lcd_d : inout std_logic_vector(7 downto 4);
76
lcd_rs : out std_logic;
77
lcd_rw : out std_logic;
78
lcd_e : out std_logic;
79
sma_clk : in std_logic;
80
clk_50mhz : in std_logic);
81
end frequency_counter;
82
-83
-----------------------------------------------------------------------------------84
-85
-- Start of test architecture
86
-87
architecture Behavioral of frequency_counter is
88
-89
-----------------------------------------------------------------------------------90
-91
-- declaration of KCPSM3
92
-93
component kcpsm3
94
Port (
address : out std_logic_vector(9 downto 0);
95
instruction : in std_logic_vector(17 downto 0);
96
port_id : out std_logic_vector(7 downto 0);
97
write_strobe : out std_logic;
98
out_port : out std_logic_vector(7 downto 0);
99
read_strobe : out std_logic;
100
in_port : in std_logic_vector(7 downto 0);
101
interrupt : in std_logic;
102
interrupt_ack : out std_logic;
103
reset : in std_logic;
104
clk : in std_logic);
105
end component;
106
-107
-- declaration of program ROM used by data capture processor
108
-109
component fc_ctrl
110
Port (
address : in std_logic_vector(9 downto 0);
111
instruction : out std_logic_vector(17 downto 0);
112
proc_reset : out std_logic;
--JTAG Loader version
113
clk : in std_logic);
114
end component;
115
116
117

Page 2

Tue Oct 04 20:29:23 2011


frequency_counter.vhd
118
119
120
121
-122
-----------------------------------------------------------------------------------123
-124
-- Signals used to select and provide sources to be analysed
125
-126
signal source_control
: std_logic_vector(7 downto 0);
127
signal dcm_oscillator
: std_logic;
128
signal ring_oscillator
: std_logic;
129
signal freq_for_measurement
: std_logic;
130
signal test_clk
: std_logic;
131
-132
-133
-134
-135
-- Signals used by clock cycle counters and controls
136
-137
signal ab_switch_delay
: std_logic_vector (3 downto 0);
138
signal a_count_ce
: std_logic;
139
signal a_count_rst
: std_logic;
140
signal a_count
: std_logic_vector (31 downto 0);
141
signal b_count_ce
: std_logic;
142
signal b_count_rst
: std_logic;
143
signal b_count
: std_logic_vector (31 downto 0);
144
-145
-146
-147
-- Signals for 1 second interrupt generation and counter switching
148
-149
signal one_second_count
: integer range 0 to 49999999 :=0;
150
signal one_second_pulse
: std_logic;
151
signal ab_switch
: std_logic;
152
signal interrupt_delay
: std_logic_vector (99 downto 0);
153
-154
-155
-- Signals used to connect KCPSM3 to program ROM and I/O logic
156
-157
signal address
: std_logic_vector(9 downto 0);
158
signal instruction
: std_logic_vector(17 downto 0);
159
signal port_id
: std_logic_vector(7 downto 0);
160
signal out_port
: std_logic_vector(7 downto 0);
161
signal in_port
: std_logic_vector(7 downto 0);
162
signal write_strobe
: std_logic;
163
signal read_strobe
: std_logic;
164
signal interrupt
: std_logic;
165
signal interrupt_ack : std_logic;
166
signal reset
: std_logic;
167
-168
-169
-- Signals for LCD operation
170
-171
-- Tri-state output requires internal signals
172
-- 'lcd_drive' is used to differentiate between LCD and StrataFLASH communications
173
-- which share the same data bits.
174
-175
signal
lcd_rw_control : std_logic;
176
signal lcd_output_data : std_logic_vector(7 downto 4);
177
signal
lcd_drive : std_logic;
178
--

Page 3

Tue Oct 04 20:29:23 2011


frequency_counter.vhd
179
-180
-181
------------------------------------------------------------------------------------------------------------------------------------------------------------------182
-183
-- Start of circuit description
184
-185
begin
186
-187
-188
----------------------------------------------------------------------------------------------------------------------------189
-- Disable unused components
190
----------------------------------------------------------------------------------------------------------------------------191
-192
--StrataFLASH must be disabled to prevent it conflicting with the LCD display
193
-194
strataflash_oe <= '1';
195
strataflash_ce <= '1';
196
strataflash_we <= '1';
197
-198
-199
----------------------------------------------------------------------------------------------------------------------------200
-- Select and Buffer signal to be analysed
201
----------------------------------------------------------------------------------------------------------------------------202
-203
-204
205
206
207
208
-209
-- Source selection multiplexer (must be combinatorial)
210
-211
212
freq_for_measurement <= sma_clk when (source_control(1 downto 0)="00")
213
else clk_50mhz when (source_control(1 downto 0)="01")
214
else dcm_oscillator when (source_control(1 downto 0)="10")
215
else ring_oscillator;
216
217
218
-219
-- Global buffer on selected source
220
-221
222
buffer_clkin: BUFG
223
port map( O => test_clk,
224
I => freq_for_measurement);
225
226
-227
----------------------------------------------------------------------------------------------------------------------------228
-- Frequency Counters

Page 4

Tue Oct 04 20:29:23 2011


frequency_counter.vhd
229
-230
-- This is formed of two simple 32-bit binary counters such that one can be counting
whilst the
231
-- other is being read and reset. Great care is taken to ensure the switch over between
the two
232
-- counters is clean and that no clock cycles are missed or glitches generated.
233
-234
-- An asynchronous reset is provided and will be controlled by PicoBlaze using a long
235
-- pulse when the counter is disabled. Hence there is no special synchronisation on thi
control.
236
-237
----------------------------------------------------------------------------------------------------------------------------238
-239
240
counter_switch_control: process(test_clk)
241
begin
242
if test_clk'event and test_clk='1' then
243
244
-- Four stage register to ensure synhchronisation of control between clock domains
245
ab_switch_delay <= ab_switch_delay(2 downto 0) & ab_switch;
246
247
-- Separate enables form switch between counters when control is consistantly high
low.
248
249
case ab_switch_delay(3 downto 1) is
250
251
when "000" => a_count_ce <= '1';
252
b_count_ce <= '0';
253
254
when "111" => a_count_ce <= '0';
255
b_count_ce <= '1';
256
257
when others => a_count_ce <= a_count_ce;
258
b_count_ce <= b_count_ce;
259
260
end case;
261
262
end if;
263
end process counter_switch_control;
264
265
-- 32-bit counters
266
267
test_counter_a: process(test_clk, a_count_rst )
268
begin
269
if a_count_rst='1' then
270
a_count <= X"00000000";
271
elsif test_clk'event and test_clk='1' then
272
if a_count_ce='1' then
273
a_count <= a_count + 1;
274
else
275
a_count <= a_count;
276
end if;
277
end if;
278
end process test_counter_a;
279
280
test_counter_b: process(test_clk, b_count_rst )
281
begin
282
if b_count_rst='1' then
283
b_count <= X"00000000";

Page 5

Tue Oct 04 20:29:23 2011


frequency_counter.vhd
284
elsif test_clk'event and test_clk='1' then
285
if b_count_ce='1' then
286
b_count <= b_count + 1;
287
else
288
b_count <= b_count;
289
end if;
290
end if;
291
end process test_counter_b;
292
293
294
-295
----------------------------------------------------------------------------------------------------------------------------296
-- One Second Timer and Circuit Control
297
-298
-- Using the normal 50MHz clock source, this circuit generates a 1 second timer which i
used to
299
-- switch the enable from one counter to the other.
300
-301
-- A short delay is then inserted to ensure that the switch has taken place before
interrupting the
302
-- PicoBlaze processor. This ensures that the counters are switched and stable for
reading etc.
303
-- Note: This could cause an issue when very low frequency signals are being measured.
304
-305
----------------------------------------------------------------------------------------------------------------------------306
-307
one_second_logic: process(clk_50mhz)
308
begin
309
if clk_50mhz'event and clk_50mhz='1' then
310
311
if one_second_count=49999999 then
--divide by 50,000,000 is 1s
312
one_second_count <= 0;
313
one_second_pulse <= '1';
314
else
315
one_second_count <= one_second_count + 1;
316
one_second_pulse <= '0';
317
end if;
318
319
-- delay of 100 clock cycles before generating interrupt
320
interrupt_delay <= interrupt_delay(98 downto 0) & one_second_pulse;
321
322
-- processor interrupt waits for an acknowledgement
323
if interrupt_ack='1' then
324
interrupt <= '0';
325
elsif interrupt_delay(99) ='1' then
326
interrupt <= '1';
327
else
328
interrupt <= interrupt;
329
end if;
330
331
-- counter selection switch toggles each second
332
if one_second_pulse='1' then
333
ab_switch <= not ab_switch;
334
end if;
335
336
end if;
337

Page 6

Tue Oct 04 20:29:23 2011


frequency_counter.vhd
338
end process one_second_logic;
339
340
-341
----------------------------------------------------------------------------------------------------------------------------342
-- KCPSM3 and the program memory used for capturing data from the counters
343
----------------------------------------------------------------------------------------------------------------------------344
-345
346
processor: kcpsm3
347
port map(
address => address,
348
instruction => instruction,
349
port_id => port_id,
350
write_strobe => write_strobe,
351
out_port => out_port,
352
read_strobe => read_strobe,
353
in_port => in_port,
354
interrupt => interrupt,
355
interrupt_ack => interrupt_ack,
356
reset => reset,
357
clk => clk_50mhz);
358
359
program_rom: fc_ctrl
360
port map(
address => address,
361
instruction => instruction,
362
proc_reset => reset,
--JTAG Loader version
363
clk => clk_50mhz);
364
365
--reset <= '0'; --When using normal version
366
-367
----------------------------------------------------------------------------------------------------------------------------368
-- Capture processor input ports
369
----------------------------------------------------------------------------------------------------------------------------370
-371
-372
-- The inputs are connected via a pipelined multiplexer
373
-374
375
input_ports: process(clk_50mhz)
376
begin
377
if clk_50mhz'event and clk_50mhz='1' then
378
379
case port_id(7 downto 4) is
380
381
-- read A-counter for addresses 00, 10, 20 and 30 hex
382
when "0000" =>
in_port <= a_count(7 downto 0);
383
when "0001" =>
in_port <= a_count(15 downto 8);
384
when "0010" =>
in_port <= a_count(23 downto 16);
385
when "0011" =>
in_port <= a_count(31 downto 24);
386
387
-- read B-counter for addresses 40, 50, 60 and 70 hex
388
when "0100" =>
in_port <= b_count(7 downto 0);
389
when "0101" =>
in_port <= b_count(15 downto 8);
390
when "0110" =>
in_port <= b_count(23 downto 16);

Page 7

Tue Oct 04 20:29:23 2011


frequency_counter.vhd
391
when "0111" =>
in_port <= b_count(31 downto 24);
392
393
-- read slide switches and counter circuit status at address 80 hex
394
when "1000" =>
in_port <= "000" & ab_switch & sw;
395
396
-- read LCD data at address 90 hex
397
when "1001" =>
in_port <= lcd_d & "0000";
398
399
-- Don't care used to ensure minimum logic
400
when others =>
in_port <= "XXXXXXXX";
401
402
end case;
403
404
end if;
405
406
end process input_ports;
407
408
409
-410
----------------------------------------------------------------------------------------------------------------------------411
-- Capture processor output ports
412
----------------------------------------------------------------------------------------------------------------------------413
-414
415
output_ports: process(clk_50mhz)
416
begin
417
418
if clk_50mhz'event and clk_50mhz='1' then
419
if write_strobe='1' then
420
421
-- LED register at address 01 hex
422
if port_id(0)='1' then
423
led <= out_port;
424
end if;
425
426
-- Counter reset controls at address 02 hex
427
if port_id(1)='1' then
428
a_count_rst <= out_port(0);
429
b_count_rst <= out_port(1);
430
end if;
431
432
-- LCD data output and controls at address 04 hex.
433
434
if port_id(2)='1' then
435
lcd_output_data <= out_port(7 downto 4);
436
lcd_drive <= out_port(3);
437
lcd_rs <= out_port(2);
438
lcd_rw_control <= out_port(1);
439
lcd_e <= out_port(0);
440
end if;
441
442
-- Source selection and control at address 08 hex.
443
444
if port_id(3)='1' then
445
source_control <= out_port;
446
end if;
447

Page 8

Tue Oct 04 20:29:23 2011


frequency_counter.vhd
448
end if;
449
end if;
450
451
end process output_ports;
452
453
-454
-455
----------------------------------------------------------------------------------------------------------------------------456
-- LCD interface
457
----------------------------------------------------------------------------------------------------------------------------458
-459
-- The 4-bit data port is bidirectional.
460
-- lcd_rw is '1' for read and '0' for write
461
-- lcd_drive is like a master enable signal which prevents either the
462
-- FPGA outputs or the LCD display driving the data lines.
463
-464
--Control of read and write signal
465
lcd_rw <= lcd_rw_control and lcd_drive;
466
467
--use read/write control to enable output buffers.
468
lcd_d <= lcd_output_data when (lcd_rw_control='0' and lcd_drive='1') else "ZZZZ";
469
470
----------------------------------------------------------------------------------------------------------------------------471
472
473
------------------------------------------------------------------------------------------------------------------------------474
475
end Behavioral;
476
477
------------------------------------------------------------------------------------------------------------------------------478
-479
-- END OF FILE frequency_counter.vhd
480
-481
------------------------------------------------------------------------------------------------------------------------------482
483

Page 9

You might also like