Project

General

Profile

Download (6.11 KB) Statistics
| Branch: | Tag: | Revision:
1
---------------------------------------------------------------------------------------------------
2
-- Filename    : usbrx_spi.vhd
3
-- Project     : OsmoSDR FPGA Firmware
4
-- Purpose     : SPI Slave Implementation
5
---------------------------------------------------------------------------------------------------
6

    
7
-----------------------------------------------------------------------------------
8
-- Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany --
9
-- written by Matthias Kleffel                                                   --
10
--                                                                               --
11
-- This program is free software; you can redistribute it and/or modify          --
12
-- it under the terms of the GNU General Public License as published by          --
13
-- the Free Software Foundation as version 3 of the License, or                  --
14
--                                                                               --
15
-- This program is distributed in the hope that it will be useful,               --
16
-- but WITHOUT ANY WARRANTY; without even the implied warranty of                --
17
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                  --
18
-- GNU General Public License V3 for more details.                               --
19
--                                                                               --
20
-- You should have received a copy of the GNU General Public License             --
21
-- along with this program. If not, see <http://www.gnu.org/licenses/>.          --
22
-----------------------------------------------------------------------------------
23

    
24
library ieee;
25
	use ieee.std_logic_1164.all;
26
	use ieee.numeric_std.all;
27
library work;
28
	use work.all;
29
	use work.mt_toolbox.all;
30

    
31
entity usbrx_spi is
32
	port(
33
		-- common
34
		clk       : in  std_logic;
35
		reset     : in  std_logic;
36

    
37
		-- SPI interface
38
		spi_ncs   : in  std_logic;
39
		spi_sclk  : in  std_logic;
40
		spi_mosi  : in  std_logic;
41
		spi_miso  : out std_logic;
42
		
43
		-- bus interface
44
		bus_rena  : out std_logic;
45
		bus_wena  : out std_logic;
46
		bus_addr  : out unsigned(6 downto 0);
47
		bus_rdata : in  std_logic_vector(31 downto 0);
48
		bus_wdata : out std_logic_vector(31 downto 0)
49
	);
50
end usbrx_spi;
51

    
52
architecture rtl of usbrx_spi is
53

    
54
	-- internal types
55
	type state_t is (S_COMMAND, S_WRITE, S_READ2, S_READ3, S_READ4);
56
	
57
	-- IO-registers
58
	signal iob_ncs  : std_logic;
59
	signal iob_sclk : std_logic;
60
	signal iob_mosi : std_logic;
61

    
62
	-- synchronized inputs
63
	signal sync_ncs  : std_logic;
64
	signal sync_sclk : std_logic;
65
	signal sync_mosi : std_logic;
66
	
67
	-- edge detection
68
	signal last_sclk : std_logic;
69
	signal last_re   : std_logic;
70
	signal last_fe   : std_logic;
71
	
72
	-- SPI slave
73
	signal state  : state_t;
74
	signal remain : unsigned(5 downto 0);
75
	signal sireg  : std_logic_vector(31 downto 0);
76
	signal soreg  : std_logic_vector(32 downto 0);
77
	signal addr   : unsigned(6 downto 0);
78

    
79
begin
80
	
81
	-- IOBs
82
	process(clk)
83
	begin
84
		if rising_edge(clk) then
85
			iob_ncs  <= spi_ncs;
86
			iob_sclk <= spi_sclk;
87
			iob_mosi <= spi_mosi;
88
			if iob_ncs='0' 
89
				then spi_miso <= soreg(32);
90
				else spi_miso <= '1';
91
			end if;
92
		end if;
93
	end process;
94
	
95
	-- input synchronizer
96
	process(clk,reset)
97
	begin
98
		if reset = '1' then
99
			sync_ncs  <= '1';
100
			sync_sclk <= '0';
101
			sync_mosi <= '0';
102
		elsif rising_edge(clk) then
103
			sync_ncs  <= iob_ncs;
104
			sync_sclk <= iob_sclk;
105
			sync_mosi <= iob_mosi;
106
		end if;
107
	end process;
108

    
109
	-- SPI slave
110
	process(clk,reset)
111
		variable re,fe : std_logic;
112
	begin
113
		if reset = '1' then
114
			last_sclk <= '0';
115
			last_re   <= '0';
116
			last_fe   <= '0';
117
			state     <= S_COMMAND;
118
			remain    <= (others=>'0');
119
			sireg     <= (others=>'1');
120
			soreg     <= (others=>'1');
121
			addr      <= (others=>'0');
122
			bus_rena  <= '0';
123
			bus_wena  <= '0';
124
			bus_addr  <= (others=>'0');
125
			bus_wdata <= (others=>'0');
126
		elsif rising_edge(clk) then
127
			-- set default values
128
			bus_rena  <= '0';
129
			bus_wena <= '0';
130
	
131
			-- detect edges on clock line
132
			last_sclk <= sync_sclk;
133
			re := sync_sclk and (not last_sclk);
134
			fe := (not sync_sclk) and last_sclk;
135
			last_re <= re;
136
			last_fe <= fe;
137
		
138
			-- update shift-registers
139
			if re='1' then
140
				sireg <= sireg(30 downto 0) & sync_mosi;
141
			end if;
142
			if fe='1' then
143
				soreg <= soreg(31 downto 0) & '1';
144
			end if;
145
	
146
			-- check state of chip-select
147
			if sync_ncs='1' then
148
				--> CS deasserted, reset slave
149
				state  <= S_COMMAND;
150
				remain <= to_unsigned(7,6);
151
			else
152
				--> CS asserted, tick state-machine
153
				case state is
154
					when S_COMMAND =>
155
						-- wait until 8 bits were received
156
						if last_re='1' then
157
							remain <= remain - 1;
158
							if remain=0 then
159
								--> got 8 bits, decode address & direction
160
								addr   <= unsigned(sireg(6 downto 0));
161
								remain <= to_unsigned(31,6);
162
								if sireg(7)='1' then
163
									state    <= S_READ2;
164
									bus_rena <= '1';
165
									bus_addr <= unsigned(sireg(6 downto 0));
166
								else 
167
									state <= S_WRITE;
168
								end if;
169
							end if;
170
						end if;
171
						
172
					when S_WRITE =>
173
						-- wait until 32 bits were received
174
						if last_re='1' then
175
							remain <= remain - 1;
176
							if remain=0 then
177
								-- issue write-request
178
								bus_wena  <= '1';
179
								bus_addr  <= addr;
180
								bus_wdata <= sireg;
181
								
182
								-- continue with next word
183
								addr   <= addr + 1;
184
								remain <= to_unsigned(31,6);
185
							end if;
186
						end if;
187
					
188
					when S_READ2 =>
189
						-- wait-state
190
						state  <= S_READ3;
191
						
192
					when S_READ3 =>
193
						-- load shift-register
194
						soreg  <= soreg(32) & bus_rdata;
195
						state  <= S_READ4;
196
					    remain <= to_unsigned(31,6);
197
						
198
					when S_READ4 =>
199
						-- wait until 32 bits were transmitted
200
						if fe='1' then
201
							remain <= remain - 1;
202
							if remain=0 then
203
								-- continue with next word
204
								bus_rena <= '1';
205
								bus_addr <= addr + 1;
206
								addr     <= addr + 1;
207
								state    <= S_READ2;
208
							end if;
209
						end if;
210
				end case;
211
			end if;
212
		end if;
213
	end process;
214
	
215
end rtl;
(6-6/7)
Add picture from clipboard (Maximum size: 48.8 MB)