source: FPGA/FTU/old_design/spi_interface/sck_logic_16.vhd@ 868

Last change on this file since 868 was 156, checked in by qweitzel, 15 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.