⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spi3-aciklamali.txt

📁 vhdl-spi module interface helpful source code
💻 TXT
📖 第 1 页 / 共 2 页
字号:
  signal master_mode : std_ulogic; -- Master mode when 1 
  signal misoe_lcl   : std_ulogic; -- local version 
  signal mosie_lcl   : std_ulogic; -- local version 
  signal oflow       : std_ulogic; 
  signal open_drain  : std_ulogic; 
  signal phase       : std_ulogic; 
  signal polck       : std_ulogic; 
  signal sck_r1      : std_ulogic; 
  signal sck_r2      : std_ulogic; 
  signal sck_r3      : std_ulogic; -- synchronizers 
  signal sel_clk     : std_ulogic_vector(1 downto 0); 
  signal shift_reg   : std_ulogic_vector(7 downto 0); 
  -- THE SPI shift register  
  signal shift_clk   : std_ulogic; 
  signal shift_clk_negedge       : std_ulogic; -- negative edge of SCK 
  signal shift_negative_edge_nxt : std_ulogic; 
  signal shift_negative_edge     : std_ulogic; 
  signal shift_datain  : std_ulogic; 
  signal shift_dataout : std_ulogic; 
  signal slvsel_r1     : std_ulogic; 
  signal slvsel_r2     : std_ulogic; 
  signal slvsel_r3     : std_ulogic; -- synchronizers 
  signal spi_go        : std_ulogic; -- begin a transfer 
  signal ssel          : std_ulogic_vector(7 downto 0); 
  -- slave select register 
  signal status        : std_ulogic_vector(7 downto 0); 
  -- status register 
  signal tx_end        : std_ulogic; 
  -- TX has completed, TX_RUN will go low 
  signal tx_run        : std_ulogic; -- tx is running 
  signal tx_start      : std_ulogic; 
  signal tx_start_r1   : std_ulogic; 
 
