source: FPGA/FTU/spi_interface/sck_logic_16.vhd @ 156

Last change on this file since 156 was 156, checked in by qweitzel, 11 years ago
First check-in of VHDL code for FTU: counters, dcm, spi
File size: 8.4 KB
Line 
1---------------------------------------------------------------------------------------------
2---------------------------------------------------------------------------------------------
3--  File:          sck_logic_16.vhd
4--
5--
6--  Original file: sck_logic.vhd
7--
8
9--  Created: 8-23-00 ALS
10--  This file generates an internal SCK by dividing the system clock as determined by CLKDIV.
11--  This internal SCK has a CPHA=1 relationship to data and is used to clock the internal SPI
12--  shift register. This internal SCK is used to generate the desired output SCK as determined
13--  by CPHA and CPOL in the control register. The SCK output to the SPI bus is output only when
14--  the slave select signals are asserted, but the internal SCK runs continuously.
15--
16--  Revised: 8-28-00 ALS
17--  Revised: 9-11-00 ALS
18--  Revised: 10-17-00 ALS
19
20---------------------------------------------------------------------------------------------
21---------------------------------------------------------------------------------------------
22--  Modified from 8 to 16 bit word size by Patrick Vogler
23--  18th November 2009
24--
25--       Modifications are marked by: *Mod: <modification>
26--
27--  Cleaned up by Quirin Weitzel
28--  21th January 2010
29---------------------------------------------------------------------------------------------
30---------------------------------------------------------------------------------------------
31library IEEE;
32use IEEE.std_logic_1164.all;
33use IEEE.std_logic_arith.all;
34
35entity sck_logic is
36  port( 
37    -- internal uC interface signals
38    clkdiv     : in    std_logic_vector(1 downto 0);   -- sets the clock divisor for sck clock
39    cpha       : in    std_logic;  -- sets clock phase for output sck clock
40    cpol       : in    std_logic;  -- sets clock polarity for output sck clock
41         
42    -- internal spi interface signals
43    clk0_mask  : in    std_logic;  -- clock mask for sck when cpha=0
44    clk1_mask  : in    std_logic;  -- clock mask for sck when cpha=1
45    sck_1      : inout std_logic;  -- internal sck created from dividing system clock
46    sck_int_re : out   std_logic;  -- rising edge of internal sck
47    sck_int_fe : out   std_logic;  -- falling edge of internal sck
48    sck_re     : out   std_logic;  -- rising edge of external sck
49    sck_fe     : out   std_logic;  -- falling edge of external sck
50    ss_in_int  : in    std_logic;  -- another master is on the bus
51         
52    -- external spi interface signals
53    sck        : inout std_logic;      -- sck as determined by cpha, cpol, and clkdiv
54         
55    -- clock and reset
56    reset      : in    std_logic;  -- active high reset   
57    clk        : in    std_logic   -- clock
58   
59  );
60       
61end sck_logic;
62
63architecture DEFINITION of sck_logic is
64
65--**************************** Constants ***************************************
66
67constant RESET_ACTIVE   : std_logic := '0';
68
69--**************************** Signals ***************************************
70
71signal clk_cnt      : STD_LOGIC_VECTOR(4 downto 0); -- clock divider output
72signal clk_cnt_en   : STD_LOGIC;            -- count enable for clock divider
73signal clk_cnt_rst  : STD_LOGIC;            -- clock count reset
74
75
76signal sck_int_d1   : STD_LOGIC;    -- sck_int delayed one clock for edge detection
77signal sck_int      : STD_LOGIC;    -- version of sck when CPHA=1
78signal sck_0        : STD_LOGIC;    -- version of sck when CPHA=0
79signal sck_out      : STD_LOGIC;    -- sck to be output if SS_IN_INT is not asserted
80signal sck_d1       : std_logic;    -- output sck delayed one clock for edge detection
81
82
83--**************************** Component Definitions  ********************************
84-- 5-bit counter for clock divider
85component upcnt5
86  port(         
87    cnt_en       : in STD_LOGIC;                        -- Count enable                     
88    clr          : in STD_LOGIC;                        -- Active high clear
89    clk          : in STD_LOGIC;                        -- Clock
90    qout         : inout STD_LOGIC_VECTOR (4 downto 0)   
91  );
92       
93end component;
94
95begin
96
97  --************************** Clock Divider Instantiation ********************************
98  CLK_DIVDR : upcnt5
99    port map(         
100      cnt_en       => clk_cnt_en,
101      clr          => clk_cnt_rst,
102      clk          => clk,
103      qout         => clk_cnt
104    );
105  -- This counter is always enabled, can't instantiate the counter with a literal
106  clk_cnt_en <= '1';
107
108  -- Clock counter is reset whenever reset is active and ss_in_int is asserted
109  clk_cnt_rst <= RESET_ACTIVE when reset = RESET_ACTIVE or ss_in_int = '0'
110                 else not(RESET_ACTIVE);
111
112  --************************** Internal SCK Generation ***************************************
113  -- SCK when CPHA=1 is simply the output of the clock divider determined by the CLK_DIV bits
114  -- SCK_INT is based off the CPHA=1 waveforms and is used as the internal SCK
115  -- SCK_INT is used to clock the SPI shift register, therefore, it runs before and after SS_N
116  -- is asserted
117  -- SCK_1 is SCK_INT when clk1_mask = 1. The clock mask blocks SCK_INT edges that are before
118  -- and after SS_N
119  sck_int_process: process (clk,reset)
120  begin
121    if reset = RESET_ACTIVE  then
122      sck_int <= '0';
123    elsif clk'event and clk = '1' then   
124      -- determine clock divider output based on control register
125      case clkdiv is
126        when "00" =>
127          sck_int <= clk_cnt(1);
128        when "01" =>
129          sck_int <= clk_cnt(2);
130        when "10" =>
131          sck_int <= clk_cnt(3);
132        when "11" =>
133          sck_int <= clk_cnt(4);
134        when others =>  -- error in register
135          sck_int <= '0';
136      end case;
137    end if;
138  end process;
139
140  sck_1 <= sck_int and clk1_mask;
141
142  -- Detect rising and falling edges of SCK_1 to use as state transition
143  sck_intedge_process: process(clk, reset)
144  begin
145    if reset = RESET_ACTIVE then
146      sck_int_d1 <= '0';
147    elsif clk'event and clk = '1' then
148      sck_int_d1 <= sck_int;
149    end if;
150  end process;
151
152  sck_int_re <= '1' when sck_int = '1' and sck_int_d1 = '0'
153                else '0';
154  sck_int_fe <= '1' when sck_int = '0' and sck_int_d1 = '1'
155                else '0';
156
157  -- SCK when CPHA=0 is out of phase with internal SCK - therefore its toggle needs to be delayed
158  -- by the signal clk_mask and then its simply an inversion of the counter bit
159
160  sck_0_process: process (clk, reset)
161  begin
162    if reset = RESET_ACTIVE then
163      sck_0 <= '0';
164    elsif clk'event and clk = '1' then       
165      if clk0_mask = '0' then
166        sck_0 <= '0';
167      else
168        case clkdiv is
169          when "00" =>
170            sck_0 <= not(clk_cnt(1));
171          when "01" =>
172            sck_0 <= not(clk_cnt(2));
173          when "10" =>
174            sck_0 <= not(clk_cnt(3));
175          when "11" =>
176            sck_0 <= not(clk_cnt(4));
177          when others =>  -- error in register
178            sck_0 <= '0';
179        end case;
180      end if;
181    end if;
182  end process;
183
184  --************************** External SCK Generation **********************************
185  -- This process outputs SCK based on the CPHA and CPOL parameters set in the control register
186  sck_out_process: process(clk, reset, cpol)
187    variable temp:  std_logic_vector(1 downto 0);
188  begin
189    if reset = RESET_ACTIVE then
190      sck_out <= '0';
191    elsif clk'event and clk = '1' then
192      temp := cpol & cpha;
193      case temp is
194        when "00" =>    -- polarity = 0, phase = 0
195          -- sck = sck_0
196          sck_out <= sck_0;
197        when "01" =>    -- polarity= 0, phase = 1
198          -- sck = sck_1
199          sck_out <= sck_1;
200        when "10" =>    -- polarity = 1, phase = 0
201          -- sck = not(sck_0)
202          sck_out <= not(sck_0);
203        when "11" =>    -- polarity = 1, phase = 1
204          -- sck = not(sck_1)
205          sck_out <= not(sck_1);
206        when others =>  -- default to sck_0
207          sck_out <= sck_0;
208      end case;
209    end if;
210  end process;
211
212  -- Detect rising and falling edges of SCK_OUT to use to end cycle correctly
213  -- and to keep RCV_LOAD signal 1 system clock in width
214  SCK_DELAY_PROCESS: process(clk, reset)
215  begin
216    if reset = RESET_ACTIVE then
217      sck_d1 <= '0';
218    elsif clk'event and clk = '1' then
219      sck_d1 <= sck_out;
220    end if;
221  end process;
222
223  sck_re <= '1' when sck_out = '1' and sck_d1 = '0'
224            else '0';
225  sck_fe <= '1' when sck_out = '0' and sck_d1 = '1'
226            else '0';
227
228  -- The SCK output is 3-stated if the SS_IN_INT signal is asserted indicating that another
229  -- master is on the bus
230  sck <= sck_out when ss_in_int = '1'
231         else    'Z';
232
233end DEFINITION;
Note: See TracBrowser for help on using the repository browser.