0

我想对来自 FPGA spartan 3 的外部数字数据进行采样。我最初想以 1000 个样本/秒的速度进行采样。如何在 vhdl 编码中选择时钟频率?

谢谢。

4

3 回答 3

5

Do not use a counter to generate a lower frequency clock signal.

Multiple clock frequencies in an FPGA cause a variety of design problems, some of which come under the heading of "advanced topics" and, while they can (if necessary) all be dealt with and solved, learning how to use a single fast clock is both simpler and generally better practice (synchronous design).

Instead, use whatever fast clock your FPGA board provides, and generate lower frequency timing signals from it, and - crucially - use them as clock enables, not clock signals.

DLLs, DCMs, PLLs and other clock managers do have their uses, but generating 1 kHz clock signals is generally not a good use, even if their limitations permit it. This application is just crying out for a clock enable...

Also, don't mess around with magic numbers, let the VHDL compiler do the work! I have put the timing requirements in a package, so you can share them with the testbench and anything else that needs to use them.

package timing is

    -- Change the first two constants to match your system requirements...
    constant Clock_Freq  : real := 40.0E6;
    constant Sample_Rate : real := 1000.0;

    -- These are calculated from the above, so stay correct when you make changes
    constant Divide      : natural := natural(Clock_Freq / Sample_Rate);
    -- sometimes you also need a period, e.g. in a testbench.
    constant clock_period : time := 1 sec / Clock_Freq;

end package timing;

And we can write the sampler as follows: (I have split the clock enable out into a separate process to clarify the use of clock enables, but the two processes could be easily rolled into one for some further simplification; the "sample" signal would then be unnecessary)

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
use work.timing.all;

entity sampler is
    Port (
        Clock   : in  std_logic;
        Reset   : in  std_logic;
        ADC_In  : in  signed(7 downto 0);   
        -- signed for audio, or unsigned, depending on your app
        Sampled : out signed(7 downto 0);   
    );
end sampler;

architecture Behavioral of Sampler is
    signal Sample : std_logic;
begin

    Gen_Sample : process (Clock,Reset) 
    variable Count : natural;
    begin
        if reset = '1' then
            Sample     <= '0';
            Count      := 0;
        elsif rising_edge(Clock) then
            Sample     <= '0';
            Count      := Count + 1;
            if Count = Divide then
                Sample <= '1';
                Count  := 0;
            end if;
        end if;
    end process;

    Sample_Data : process (Clock) 
    begin
        if rising_edge(Clock) then
            if Sample = '1' then
                Sampled <= ADC_In;
            end if;
        end if;
    end process;

end Behavioral;
于 2013-08-10T09:58:21.350 回答
2

基本时钟必须基于外部时钟,不能仅通过 Spartan-3 FPGA 中的内部资源生成。如果需要,您可以使用 Spartan-3 FPGA 数字时钟管理器 (DCM) 资源来调整外部时钟。合成的 VHDL 代码本身不能生成时钟。

一旦有了更高频率的基本时钟,例如 100 MHz,您就可以轻松地将其分频以生成 1 kHz 的指示,用于对外部输入进行采样。

于 2013-08-08T05:02:06.957 回答
1

这取决于您可用的时钟频率。如果你有一个 20MHz 的时钟源,你需要将它除以 20000 以获得 1KHz,你可以用 VHDL 或使用 DCM 来做到这一点。

这是一个关于如何从 20MHz 输入创建 1kHz 时钟的示例:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity clk20Hz is
    Port (
        clk_in : in  STD_LOGIC;
        reset  : in  STD_LOGIC;
        clk_out: out STD_LOGIC
    );
end clk200Hz;

architecture Behavioral of clk20Hz is
    signal temporal: STD_LOGIC;
    signal counter : integer range 0 to 10000 := 0;
begin
    frequency_divider: process (reset, clk_in) begin
        if (reset = '1') then
            temporal <= '0';
            counter <= 0;
        elsif rising_edge(clk_in) then
            if (counter = 10000) then
                temporal <= NOT(temporal);
                counter <= 0;
            else
                counter <= counter + 1;
            end if;
        end if;
    end process;

    clk_out <= temporal;
end Behavioral;
于 2013-08-08T12:01:22.180 回答