Another LED connected for debugging.
[bos2k9.git] / bos2k9.vhd
1 -----------------------------------------------------------------------
2 -- Copyright (c) 2009 Malte S. Stretz <http://msquadrat.de> 
3 --
4 -- The project top level entity.
5 --
6 -- It implements a simple test setup which can read data from an SD 
7 -- card.  Blocks are read in 512 Byte blocks, so both block addresses
8 -- and byte addresses (relative to the block start) can be specified.
9 -- The system starts up doing nothing, an init button has to be pressed
10 -- to initialize the card and afterwards the selected block can be read
11 -- to an internal buffer.
12 --
13 -- This is designed around the DE2 evaluation board.  To simplify
14 -- development, the ports of the entity are named after the file
15 -- `DE2_Pin_Table.pdf`, which is part of the DE2 documentation.
16 -- The PDF file was converted to a TCL file and is included in this
17 -- project as `de2_pins.tcl` and can be copied to the `bos2k9.qsf`
18 -- project file.  This has the side effect that Quartus will complain
19 -- that some of these pins are stuck to GND or not used; these 
20 -- warnings can be ignored.
21 --
22 -- The following pins are used:
23 --  * `CLOCK_50` is the 50 MHz system clock.
24 --  * `KEY` are the four push button which are low-active.
25 --  * `SW` are the eighteen on-off switches.
26 --  * `LEDR` are the eighteen red LEDs above the switches.
27 --  * `LEDG` are the nine green LEDs; the low eight are located above
28 --    the push buttons, the ninth is above the row of red LEDs.
29 --  * `SD_DAT` is the SPI MISO.
30 --  * `SD_CMD` is the SPI MOSI.
31 --  * `SD_DAT3` is the SPI CS.
32 --  * `SD_CLK` is the SPI SCK.
33 --
34 -- LEDG(0) should be always on and represents a powered system. The 
35 -- `reset` is wired to `SW(17)`, so the switch should be off when these
36 -- system is started.  Once `reset` is off (ie. the switch on), the card
37 -- can be initialized (and later reset) by pressing `KEY(0)`.  Once
38 -- LEDG(2) is led, the system is ready to read a block; if an error 
39 -- occurs, LEDG(1) is switched on instead.
40 --
41 -- The low eight bits of the block address can be specified by the
42 -- first eight `SW`es, ie. SW(0) to SW(7).  Only the first 256 blocks 
43 -- of 4096 possible ones (on 2 GiB SD cards; SDHC is not supported) can 
44 -- be read.  `KEY(1)` starts the reading of the selected block.
45 --
46 -- The used `button` entity ensures that even with really slow fingers,
47 -- the button press is only signaled once.  As the buttons on the DE2
48 -- board tend to break, this cannot be ensured but a longer press 
49 -- doesn't break anything.
50 --
51 -- The currently via SW(8) to SW(15) selected byte is displayed on the
52 -- LEDs LEDR(0) to LEDR(7) and inverted on LEDR(8) to LEDR(15).
53 --
54 -- Because only eight address bits are wired, only half the block can 
55 -- be displayed.  Both this and the above limitation doesn't matter as 
56 -- this is a test setup only.
57 --
58 -- For debugging purposes, the SPI bus is also wired to the LEDs 
59 -- LEDG(7) to LEDG(4). 
60 -----------------------------------------------------------------------
61
62 library ieee;
63 use ieee.std_logic_1164.all;
64
65 library fhw_sd;
66 use fhw_sd.sd_host;
67
68 library fhw_tools;
69 use fhw_tools.all;
70 use fhw_tools.types.all;
71
72 use work.bos2k9_globals.all;
73
74 -----------------------------------------------------------------------
75
76 entity bos2k9 is
77   port(
78     CLOCK_50 : in std_logic;
79     
80     KEY  : in  std_logic_vector(3 downto 0);
81     SW   : in  std_logic_vector(17 downto 0);
82     LEDR : out std_logic_vector(17 downto 0);
83     LEDG : out std_logic_vector(8 downto 0);
84     
85     UART_RXD : in  std_logic;
86     UART_TXD : out std_logic;
87     
88     SD_DAT  : in  std_logic;
89     SD_CMD  : out std_logic;
90     SD_DAT3 : out std_logic;
91     SD_CLK  : out std_logic);
92 end bos2k9;
93
94 -----------------------------------------------------------------------
95
96 architecture board of bos2k9 is
97
98   component sd_host is
99     generic(
100       clock_interval : time     := clock_interval_c;
101       clock_divider  : positive := sd_clock_div_c);
102     port(
103       clk : in  std_logic;
104       rst : in  std_logic;
105
106       init  : in  std_logic;
107       ready : out std_logic;
108       error : out std_logic;
109       
110       address : in  std_logic_block_address_t;
111       start   : in  std_logic;
112       rxd     : out std_logic_byte_t;
113       shd     : out std_logic;
114       
115       miso  : in  std_logic;
116       mosi  : out std_logic;
117       sck   : out std_logic;
118       cs    : out std_logic);
119   end component;
120   
121   component rs232_send is
122     generic(
123       clock_divider  : positive := ser_clock_div_c);
124     port(
125       clk : in  std_logic;
126       rst : in  std_logic;
127       
128       tx  : out std_logic;
129       txd : in  std_logic_byte_t;
130       txn : in  std_logic;
131       txb : out std_logic);
132    end component;
133   
134   component bos2k9_mmu is
135     port(
136       clock : in  std_logic;
137       reset : in  std_logic;
138     
139       write_next : in  std_logic;
140       write_addr : out std_logic_byte_address_t;
141       write_data : in  std_logic_byte_t;
142     
143       read_addr : in  std_logic_byte_address_t;
144       read_data : out std_logic_byte_t);
145   end component;
146   
147   component button
148     port(
149       clk : in std_logic;
150       rst : in std_logic;
151       
152       input  : in  std_ulogic;
153       output : out std_ulogic);
154   end component;
155
156   signal clock_s : std_logic;
157   signal reset_s : std_logic;
158   
159   signal ready_led_s : std_logic;
160   signal error_led_s : std_logic;
161   signal dummy_led_s : std_logic;
162   
163   signal init_btn_s : std_logic;
164   signal read_btn_s : std_logic;
165   signal send_btn_s : std_logic;
166   
167   signal byte_led_s  : std_logic_vector(7 downto 0);
168   signal byte_sw1_s  : std_logic_vector(7 downto 0);
169   signal byte_sw2_s  : std_logic_vector(7 downto 0);
170   
171   signal spi_s : spi_bus_t;
172   signal ser_s : ser_bus_t;
173   
174 begin
175   clock_s <= CLOCK_50;
176   reset_s <= not SW(17);
177
178   init_button : button port map(clock_s, reset_s,
179     input  => KEY(0),
180     output => init_btn_s);
181   read_button : button port map(clock_s, reset_s,
182     input  => KEY(1),
183     output => read_btn_s);
184   send_button : button port map(clock_s, reset_s,
185     input  => KEY(2),
186     output => send_btn_s);
187   
188   spi_s.miso <= SD_DAT;
189   SD_CMD     <= spi_s.mosi;
190   SD_CLK     <= spi_s.sck;
191   SD_DAT3    <= spi_s.cs;
192   
193   UART_TXD <= ser_s.tx;
194   ser_s.rx <= UART_RXD;
195   
196   LEDG <= (
197     7 => spi_s.miso,
198     6 => spi_s.mosi,
199     5 => spi_s.sck,
200     4 => spi_s.cs,
201     3 => dummy_led_s,
202     1 => ready_led_s,
203     0 => error_led_s,
204     others => '0');
205   LEDR <= (
206    17 => not reset_s,
207    15 => not byte_led_s(7),
208    14 => not byte_led_s(6),
209    13 => not byte_led_s(5),
210    12 => not byte_led_s(4),
211    11 => not byte_led_s(3),
212    10 => not byte_led_s(2),
213     9 => not byte_led_s(1),
214     8 => not byte_led_s(0),
215     7 => byte_led_s(7),
216     6 => byte_led_s(6),
217     5 => byte_led_s(5),
218     4 => byte_led_s(4),
219     3 => byte_led_s(3),
220     2 => byte_led_s(2),
221     1 => byte_led_s(1),
222     0 => byte_led_s(0),
223     others => '0');
224   byte_sw1_s <= SW(7 downto 0);
225   byte_sw2_s <= SW(15 downto 8);
226   
227   guts : block
228     signal sd_init_s    : std_logic;
229     signal sd_ready_s   : std_logic;
230     signal sd_error_s   : std_logic;
231     signal sd_address_s : std_logic_block_address_t;
232     signal sd_start_s   : std_logic;
233     signal sd_data_s    : std_logic_byte_t;
234     signal sd_latch_s   : std_logic;
235     signal sd_shift_s   : std_logic;
236   
237     signal bl_address_s : std_logic_byte_address_t;
238     
239     signal ser_send_s   : std_logic;
240     signal ser_data_s   : std_logic_byte_t;
241     signal ser_busy_s   : std_logic;
242   begin
243
244     ready_led_s <= sd_ready_s;
245     error_led_s <= sd_error_s;
246     
247     sd_init_s  <= init_btn_s;
248     sd_start_s <= read_btn_s;
249   
250     sd_address_s(std_logic_block_address_t'high downto std_logic_byte_t'high + 1) <= (others => '0');
251     sd_address_s(std_logic_byte_t'range) <= byte_sw1_s;
252     bl_address_s(std_logic_byte_address_t'high downto std_logic_byte_t'high + 1) <= (others => '0');
253     bl_address_s(std_logic_byte_t'range) <= byte_sw2_s;
254     
255     ser_send_s <= send_btn_s;
256     
257     byte_led_s <= ser_data_s;
258     
259     dummy_led_s <= ser_busy_s;
260   
261     sd_io : sd_host port map(
262       clk => clock_s,
263       rst => reset_s,
264     
265       init    => sd_init_s, 
266       ready   => sd_ready_s,
267       error   => sd_error_s,
268       address => sd_address_s,
269       start   => sd_start_s,
270       rxd     => sd_data_s,
271       shd     => sd_latch_s,
272     
273       miso  => spi_s.miso,
274       mosi  => spi_s.mosi,
275       sck   => spi_s.sck,
276       cs    => spi_s.cs);
277     ser_io : rs232_send port map(
278       clk => clock_s,
279       rst => reset_s,
280       
281       tx  => ser_s.tx,
282       txd => ser_data_s,
283       txn => ser_send_s,
284       txb => ser_busy_s);
285     mmu : bos2k9_mmu port map(
286       clock => clock_s,
287       reset => reset_s,
288       write_next => sd_latch_s,
289       write_addr => open,
290       write_data => sd_data_s,
291       read_addr  => bl_address_s,
292       read_data  => ser_data_s);
293   end block;
294 end board;