سلام.
لطفا منو در نوشتن یک کد vhdl برای جمع دو فرکانس ورودی که به صورت کلاکند کمک کنید.
:cry2: :cry2: :cry2:
لطفا منو در نوشتن یک کد vhdl برای جمع دو فرکانس ورودی که به صورت کلاکند کمک کنید.
:cry2: :cry2: :cry2:
--
--
-- AUTO-RANGING Single Chip Frequency Counter
--
-- This is a synthesizable model of an autoranging frequency counter.
-- The overall frequency counting coverage is from DC~9.999MHz. There are
-- four ranges, which are "auto" selected:
--
-- frequency GATE width
-- DC-9999Hz, 1 sec
-- 10.00KHz-99.99KHz, .1 sec
-- 100.0KHz-999.9KHz. .01 sec
-- 1.000MHz-9.999MHz .001 sec
--
--
-- Top level chip-interface is as follows:
--
-- Input:
-- sys_rs_l std_logic asynchronous actuve low reset
-- ref_clk std_logic 10MHz reference clock input
-- Funknown std_logic reference clock input from DC - 10Mhz
--
-- Output
-- gate0_l std_logic one's place 7segment LED common anode gate
-- gate1_l std_logic ten's place 6segment LED common anode gate
-- gate2_l std_logic hundred's place 7segment LED common anode gate
-- gate3_l std_logic thousand's place 6segment LED common anode gate
--
--
--
-- OPERATION
--
-- This frequency counter is based on the premise of counting the incoming unknown
-- frequency's rising edge for a predetermined fixed amount of time, or GATE.
-- If the counter overflow , then the presently selected GATE is too wide, so the
-- next shortest GATE width is selected. This switching is done immediately, so
-- that no time is wasted in waiting for the GATE to turn off.
-- The measured frequency data is then displayed onto a multiplexed 4 digit 7segment
-- LED display. Since the LED display is refhreshed at 100KHz, a fixed time interval
-- is waited before the next conversion cycle. This gives the display a chance to
-- "update" all the segments.
--
--
-- STATE TRANSITION
--
-- /------\
-- | |
-- | IDLE
-- | |
-- | /-- |
-- | | \ V overflow=HI
-- | | GATE_ON ----------------> OVERFLOW
-- | \--/ | |
-- | | |
-- | | gate_counter=N |
-- | | |
-- | V |
-- | DISPLAY |
-- | | |
-- | | |
-- | /-- | |
-- | | \ V |
-- | | DELAY <----------------------/
-- | \--/ |
-- \-------/
-- gate_counter=N2
--
-- IDLE state
-- This state hold the BCD counter in reset state then transitions
-- into the next state, GATE_ON. The BCD counter must be hold into reset
-- in order not to accumulate from the previous count cycle
--
-- GATE_ON state
-- In this state, the BCD counter is allowed to start counting by asserting
-- the signal 'GATE'. Also, an internal timer is started which times
-- the time for which the GATE should be on for. Go to next state when
-- the timer hits the expected tick count
--
-- DISPLAY state
-- In this state, the 4 digit muxed display is "refreshed", that is loaded with
-- the new data from the BCD counter
--
-- DELAY state
-- This state simply waits for a fixed delay. This fixed delay is required
-- in order to give the display a chance to cycle through the segment refreshing
--
-- OVERFLOW state
-- This state enters when the BCD counter overflows with the given GATE. This
-- means that the GATE is too long, so the next shortest gate length is chosen
-- and the measurement starts over again.
--
--
--
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_unsigned.all;
ENTITY freq_counter IS
PORT (
sys_rst_l : IN std_logic;
ref_clk : IN std_logic;
Funknown : IN std_logic;
gate0_l : OUT std_logic;
gate1_l : OUT std_logic;
gate2_l : OUT std_logic;
gate3_l : OUT std_logic;
digit_out_l : OUT std_logic_vector (7 downto 0);
-- debug
d_gate : OUT std_logic;
d_gate_cnt_limit : OUT integer range 0 to 10000000;
d_f_counter_count_out : OUT std_logic_vector (15 downto 0);
d_f_overflow : OUT std_logic
);
END freq_counter;
ARCHITECTURE FREQ_COUNTER_RTL OF freq_counter IS
-- Declare the 4 digit muxed 7segment LED display DISPLAY
COMPONENT disp4_muxed
PORT ( clk_disp : IN std_logic;
clk_ref : IN std_logic;
sys_rst_l : IN std_logic;
data_in : IN std_logic_vector (15 downto 0);
dp_in : IN std_logic_vector ( 1 downto 0);
load : IN std_logic;
gate0_l : OUT std_logic;
gate1_l : OUT std_logic;
gate2_l : OUT std_logic;
gate3_l : OUT std_logic;
digit_out_l: OUT std_logic_vector (7 downto 0) -- MSB=dp,g,f,.., LSB=a
);
END COMPONENT;
-- Declare the 4 digit BCD counter
COMPONENT bcdcounter4
PORT ( Funknown : IN std_logic;
sys_rst_l : IN std_logic;
GATE : IN std_logic;
ready : OUT std_logic;
data_out : OUT std_logic_vector (15 downto 0);
overflow : OUT std_logic
);
END COMPONENT;
CONSTANT HIGH : std_logic := '1';
CONSTANT LOW : std_logic := '0';
TYPE allowed_states IS (idle, gate_on, display, delay, overflow);
SIGNAL state : allowed_states;
SIGNAL display_load : std_logic;
SIGNAL gate : std_logic;
SIGNAL f_ready : std_logic;
SIGNAL f_counter_count_out : std_logic_vector (15 downto 0);
SIGNAL f_overflow : std_logic;
SIGNAL clk_100Khz : std_logic;
SIGNAL scaler : std_logic_vector (2 downto 0);
SIGNAL auto_scale : std_logic_vector (2 downto 0);
SIGNAL gate_counter : integer RANGE 0 TO 10000000; -- 24 bits
SIGNAL GATE_CNT_LIMIT : integer RANGE 0 TO 10000000;
SIGNAL cnt_ena : std_logic;
SIGNAL counter_reset : std_logic;
-- RTL BEGINS HERE
BEGIN
-- debug signals (turn them off if yuo do not need them
-- these were on for helping simulation)
d_gate <= gate;
d_gate_cnt_limit <= gate_cnt_limit;
d_f_counter_count_out <= f_counter_count_out;
d_f_overflow <= f_overflow;
-- Connect the subcomponenet
THE_DISPLAY: disp4_muxed PORT MAP (clk_disp => clk_100Khz,
clk_ref => ref_clk,
sys_rst_l => sys_rst_l,
data_in => f_counter_count_out,
dp_in => NOT (auto_scale(1 downto 0)),
load => display_load,
gate0_l => gate0_l,
gate1_l => gate1_l,
gate2_l => gate2_l,
gate3_l => gate3_l,
digit_out_l => digit_out_l );
-- COnnect the 4 digit BCD counter
THE_COUNTER: bcdcounter4 PORT MAP (Funknown => Funknown,
sys_rst_l => counter_reset,
GATE => gate,
ready => f_ready,
data_out => f_counter_count_out,
overflow => f_overflow );
-- CONTROLLER STATE MACHINE
--
SM: PROCESS (sys_rst_l, ref_clk)
BEGIN
-- on reset clear the world
IF (sys_rst_l=LOW) THEN
state <= idle;
scaler <= "000";
auto_scale <= "000";
gate <= LOW;
cnt_ena <= LOW;
display_load <= LOW;
counter_reset <= LOW; -- reset the fcounter
-- on every rising edge of ref_clk (10MHz)
ELSIF (ref_clk=HIGH and ref_clk'EVENT) THEN
CASE (state) IS
-- IDLE state
-- goto next state
WHEN idle =>
state <= gate_on;
counter_reset <= LOW; -- reset the fcounter
-- GATE_ON state
-- turn on the "gate" which the BCD counter will count clk pulses
WHEN gate_on =>
counter_reset <= HIGH;
gate <= HIGH; -- GATE is high
cnt_ena <= HIGH; -- GATE counter is enabled
-- if the gate counter reaches the gate time limit, goto next state
IF (gate_counter=GATE_CNT_LIMIT) THEN
gate <= LOW; -- turn off gate
cnt_ena <= LOW; -- turn off gate counter
state <= display;
auto_scale <= "000";
-- if the BCD counter has overflowed, go to overflow state
ELSIF (f_overflow=HIGH) THEN
state <= overflow;
END IF;
-- DISPLAY state
-- go and "refresh" the display
WHEN display =>
display_load <= HIGH; -- load the display with the recent BCD counter
state <= delay;
-- DELAY state
-- wait here for a bit, to give the muxed LED display a chance
-- to go through its mux cycle
WHEN delay =>
scaler <= "100"; -- set delay to be just the display delay
cnt_ena <= HIGH; -- enable gate counter
display_load <= LOW; -- stop with the loading..
-- when the counter has hit the time limit go to next state
IF (gate_counter=GATE_CNT_LIMIT) THEN
cnt_ena <= LOW; -- turn off gate counter
scaler <= auto_scale;
state <= idle;
END IF;
-- OVERFLOW state
-- when the BCD counter has overflowed with the current gate width,
-- select the next shortest gate (1sec, .1sec, .01sec and .001 sec)
-- and remeasure it.
WHEN overflow =>
CASE (auto_scale) IS
WHEN "000" => auto_scale <= "001";
WHEN "001" => auto_scale <= "010";
WHEN "010" => auto_scale <= "011";
WHEN "011" => auto_scale <= "011";
WHEN OTHERS => NULL;
END CASE;
gate <= LOW; -- turn off gate
cnt_ena <= LOW;
state <= delay;
END CASE;
END IF;
END PROCESS SM;
-- GATE WIDTH SELECTOR
-- This process selects the width of the GATE signal, by selecting
-- the ticks which will equal the reference time. The ticks is
-- based on 100nS period (10MHz). IF you're using a differenct clock, you need to
-- change the below 5 values
PROCESS (scaler)
BEGIN
CASE (scaler) IS
WHEN "000" =>
GATE_CNT_LIMIT <= 10000000; -- 10 million cycles per GATE of 1 SECOND
WHEN "001" =>
GATE_CNT_LIMIT <= 1000000; -- 1 million cycles per GATE of .1 SECOND
WHEN "010" =>
GATE_CNT_LIMIT <= 100000; -- 100K cycles per GATE of .01 SECOND
WHEN "011" =>
GATE_CNT_LIMIT <= 10000; -- 10K cycles per GATE of .001 SECOND
WHEN "100" =>
GATE_CNT_LIMIT <= 50000; -- 50000 a bit of delay, for LED mux disp refresh
WHEN OTHERS =>
NULL;
END CASE;
END PROCESS;
-- TIMER
-- This timer is enabled when "ent_ena" signal is asserted.
-- Synchronous to the 10MHZ clock, on the rising edge
PROCESS (cnt_ena, ref_clk )
BEGIN
IF (cnt_ena=LOW) THEN
gate_counter <= 0;
ELSIF (ref_clk=HIGH and ref_clk'EVENT) THEN
gate_counter <= gate_counter + 1;
END IF;
END PROCESS;
-- 100KHz clock generator
-- This is a divider which gnerates 100KHz clock from the 10MHz clock in
-- The 100KHz clock is used on the LED display segment refreshing
PROCESS (sys_rst_l, ref_clk)
VARIABLE counter : INTEGER range 0 TO 50;
BEGIN
IF (sys_rst_l='0') THEN -- active low, asynchronous reset
clk_100KHZ <= '0';
counter := 0;
ELSIF (ref_clk='1' AND ref_clk'EVENT) THEN -- toggle at 50 ticks of 100nS
IF (counter=50) THEN
clk_100KHZ <= NOT clk_100KHZ;
counter := 0;
ELSE
counter := counter + 1;
END IF;
END IF;
END PROCESS;
END FREQ_COUNTER_RTL;
دیدگاه