Hallo! Das ist mein erster, ernster Versuch mit VHDL ;) Ich habe versucht den TWI- Prescaler der Mega AVRs (48/88/168- bestimmt auch viele andere) nachzubauen. Ich finde, dass das schon mal ganz toll aussieht, aber ist es das auch?
1 | library IEEE; |
2 | use IEEE.STD_LOGIC_1164.ALL; |
3 | use IEEE.NUMERIC_STD.ALL; |
4 | |
5 | entity i2c_ce_gen is |
6 | Port ( CLK_I : in STD_LOGIC; |
7 | RST_I : in STD_LOGIC; |
8 | CE_I : in STD_LOGIC; |
9 | TWPS_I : in STD_LOGIC_VECTOR (1 downto 0); |
10 | TWBR_I : in STD_LOGIC_VECTOR (7 downto 0); |
11 | CE_O : out STD_LOGIC); |
12 | end i2c_ce_gen; |
13 | |
14 | architecture Behavioral of i2c_ce_gen is |
15 | |
16 | signal prescale : integer range 0 to 32767; |
17 | signal prescale_cmp : integer range 0 to 32767; |
18 | signal sub_prescale : integer range 1 to 64; |
19 | signal twbr_temp : integer range 0 to 255; |
20 | |
21 | begin
|
22 | |
23 | process (CLK_I) |
24 | begin
|
25 | --[CLKSYNC] sync process
|
26 | if rising_edge(CLK_I) then |
27 | --[RESET]sync reset
|
28 | if RST_I = '1' then |
29 | CE_O <= '0'; |
30 | prescale <= 0; |
31 | prescale_cmp <= 0; |
32 | sub_prescale <= 1; |
33 | else
|
34 | --avr style prescaler selection
|
35 | case TWPS_I is |
36 | when "00" => sub_prescale <= 1; |
37 | when "01" => sub_prescale <= 4; |
38 | when "10" => sub_prescale <= 16; |
39 | when "11" => sub_prescale <= 64; |
40 | when others => null; |
41 | end case; |
42 | --avr style prescale count register
|
43 | twbr_temp <= to_integer( unsigned(TWBR_I)); |
44 | --calculation of compare value (avr style)
|
45 | prescale_cmp <= 15 + 2 * twbr_temp * sub_prescale; |
46 | |
47 | --[CE] to cascade prescalers
|
48 | if CE_I = '1' then |
49 | prescale <= prescale + 1; |
50 | --[COMP] comparator
|
51 | if prescale = prescale_cmp then |
52 | CE_O <= '1'; |
53 | prescale <= 0; |
54 | else
|
55 | CE_O <= '0'; |
56 | end if; --/[COMP] |
57 | end if; --/[CE] |
58 | end if; --/[RESET] |
59 | end if; --/[CLKSYNC] |
60 | end process; |
61 | end Behavioral; |