VHDL driving signal from different processes

前端 未结 5 1064
醉梦人生
醉梦人生 2021-01-04 12:22

I have a little problem with following VHDL code:

process (zbroji)
begin
    if rising_edge(zbroji) then
        oduzima <= \'0\';
        ucitanPrvi <         


        
5条回答
  •  刺人心
    刺人心 (楼主)
    2021-01-04 12:50

    If you want to synthesize your design for a real FPGA or ASIC, you are going to have to think of VHDL in terms of real hardware (wires, flip flops, gates, etc.). Also, if you want to perform a real rising edge detect in hardware, you will need a system clock that drives a flip flop. Given your original code sample, it doesn't seem that zbroji or oduzmi are system clocks, but just std_logic signals. I wrote this code example assuming basic functionality from your example, hopefully, you can take my code and comments and accomplish what you need.

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    
    entity example is
      port (Reset      : in  std_logic;
            SysClk     : in  std_logic;
            zbroji     : in  std_logic;
            oduzmi     : in  std_logic;
            ulaz_broj  : in  std_logic;
            oduzima    : out std_logic;
            ucitanPrvi : out std_logic;
            broj1      : out std_logic
            );
    
    end example;
    
    architecture Behavioral of example is
    
      -- Delayed version of input signals (1 clock cycle delay)
      signal zbroji_d : std_logic;
      signal oduzmi_d : std_logic;
    
      signal zbrojiRE : std_logic;
      signal oduzmiRE : std_logic;
    
    begin
    
      -- Generate 1 clock cycle delayed version of
      -- signals we want to detect the rising edge
      -- Assumes active high reset
      -- Note: You should only use the rising_edge macro
      -- on an actual global or regional clock signal. FPGA's and
      -- ASICs place timing constraints on defined clock signals
      -- that make it possible to use rising_edge, otherwise, we have
      -- to generate our own rising edge signals by comparing delayed
      -- versions of a signal with the current signal.
      -- Also, with any respectable synthesizer / simulator using
      -- rising_edge is almos exactly the same as (clk'event and clk='1')
      -- except rising_edge only returns a '1' when the clock makes a
      -- valid '0' to '1' transition. (see link below)
      EdgeDetectProc : process (Reset, SysClk)
      begin
        if Reset = '1' then
          zbroji_d <= '0';
          oduzmi_d <= '0';
        elsif rising_edge(SysClk) then
          zbroji_d <= zbroji;
          oduzmi_d <= oduzmi;
        end if;
      end process EdgeDetectProc;
    
      -- Assert risinge edge signals for one clock cycle 
      zbrojiRE <= '1' when zbroji = '1' and zbroji_d = '0' else '0';
      oduzmiRE <= '1' when oduzmi = '1' and oduzmi_d = '0' else '0';
    
      -- Assumes that you want a single cycle pulse on ucitanPrvi on the
      -- rising edege of zbroji or oduzmi;
      ucitanPrvi <= zbrojiRE or oduzmiRE;
    
      -- Based on your example, I can't tell what you want to do with the
      -- broj1 signal, but this logic will drive broj1 with ulaz_broj on
      -- either the zbroji or oduzmi rising edge, otherwise '0'.
      broj1 <= ulaz_broj when zbrojiRE = '1' else
               ulaz_broj when oduzmiRE = '1' else
               '0';
    
      -- Finally, it looks like you want to clear oduzima on the rising
      -- edge of zbroji and assert oduzima on the rising edge of
      -- oduzmi
      LatchProc : process (Reset, SysClk)
      begin
        if Reset = '1' then
          oduzima <= '0';
        elsif rising_edge(SysClk) then
          if zbrojiRE = '1' then
            oduzima <= '0';
          elsif oduzmiRE = '1' then
            oduzima <= '1';
          end if;
        end if;
      end process LatchProc;
    
    end Behavioral;
    

    The previous code assumes you have a system clock. In a simulator like ModelSim (free student edition), you can generate a 100 MHz clock with non-synthesizable testbench code like this...

    ClockProc : process
    begin 
       SysClk <= '0';
       wait for 5 ns;
       SysClk <= '1';
       wait for 5 ns;
    end process ClockProc;
    

    In an actual FPGA/ASIC implementation, you will probably want to use an external oscillator that you run into your chip, drive the signal into a DCM (Digital clock manager), which will output a very clean clock signal to all of your VHDL logic, so you can have a glitch free design.

    And finally, here is a great explanation on the differences between rising_edge and (clk'event and clk='1')

    http://vhdlguru.blogspot.com/2010/04/difference-between-risingedgeclk-and.html

    Hope that helps.

提交回复
热议问题