begin   --------------------------------------------------------------- 
 
  mosio <= shift_dataout when mosie_lcl='1' and open_drain='0' else 
           '0';  
  mosie <= mosie_lcl when open_drain='0' else 
           '1' when mosie_lcl='1' and shift_dataout='0' else 
           -- drive low when open drain enabled. 
           '0'; 
 
  misoo <= shift_dataout when misoe_lcl='1' and open_drain='0' else 
           '0';  
  misoe <= misoe_lcl when open_drain='0' else 
           '1' when misoe_lcl='1' and shift_dataout='0' else 
           -- drive low when open drain enabled. 
           '0'; 
 
  misoe_lcl <= '1' when master_mode='0' and slvsel='1' else 
               '0'; 
  mosie_lcl <= '1' when master_mode='1' else 
               '0'; 
 
  -- spi_go initiates a transfer - A write to the DOUT reg in master 
  -- mode ignore the CPU write if we're already running. 
  spi_go <= '1' when chip_sel='1' and write='1' and addr="00" and  
                     tx_run='0' and slvsel_r3='0' else 
            '0'; 
 
  sr_proc : process(clk) -------------Shift register---------------- 
  begin 
    if (clk'event and clk='1') then 
      if (rst='1') then 
        shift_reg <= "00000000";   -- sync reset 
      else 
        if (spi_go='1') then -- don't reload while running 
          shift_reg  <= datain;    -- load with data from CPU 
        elsif (shift_clk='1') then 
          shift_reg <= shift_reg(6 downto 0) & shift_datain; 
        end if; 
      end if; 
    end if; 
  end process; 
 
  neg_proc : process(clk) ----------Hold time register-------------- 
  begin 
    if (clk'event and clk='1') then        -- negative edge pipeline DFF 
      if (rst='1') then 
        shift_negative_edge <= '0';     -- sync reset 
      elsif (shift_clk_negedge='1') then 
        shift_negative_edge  <= shift_negative_edge_nxt; 
      elsif (spi_go='1') then 
        shift_negative_edge  <= datain(7); -- preload for phase=0 mode 
      end if; 
    end if; 
  end process; 
 
  shift_negative_edge_nxt <= shift_reg(7) when phase='1' else 
                             misoi when master_mode='1' else 
                             mosii; 
 
  shift_dataout <= shift_negative_edge when phase='1' else 
                   -- add in the negative edge dff on phase=1 
                   shift_reg(7); 
 
  shift_datain <= shift_negative_edge when phase='0' else 
                  -- insert the neg DFF in phase=0 
                  misoi when master_mode='1' else 
                  mosii; 
 
  tr_proc : process(clk) ---------------TX run------------------ 
  -- this bit is active while a transmit is running 
  begin 
    if (clk'event and clk='1') then 
      if (rst='1') then 
        tx_run <= '0';     -- sync reset 
      else 
        if (tx_start='1') then 
          tx_run  <= '1'; 
        elsif (tx_end='1') then 
          tx_run <= '0'; 
        end if; 
      end if; 
    end if; 
  end process; 
 
  bc_proc : process (clk) 
  begin -------------Bit counter for master mode---------------- 
    if (clk'event and clk='1') then 
      if (rst='1') then -- sync reset 
        bit_ctr <= "000";  
      else 
        if (tx_start='1') then 
          bit_ctr <= ssel(7 downto 5); 
        elsif (shift_clk='1') then 
          bit_ctr <= std_ulogic_vector(unsigned(bit_ctr)-1); 
        end if; 
      end if; 
    end if; 
  end process; -- bit counter 
 
  tx_end <= '1' when master_mode='1' and bit_ctr="001" 
                     and shift_clk='1' and tx_run='1' else 
            '0'; 
  tx_start <= '1' when master_mode='1' and spi_go='1' else 
              '0'; 
 
  gjr_proc : process (clk) 
  begin        ---------Control Register---------------------- 
    if (clk'event and clk='1') then 
      if (rst='1') then -- sync reset 
        ctl_reg <= "00000000";  
      else 
        if (chip_sel='1' and write='1' and addr="01") then -- load 
          ctl_reg <= datain; 
        end if; 
      end if; 
    end if; 
  end process; 
 
  -- map the control register to more meaningfull names 
  master_mode <= ctl_reg(1); 
  open_drain  <= ctl_reg(2); 
  polck       <= ctl_reg(3); 
  phase       <= ctl_reg(4); 
  sel_clk     <= ctl_reg(6 downto 5); 
 
  s_proc : process (clk) 
  begin  ---------Slave Select Register------------------------- 
    if (clk'event and clk='1') then 
      if (rst='1') then -- sync reset 
        ssel <= "00000000";  
      else 
        if (chip_sel='1' and write='1' and addr="11") then -- load 
          ssel <= datain; 
        end if; 
      end if; 
    end if; 
  end process; 
  slvselo <= ssel(4 downto 0);    -- drive the port 
  slvsele <= master_mode; 
 
  cf_proc : process (clk) 
  begin ---------Collision flag bit--------------------------- 
    if (clk'event and clk='1') then 
      if (rst='1') then 
        col_flag <= '0'; 
      else 
        if (master_mode='1' and slvsel_r3='1') then 
          col_flag <= '1';         
        elsif (chip_sel='1' and write='1' 
               and addr="10" and datain(5)='1') then 
          col_flag <= '0'; 
        end if; 
      end if; 
    end if; 
  end process; 
 
  o_proc : process (clk) 
  begin ---------OFLOw flag bit------------------------------ 
    if (clk'event and clk='1') then 
      if (rst='1') then 
        oflow <= '0'; 
      else 
        if (chip_sel='1' and write='1' and addr="00" and 
            -- write to DOUT 
            (tx_run='1' or slvsel_r3='1')) then    -- and we're busy 
          oflow <= '1'; 
        elsif (chip_sel='1' and write='1' and addr="10" 
               and datain(6)='1') then 
          oflow <= '0'; 
        end if; 
      end if; 
    end if; 
  end process; 
 
  elr_proc : process (clk) 
  begin ---------IRQ flag bit------------------------------ 
    if (clk'event and clk='1') then 
      if (rst='1') then 
        irq_flag <= '0'; 
      else 
        if (tx_end='1' or (slvsel_r2='0' and slvsel_r3='1')) then 
          irq_flag <= '1';         
        elsif (chip_sel='1' and write='1' and addr="10" 
               and datain(7)='1') then 
          irq_flag <= '0'; 
        end if; 
      end if; 
    end if; 
  end process; 
  irq <= irq_flag and ctl_reg(7); -- gate with the IRQENB bit. 
 
  flops_proc : process (clk) 
  begin      ----------------various pipeline flops--------- 
    if (clk'event and clk='1') then 
      slvsel_r3   <= slvsel_r2; 
      slvsel_r2   <= slvsel_r1;         -- synchronizers 
      slvsel_r1   <= slvsel; 
      sck_r3      <= sck_r2; 
      sck_r2      <= sck_r1;            -- synchronizers 
      sck_r1      <= not scki xor polck; 
      -- select the desired polarity of the slave clk 
      tx_start_r1 <= tx_start; 
    end if; 
  end process; 
 
  dvd_proc : process (clk)  
  begin----------------clock divider for clk generation------- 
    -- create a 2x clock which creates 2 pulses. 
    -- One for each edge of SCK. 
    if (clk'event and clk='1') then 
      if (not (tx_run='1' and master_mode='1') or tx_end='1') then 
        -- divider only runs when sending data 
        dvd_ctr <= "00000";  
        dvd2 <= '0'; 
      else 
        if (dvd_ctr="00000") then 
          if (sel_clk="00") then 
            dvd_ctr <= "00011"; 
          elsif (sel_clk="01") then 
            dvd_ctr <= "00111"; 
          elsif (sel_clk="10") then 
            dvd_ctr <= "01111"; 
          else 
            dvd_ctr <= "11111"; 
          end if; 
          if (tx_start_r1='0') then 
            dvd2 <= not dvd2; 
          end if; 
        else 
          dvd_ctr <= std_ulogic_vector(unsigned(dvd_ctr)-1); 
        end if; 
      end if; 
    end if; 
  end process; -- dvd 
  dvd_zero <= '1' when dvd_ctr="00000" else 
              '0'; 
 
  shift_clk <= dvd_zero and dvd2 and tx_run and not tx_start_r1  
               -- TX_START_R1 prevents data from shifting on the first 
               -- clock in POLCK=1 mode which we don't want.We only get 
               -- 7 clocks otherwise. 
               when master_mode='1' else 
               sck_r2 and not sck_r3; 
 
  shift_clk_negedge <= dvd_zero and not dvd2 and tx_run 
                       when master_mode='1' 
                       else not sck_r2 and sck_r3; 
 
  with addr select 
    dataout <= -- dataout multiplexor for register readback 
               shift_reg  when "00", 
               ctl_reg    when "01", 
               status     when "10", 
               ssel       when "11", 
               "XXXXXXXX" when others; 
 
  -- assemble the bits that make up the status register 
  status <= irq_flag & oflow & col_flag & "000" & tx_run & slvsel_r3; 
 
  scke <= master_mode; 
  scko <= dvd2 xor polck; 
 
end rtl; 
 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -