Introduce constants for parity.
[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     parity_type    : std_logic := '0');
23   port(
24     clock : in  std_logic;
25     reset : in  std_logic;
26     
27     txn : in  std_logic;
28     txd : in  std_logic_byte_t;
29     txb : out std_logic;
30     tx  : out std_logic);
31 end bos2k9_pump;
32
33 -----------------------------------------------------------------------
34
35 architecture rtl of bos2k9_pump is
36     component rs232_send is
37     generic(
38       clock_divider  : positive  := clock_divider;
39       parity_enabled : std_logic := parity_enabled;
40       parity_type    : std_logic := parity_type);
41     port(
42       clk : in  std_logic;
43       rst : in  std_logic;
44       
45       tx  : out std_logic;
46       txd : in  std_logic_byte_t;
47       txn : in  std_logic;
48       txb : out std_logic);
49    end component;
50  
51    component bos2k9_mmu is
52     port(
53       clock : in  std_logic;
54       reset : in  std_logic;
55     
56       write_next : in  std_logic;
57       write_addr : out std_logic_byte_address_t;
58       write_data : in  std_logic_byte_t;
59     
60       read_addr : in  std_logic_byte_address_t;
61       read_data : out std_logic_byte_t);
62   end component;
63   
64   type state_t is(
65     idle_state_c,
66     send_state_c,
67     wait_state_c,
68     next_state_c);
69   signal state_s : state_t;
70
71   signal busy_s : std_logic;
72   signal done_s : std_logic;
73   
74   signal otrg_s : std_logic;
75   
76   signal sout_s : std_logic_byte_t;
77   signal strg_s : std_logic;
78   signal sbsy_s : std_logic;
79
80   signal iadr_s : std_logic_byte_address_t;
81   signal oadr_s : std_logic_byte_address_t;
82 begin
83   -- We're busy as soon as the state machine goes off.
84   txb <= busy_s or txn;
85   
86   -- Just to be sure, wait until the second byte was read.
87   --otrg_s <= txn;
88   otrg_s <= iadr_s(1);
89   
90   strg_s <= '1' when state_s = send_state_c
91        else '0';
92
93   sequence : process(clock, reset)
94   begin
95     if reset = '1' then
96       state_s <= idle_state_c;
97     elsif rising_edge(clock) then
98       case state_s is
99         when idle_state_c =>
100           if otrg_s = '1' then
101             state_s <= send_state_c;
102           end if;
103         when send_state_c =>
104           state_s <= wait_state_c;
105         when wait_state_c =>
106           if sbsy_s = '0' then
107             state_s <= next_state_c;
108           end if;
109         when next_state_c =>
110           if done_s = '1' then
111             state_s <= send_state_c;
112           else
113             state_s <= idle_state_c;
114           end if;
115       end case;
116     end if;
117   end process;
118   
119   pointer : process(clock, reset)
120   begin
121     if reset = '1' then
122       oadr_s <= (others => '0');
123     elsif rising_edge(clock) then
124       if state_s = next_state_c then
125         oadr_s <= std_logic_vector(unsigned(oadr_s) + 1);
126       end if;
127     end if;
128   end process;
129   
130   busy_ff : process(clock, reset)
131   begin
132     if reset = '1' then
133       busy_s <= '0';
134     elsif rising_edge(clock) then
135       if busy_s = '0' then
136         busy_s <= txn;
137       elsif state_s = next_state_c then
138         busy_s <= not done_s;
139       end if;
140     end if;
141   end process;
142
143   done_net : process(oadr_s)
144     variable done_v : std_logic;
145   begin
146     done_v := '1';
147     for i in std_logic_byte_address_t'range loop
148       done_v := done_v and oadr_s(i);
149     end loop;
150     done_s <= done_v;
151   end process;
152   
153   ser_io : rs232_send port map(
154     clk => clock,
155     rst => reset,
156     
157     tx  => tx,
158     txd => sout_s,
159     txn => strg_s,
160     txb => sbsy_s);
161   mmu : bos2k9_mmu port map(
162     clock => clock,
163     reset => reset,
164     write_next => txn,
165     write_addr => iadr_s,
166     write_data => txd,
167     read_addr  => oadr_s,
168     read_data  => sout_s);
169 end rtl;