Be busy as soon as the first txn arrives.
[bos2k9.git] / bos2k9_pump.vhd
1 -----------------------------------------------------------------------
2 -- Copyright (c) 2009 Malte S. Stretz <http://msquadrat.de> 
3 --
4 -- This entity is a drop-in replacement for `fhw_rs232.rs232_send`
5 -- which sends out 512 Bytes (buffered internally) at once.
6 --
7 -----------------------------------------------------------------------
8
9 library ieee;
10 use ieee.std_logic_1164.all;
11 use ieee.numeric_std.all;
12
13 library fhw_tools;
14 use fhw_tools.types.all;
15
16 use work.bos2k9_globals.all;
17
18 entity bos2k9_pump is
19   generic(
20     clock_divider  : positive;
21     parity_enabled : std_logic := '1');
22   port(
23     clock : in  std_logic;
24     reset : in  std_logic;
25     
26     txn : in  std_logic;
27     txd : in  std_logic_byte_t;
28     txb : out std_logic;
29     tx  : out std_logic);
30 end bos2k9_pump;
31
32 -----------------------------------------------------------------------
33
34 architecture rtl of bos2k9_pump is
35      component rs232_send is
36     generic(
37       clock_divider  : positive  := clock_divider;
38       parity_enabled : std_logic := parity_enabled);
39     port(
40       clk : in  std_logic;
41       rst : in  std_logic;
42       
43       tx  : out std_logic;
44       txd : in  std_logic_byte_t;
45       txn : in  std_logic;
46       txb : out std_logic);
47    end component;
48  
49    component bos2k9_mmu is
50     port(
51       clock : in  std_logic;
52       reset : in  std_logic;
53     
54       write_next : in  std_logic;
55       write_addr : out std_logic_byte_address_t;
56       write_data : in  std_logic_byte_t;
57     
58       read_addr : in  std_logic_byte_address_t;
59       read_data : out std_logic_byte_t);
60   end component;
61   
62   type state_t is(
63     idle_state_c,
64     send_state_c,
65     wait_state_c,
66     next_state_c);
67   signal state_s : state_t;
68
69   signal busy_s : std_logic;
70   signal done_s : std_logic;
71   
72   signal otrg_s : std_logic;
73   
74   signal sout_s : std_logic_byte_t;
75   signal strg_s : std_logic;
76   signal sbsy_s : std_logic;
77
78   signal iadr_s : std_logic_byte_address_t;
79   signal oadr_s : std_logic_byte_address_t;
80 begin
81   -- We're busy as soon as the state machine goes off.
82   txb <= busy_s or txn;
83   
84   -- Just to be sure, wait until the second byte was read.
85   otrg_s <= iadr_s(1);
86   
87   strg_s <= '1' when state_s = send_state_c
88        else '0';
89
90   sequence : process(clock, reset)
91   begin
92     if reset = '1' then
93       state_s <= idle_state_c;
94     elsif rising_edge(clock) then
95       case state_s is
96         when idle_state_c =>
97           if otrg_s = '1' then
98             state_s <= send_state_c;
99           end if;
100         when send_state_c =>
101           state_s <= wait_state_c;
102         when wait_state_c =>
103           if sbsy_s = '0' then
104             state_s <= next_state_c;
105           end if;
106         when next_state_c =>
107           if done_s = '1' then
108             state_s <= send_state_c;
109           else
110             state_s <= idle_state_c;
111           end if;
112       end case;
113     end if;
114   end process;
115   
116   pointer : process(clock, reset)
117   begin
118     if reset = '1' then
119       oadr_s <= (others => '0');
120     elsif rising_edge(clock) then
121       if state_s = next_state_c then
122         oadr_s <= std_logic_vector(unsigned(oadr_s) + 1);
123       end if;
124     end if;
125   end process;
126   
127   busy_ff : process(clock, reset)
128   begin
129     if reset = '1' then
130       busy_s <= '0';
131     elsif rising_edge(clock) then
132       if busy_s = '0' then
133         busy_s <= txn;
134       elsif state_s = next_state_c then
135         busy_s <= not done_s;
136       end if;
137     end if;
138   end process;
139
140   done_net : process(oadr_s)
141     variable done_v : std_logic;
142   begin
143     done_v := '1';
144     for i in std_logic_byte_address_t'range loop
145       done_v := done_v and oadr_s(i);
146     end loop;
147     done_s <= done_v;
148   end process;
149   
150   ser_io : rs232_send port map(
151     clk => clock,
152     rst => reset,
153     
154     tx  => tx,
155     txd => sout_s,
156     txn => strg_s,
157     txb => sbsy_s);
158   mmu : bos2k9_mmu port map(
159     clock => clock,
160     reset => reset,
161     write_next => txn,
162     write_addr => iadr_s,
163     write_data => txd,
164     read_addr  => oadr_s,
165     read_data  => sout_s);
166 end rtl;