📄 frequency_counter.vhd
字号:
-- counters is clean and that no clock cycles are missed or glitches generated.
--
-- An asynchronous reset is provided and will be controlled by PicoBlaze using a long
-- pulse when the counter is disabled. Hence there is no special synchronisation on this control.
--
----------------------------------------------------------------------------------------------------------------------------------
--
counter_switch_control: process(test_clk)
begin
if test_clk'event and test_clk='1' then
-- Four stage register to ensure synhchronisation of control between clock domains
ab_switch_delay <= ab_switch_delay(2 downto 0) & ab_switch;
-- Separate enables form switch between counters when control is consistantly high or low.
case ab_switch_delay(3 downto 1) is
when "000" => a_count_ce <= '1';
b_count_ce <= '0';
when "111" => a_count_ce <= '0';
b_count_ce <= '1';
when others => a_count_ce <= a_count_ce;
b_count_ce <= b_count_ce;
end case;
end if;
end process counter_switch_control;
-- 32-bit counters
test_counter_a: process(test_clk, a_count_rst )
begin
if a_count_rst='1' then
a_count <= X"00000000";
elsif test_clk'event and test_clk='1' then
if a_count_ce='1' then
a_count <= a_count + 1;
else
a_count <= a_count;
end if;
end if;
end process test_counter_a;
test_counter_b: process(test_clk, b_count_rst )
begin
if b_count_rst='1' then
b_count <= X"00000000";
elsif test_clk'event and test_clk='1' then
if b_count_ce='1' then
b_count <= b_count + 1;
else
b_count <= b_count;
end if;
end if;
end process test_counter_b;
--
----------------------------------------------------------------------------------------------------------------------------------
-- One Second Timer and Circuit Control
--
-- Using the normal 50MHz clock source, this circuit generates a 1 second timer which is used to
-- switch the enable from one counter to the other.
--
-- A short delay is then inserted to ensure that the switch has taken place before interrupting the
-- PicoBlaze processor. This ensures that the counters are switched and stable for reading etc.
-- Note: This could cause an issue when very low frequency signals are being measured.
--
----------------------------------------------------------------------------------------------------------------------------------
--
one_second_logic: process(clk_50mhz)
begin
if clk_50mhz'event and clk_50mhz='1' then
if one_second_count=49999999 then --divide by 50,000,000 is 1s
one_second_count <= 0;
one_second_pulse <= '1';
else
one_second_count <= one_second_count + 1;
one_second_pulse <= '0';
end if;
-- delay of 100 clock cycles before generating interrupt
interrupt_delay <= interrupt_delay(98 downto 0) & one_second_pulse;
-- processor interrupt waits for an acknowledgement
if interrupt_ack='1' then
interrupt <= '0';
elsif interrupt_delay(99) ='1' then
interrupt <= '1';
else
interrupt <= interrupt;
end if;
-- counter selection switch toggles each second
if one_second_pulse='1' then
ab_switch <= not ab_switch;
end if;
end if;
end process one_second_logic;
--
----------------------------------------------------------------------------------------------------------------------------------
-- KCPSM3 and the program memory used for capturing data from the counters
----------------------------------------------------------------------------------------------------------------------------------
--
processor: kcpsm3
port map( address => address,
instruction => instruction,
port_id => port_id,
write_strobe => write_strobe,
out_port => out_port,
read_strobe => read_strobe,
in_port => in_port,
interrupt => interrupt,
interrupt_ack => interrupt_ack,
reset => reset,
clk => clk_50mhz);
program_rom: fc_ctrl
port map( address => address,
instruction => instruction,
proc_reset => reset, --JTAG Loader version
clk => clk_50mhz);
--reset <= '0'; --When using normal version
--
----------------------------------------------------------------------------------------------------------------------------------
-- Capture processor input ports
----------------------------------------------------------------------------------------------------------------------------------
--
--
-- The inputs are connected via a pipelined multiplexer
--
input_ports: process(clk_50mhz)
begin
if clk_50mhz'event and clk_50mhz='1' then
case port_id(7 downto 4) is
-- read A-counter for addresses 00, 10, 20 and 30 hex
when "0000" => in_port <= a_count(7 downto 0);
when "0001" => in_port <= a_count(15 downto 8);
when "0010" => in_port <= a_count(23 downto 16);
when "0011" => in_port <= a_count(31 downto 24);
-- read B-counter for addresses 40, 50, 60 and 70 hex
when "0100" => in_port <= b_count(7 downto 0);
when "0101" => in_port <= b_count(15 downto 8);
when "0110" => in_port <= b_count(23 downto 16);
when "0111" => in_port <= b_count(31 downto 24);
-- read slide switches and counter circuit status at address 80 hex
when "1000" => in_port <= "000" & ab_switch & sw;
-- read LCD data at address 90 hex
when "1001" => in_port <= lcd_d & "0000";
-- Don't care used to ensure minimum logic
when others => in_port <= "XXXXXXXX";
end case;
end if;
end process input_ports;
--
----------------------------------------------------------------------------------------------------------------------------------
-- Capture processor output ports
----------------------------------------------------------------------------------------------------------------------------------
--
output_ports: process(clk_50mhz)
begin
if clk_50mhz'event and clk_50mhz='1' then
if write_strobe='1' then
-- LED register at address 01 hex
if port_id(0)='1' then
led <= out_port;
end if;
-- Counter reset controls at address 02 hex
if port_id(1)='1' then
a_count_rst <= out_port(0);
b_count_rst <= out_port(1);
end if;
-- LCD data output and controls at address 04 hex.
if port_id(2)='1' then
lcd_output_data <= out_port(7 downto 4);
lcd_drive <= out_port(3);
lcd_rs <= out_port(2);
lcd_rw_control <= out_port(1);
lcd_e <= out_port(0);
end if;
-- Source selection and control at address 08 hex.
if port_id(3)='1' then
source_control <= out_port;
end if;
end if;
end if;
end process output_ports;
--
--
----------------------------------------------------------------------------------------------------------------------------------
-- LCD interface
----------------------------------------------------------------------------------------------------------------------------------
--
-- The 4-bit data port is bidirectional.
-- lcd_rw is '1' for read and '0' for write
-- lcd_drive is like a master enable signal which prevents either the
-- FPGA outputs or the LCD display driving the data lines.
--
--Control of read and write signal
lcd_rw <= lcd_rw_control and lcd_drive;
--use read/write control to enable output buffers.
lcd_d <= lcd_output_data when (lcd_rw_control='0' and lcd_drive='1') else "ZZZZ";
----------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------
end Behavioral;
------------------------------------------------------------------------------------------------------------------------------------
--
-- END OF FILE frequency_counter.vhd
--
------------------------------------------------------------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -