7912641273527e936e082fdaf558e9297b381170
[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).
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 use ieee.numeric_std.all;
65
66 library fhw_sd;
67 use fhw_sd.sd_host;
68
69 library fhw_tools;
70 use fhw_tools.all;
71 use fhw_tools.types.all;
72
73 use work.bos2k9_globals.all;
74
75 -----------------------------------------------------------------------
76
77 entity bos2k9 is
78   port(
79     CLOCK_50 : in std_logic;
80     
81     KEY  : in  std_logic_vector(3 downto 0);
82     SW   : in  std_logic_vector(17 downto 0);
83     LEDR : out std_logic_vector(17 downto 0);
84     LEDG : out std_logic_vector(8 downto 0);
85     
86     UART_RXD : in  std_logic;
87     UART_TXD : out std_logic;
88     
89     SD_DAT  : in  std_logic;
90     SD_CMD  : out std_logic;
91     SD_DAT3 : out std_logic;
92     SD_CLK  : out std_logic);
93 end bos2k9;
94
95 -----------------------------------------------------------------------
96
97 architecture board of bos2k9 is
98
99   component sd_host is
100     generic(
101       clock_interval : time     := clock_interval_c;
102       clock_divider  : positive := sd_clock_div_c);
103     port(
104       clk : in  std_logic;
105       rst : in  std_logic;
106
107       init  : in  std_logic;
108       ready : out std_logic;
109       error : out std_logic;
110       
111       address : in  std_logic_block_address_t;
112       start   : in  std_logic;
113       rxd     : out std_logic_byte_t;
114       shd     : out std_logic;
115       
116       miso  : in  std_logic;
117       mosi  : out std_logic;
118       sck   : out std_logic;
119       cs    : out std_logic);
120   end component;
121   
122   component rs232_send is
123     generic(
124       clock_divider  : positive := ser_clock_div_c;
125       parity_enabled : std_logic := '1');
126     port(
127       clk : in  std_logic;
128       rst : in  std_logic;
129       
130       tx  : out std_logic;
131       txd : in  std_logic_byte_t;
132       txn : in  std_logic;
133       txb : out std_logic);
134    end component;
135   
136   component bos2k9_mmu is
137     port(
138       clock : in  std_logic;
139       reset : in  std_logic;
140     
141       write_next : in  std_logic;
142       write_addr : out std_logic_byte_address_t;
143       write_data : in  std_logic_byte_t;
144     
145       read_addr : in  std_logic_byte_address_t;
146       read_data : out std_logic_byte_t);
147   end component;
148   
149   component bos2k9_counter is
150     generic(
151       cnt  : positive);
152     port(
153       clk  : in  std_logic;
154       rst  : in  std_logic;
155       en   : in  std_logic;
156       clr  : in  std_logic;
157       done : out std_logic);
158   end component;
159   
160   component button
161     port(
162       clk : in std_logic;
163       rst : in std_logic;
164       
165       input  : in  std_ulogic;
166       output : out std_ulogic);
167   end component;
168
169   signal clock_s : std_logic;
170   signal reset_s : std_logic;
171   
172   signal ready_led_s : std_logic;
173   signal error_led_s : std_logic;
174   signal dummy_led_s : std_logic;
175   
176   signal read_btn_s : std_logic;
177   
178   signal byte_led_s  : std_logic_vector(7 downto 0);
179   signal byte_sw1_s  : std_logic_vector(7 downto 0);
180   
181   signal spi_s : spi_bus_t;
182   signal ser_s : ser_bus_t;
183   
184 begin
185   clock_s <= CLOCK_50;
186   reset_s <= not SW(17);
187
188   read_button : button port map(clock_s, reset_s,
189     input  => KEY(1),
190     output => read_btn_s);
191   
192   spi_s.miso <= SD_DAT;
193   SD_CMD     <= spi_s.mosi;
194   SD_CLK     <= spi_s.sck;
195   SD_DAT3    <= spi_s.cs;
196   
197   UART_TXD <= ser_s.tx;
198   ser_s.rx <= UART_RXD;
199   
200   LEDG <= (
201     7 => spi_s.miso,
202     6 => spi_s.mosi,
203     5 => spi_s.sck,
204     4 => spi_s.cs,
205     3 => dummy_led_s,
206     1 => ready_led_s,
207     0 => error_led_s,
208     others => '0');
209   LEDR <= (
210    17 => not reset_s,
211     7 => byte_led_s(7),
212     6 => byte_led_s(6),
213     5 => byte_led_s(5),
214     4 => byte_led_s(4),
215     3 => byte_led_s(3),
216     2 => byte_led_s(2),
217     1 => byte_led_s(1),
218     0 => byte_led_s(0),
219     others => '0');
220   byte_sw1_s <= SW(7 downto 0);
221   
222   guts : block
223     signal sd_init_s    : std_logic;
224     signal sd_ready_s   : std_logic;
225     signal sd_error_s   : std_logic;
226     signal sd_address_s : std_logic_block_address_t;
227     signal sd_start_s   : std_logic;
228     signal sd_data_s    : std_logic_byte_t;
229     signal sd_latch_s   : std_logic;
230     signal sd_shift_s   : std_logic;
231     
232     signal ser_send_s   : std_logic;
233     signal ser_data_s   : std_logic_byte_t;
234     signal ser_busy_s   : std_logic;
235     
236     signal r_address_s    : std_logic_byte_address_t;
237     signal r_address_lo_s : std_logic;
238     signal r_address_hi_s : std_logic;
239     signal w_address_s    : std_logic_byte_address_t;
240     signal w_address_lo_s : std_logic;
241     signal w_address_hi_s : std_logic;
242     
243     signal start_s : std_logic;
244     signal shift_s : std_logic;
245     signal write_s : std_logic;
246   begin
247
248     ready_led_s <= sd_ready_s;
249     error_led_s <= sd_error_s;
250     dummy_led_s <= write_s;
251     byte_led_s  <= ser_data_s;
252     
253     sd_address_s(std_logic_block_address_t'high downto std_logic_byte_t'high + 1) <= (others => '0');
254     sd_address_s(std_logic_byte_t'range) <= byte_sw1_s;
255     
256     sd_start_s <= read_btn_s and not write_s;
257     
258     -------------------------------------------------------------------
259     
260     write_s <= start_s or not r_address_lo_s;
261     
262     starter : process(clock_s, reset_s)
263     begin
264       if reset_s = '1' then
265         start_s <= '0';
266       elsif rising_edge(clock_s) then
267         if write_s = '0' then
268           start_s <= not w_address_lo_s;
269         else
270           start_s <= r_address_lo_s;
271         end if;
272       end if;
273     end process;
274     
275     ser_send_s <= write_s and not shift_s;
276     
277     shifter : process(clock_s, reset_s)
278     begin
279       if reset_s = '1' then
280         shift_s <= '0';
281       elsif rising_edge(clock_s) then
282         shift_s <= write_s and not ser_busy_s and not start_s;
283       end if;
284     end process;
285     
286     trigger : process(clock_s, reset_s)
287     begin
288       if reset_s = '1' then
289         
290       elsif rising_edge(clock_s) then
291         
292       end if;
293     end process;
294     
295     addresser : process(clock_s, reset_s)
296     begin
297       if reset_s = '1' then
298         r_address_s <= (others => '0');
299       elsif rising_edge(clock_s) then
300         if shift_s = '1' then
301           r_address_s <= std_logic_vector(unsigned(r_address_s) + 1);
302         end if;
303       end if;
304     end process;
305       
306       
307         if (write_s and not ser_busy_s and not start_s and not shift_s) = '1' then
308           
309           shift_s <= '1';
310         end if;
311       end if;
312     end process;
313     
314     address_net : process(r_address_s, w_address_s)
315       variable r_address_lo_v : std_logic;
316       variable r_address_hi_v : std_logic;
317       variable w_address_lo_v : std_logic;
318       variable w_address_hi_v : std_logic;
319     begin
320       r_address_lo_v := '1';
321       r_address_hi_v := '1';
322       w_address_lo_v := '1';
323       r_address_hi_v := '1';
324       for i in std_logic_byte_address_t'range loop
325         r_address_lo_v := r_address_lo_v and not r_address_s(i);
326         r_address_hi_v := r_address_hi_v and     r_address_s(i);
327         w_address_lo_v := w_address_lo_v and not w_address_s(i);
328         r_address_hi_v := r_address_hi_v and     w_address_s(i);
329       end loop;
330       r_address_lo_s <= r_address_lo_v;
331       r_address_hi_s <= r_address_hi_v;
332       w_address_lo_s <= w_address_lo_v;
333       r_address_hi_s <= r_address_hi_v;
334     end process;
335   
336     sd_io : sd_host port map(
337       clk => clock_s,
338       rst => reset_s,
339     
340       init    => sd_init_s, 
341       ready   => sd_ready_s,
342       error   => sd_error_s,
343       address => sd_address_s,
344       start   => sd_start_s,
345       rxd     => sd_data_s,
346       shd     => sd_latch_s,
347     
348       miso  => spi_s.miso,
349       mosi  => spi_s.mosi,
350       sck   => spi_s.sck,
351       cs    => spi_s.cs);
352     sd_to : bos2k9_counter generic map(
353       cnt  => init_ticks_c) port map(
354       clk  => clock_s,
355       rst  => reset_s,
356       en   => '1',
357       clr  => sd_ready_s,
358       done => sd_init_s);
359     ser_io : rs232_send port map(
360       clk => clock_s,
361       rst => reset_s,
362       
363       tx  => ser_s.tx,
364       txd => ser_data_s,
365       txn => ser_send_s,
366       txb => ser_busy_s);
367     mmu : bos2k9_mmu port map(
368       clock => clock_s,
369       reset => reset_s,
370       write_next => sd_latch_s,
371       write_addr => w_address_s,
372       write_data => sd_data_s,
373       read_addr  => r_address_s,
374       read_data  => ser_data_s);
375   end block;
376 end board;