OpenCores
URL https://opencores.org/ocsvn/forth-cpu/forth-cpu/trunk

Subversion Repositories forth-cpu

[/] [forth-cpu/] [trunk/] [led.vhd] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 howe.r.j.8
--------------------------------------------------------------------------------
2
--| @file led.vhd
3
--| @brief controls a number of led displays, 8 segment LEDs, there
4
--| is no enable, just write 0 to the displays to turn them off.
5
--|
6
--| @author     Richard James Howe.
7
--| @copyright  Copyright 2013 Richard James Howe.
8
--| @license    MIT
9
--| @email      howe.r.j.89@gmail.com
10
--|
11
--------------------------------------------------------------------------------
12
library ieee,work;
13
use ieee.std_logic_1164.all;
14
use ieee.numeric_std.all;
15
 
16
package led_pkg is
17
        constant character_length: positive := 4;
18
 
19
        subtype led_character is std_ulogic_vector(character_length - 1 downto 0);
20
        subtype led_8_segment is std_ulogic_vector(7 downto 0);
21
 
22
        component led_8_segment_display is
23
                generic(
24
                        clock_frequency:        positive;
25
                        use_bcd_not_hex:        boolean := true;
26
                        refresh_rate_us:        natural := 1500;
27
                        number_of_led_displays: positive := 4);
28
                port(
29
                        clk:      in   std_ulogic;
30
                        rst:      in   std_ulogic;
31
 
32
                        leds_we:  in   std_ulogic;
33
                        leds:     in   std_ulogic_vector((number_of_led_displays * character_length) - 1 downto 0);
34
 
35
                        -- Physical outputs
36
                        an:       out  std_ulogic_vector(number_of_led_displays - 1 downto 0);  -- anodes, controls on/off
37
                        ka:       out  std_ulogic_vector(7 downto 0)); -- cathodes, data on display
38
        end component;
39
 
40
end package;
41
 
42
 
43
--| This module implements a 8 segment display driver, with 4 displays in total:
44
--|
45
--|    _____________________ an (selects segment)
46
--|    |     |     |     |
47
--|   __    __    __    __
48
--|  |  |  |  |  |  |  |  |
49
--|  |__|  |__|  |__|  |__|
50
--|  |  |  |  |  |  |  |  |
51
--|  |__|. |__|. |__|. |__|.
52
--|   |____|_____|_____|____ ka (value to display on segment)
53
--|
54
--| Each of the display shares a common anode for all of its LEDs, this can be
55
--| used to select an individual display
56
 
57
library ieee,work;
58
use ieee.std_logic_1164.all;
59
use ieee.numeric_std.all;
60
use work.util.reg;
61
use work.util.timer_us;
62
use work.util.invert;
63
use work.led_pkg.all;
64
 
65
entity led_8_segment_display is
66
        generic(
67
                clock_frequency:        positive;
68
                use_bcd_not_hex:        boolean  := true;
69
                refresh_rate_us:        natural  := 1500;
70
                number_of_led_displays: positive := 4);
71
        port(
72
                clk:      in   std_ulogic;
73
                rst:      in   std_ulogic;
74
 
75
                leds_we:  in   std_ulogic;
76
                leds:     in   std_ulogic_vector((number_of_led_displays * character_length) - 1 downto 0);
77
 
78
                -- Physical outputs
79
                an:       out  std_ulogic_vector(number_of_led_displays - 1 downto 0);  -- anodes, controls on/off
80
                ka:       out  std_ulogic_vector(7 downto 0)); -- cathodes, data on display
81
end;
82
 
83
architecture rtl of led_8_segment_display is
84
 
85
        -- 8 Segment LED lookup table converts a BCD character into a value
86
        -- that can be displayed on an 8 segment display. The layout of which
87
        -- is as follows:
88
        --
89
        --       A
90
        --      ---
91
        --   F |   | B
92
        --     |___|
93
        --   E | G | C
94
        --     |___| . DP
95
        --       D
96
        --
97
        -- The following encoding is used to convert the input BCD character
98
        -- into a value that can be put onto the display.
99
        --
100
        --  -----------------------------------------
101
        -- |   | DP| G | F | E | D | C | B | A | Hex |
102
        -- |BCD| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |Hi Lo|
103
        --  -----------------------------------------
104
        -- | 0 |   |   | 1 | 1 | 1 | 1 | 1 | 1 | 3 F |
105
        -- | 1 |   |   |   |   |   | 1 | 1 |   | 0 6 |
106
        -- | 2 |   | 1 |   | 1 | 1 |   | 1 | 1 | 5 B |
107
        -- | 3 |   | 1 |   |   | 1 | 1 | 1 | 1 | 4 F |
108
        -- | 4 |   | 1 | 1 |   |   | 1 | 1 |   | 6 6 |
109
        -- | 5 |   | 1 | 1 |   | 1 | 1 |   | 1 | 6 D |
110
        -- | 6 |   | 1 | 1 | 1 | 1 | 1 |   | 1 | 7 D |
111
        -- | 7 |   |   |   |   |   | 1 | 1 | 1 | 0 7 |
112
        -- | 8 |   | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 7 F |
113
        -- | 9 |   | 1 | 1 |   | 1 | 1 | 1 | 1 | 6 F |
114
        -- |   |   |   |   |   |   |   |   |   | 0 0 |
115
        -- | . | 1 |   |   |   |   |   |   |   | 8 0 |
116
        -- | - |   | 1 |   |   |   |   |   |   | 4 0 |
117
        --  -----------------------------------------
118
        -- | A |   | 1 | 1 | 1 |   | 1 | 1 | 1 | 7 7 |
119
        -- | b |   | 1 | 1 | 1 | 1 | 1 |   |   | 7 C |
120
        -- | C |   |   | 1 | 1 | 1 |   |   | 1 | 3 9 |
121
        -- | d |   | 1 |   | 1 | 1 | 1 | 1 |   | 5 E |
122
        -- | E |   | 1 | 1 | 1 | 1 |   |   | 1 | 7 9 |
123
        -- | F |   | 1 | 1 | 1 |   |   |   | 1 | 7 1 |
124
        --  -----------------------------------------
125
        --
126
        -- The table is then inverted before it goes to the output.
127
        --
128
 
129
        function hex_to_8segment(a: led_character) return led_8_segment is
130
                variable r: std_ulogic_vector(7 downto 0);
131
        begin
132
                case a is
133
                        when "0000" => r := x"3F"; -- 0
134
                        when "0001" => r := x"06"; -- 1
135
                        when "0010" => r := x"5B"; -- 2
136
                        when "0011" => r := x"4F"; -- 3
137
                        when "0100" => r := x"66"; -- 4
138
                        when "0101" => r := x"6D"; -- 5
139
                        when "0110" => r := x"7D"; -- 6
140
                        when "0111" => r := x"07"; -- 7
141
                        when "1000" => r := x"7F"; -- 8
142
                        when "1001" => r := x"6F"; -- 9
143
                        when "1010" => r := x"77"; -- A
144
                        when "1011" => r := x"7C"; -- b
145
                        when "1100" => r := x"39"; -- C
146
                        when "1101" => r := x"5E"; -- d
147
                        when "1110" => r := x"79"; -- E
148
                        when "1111" => r := x"71"; -- F
149
                        when others => r := x"00"; -- Unused
150
                end case;
151
                return r;
152
        end function;
153
 
154
        function bcd_to_8segment(a: led_character) return led_8_segment is
155
                variable r: std_ulogic_vector(7 downto 0);
156
        begin
157
                case a is
158
                        when "0000" => r := x"3F"; -- 0
159
                        when "0001" => r := x"06"; -- 1
160
                        when "0010" => r := x"5B"; -- 2
161
                        when "0011" => r := x"4F"; -- 3
162
                        when "0100" => r := x"66"; -- 4
163
                        when "0101" => r := x"6D"; -- 5
164
                        when "0110" => r := x"7D"; -- 6
165
                        when "0111" => r := x"07"; -- 7
166
                        when "1000" => r := x"7F"; -- 8
167
                        when "1001" => r := x"6F"; -- 9
168
                        when "1010" => r := x"00"; -- Blank
169
                        when "1011" => r := x"80"; -- .
170
                        when "1100" => r := x"40"; -- -
171
                        when "1101" => r := x"00"; -- Unused
172
                        when "1110" => r := x"00"; -- Unused
173
                        when "1111" => r := x"00"; -- Unused
174
                        when others => r := x"00"; -- Unused
175
                end case;
176
                return r;
177
        end function;
178
 
179
        function char_to_8segment(a: led_character) return led_8_segment is
180
        begin
181
                if use_bcd_not_hex then
182
                        return invert(bcd_to_8segment(a));
183
                else
184
                        return invert(hex_to_8segment(a));
185
                end if;
186
        end function;
187
 
188
        signal leds_o: std_ulogic_vector(leds'range) := (others => '0');
189
 
190
        signal do_shift:  std_ulogic := '0';
191
        signal shift_reg: std_ulogic_vector(number_of_led_displays - 1 downto 0) := (0 => '1', others => '0');
192
 
193
 
194
        signal leds_reg_o: std_ulogic_vector(leds'range) := (others => '0');
195
        signal leds_reg_we_o: std_ulogic := '0';
196
begin
197
        an <= invert(shift_reg);
198
 
199
        segment_reg: entity work.reg
200
                generic map(N => number_of_led_displays * character_length)
201
                port map(
202
                        clk => clk,
203
                        rst => rst,
204
                        we  => leds_we,
205
                        di  => leds,
206
                        do  => leds_reg_o);
207
 
208
        segment_reg_re: entity work.reg
209
                generic map(N => 1)
210
                port map(
211
                        clk   => clk,
212
                        rst   => rst,
213
                        we    => '1',
214
                        di(0) => leds_we,
215
                        do(0) => leds_reg_we_o);
216
 
217
        led_gen: for i in number_of_led_displays - 1 downto 0 generate
218
                led_i: entity work.reg
219
                        generic map(
220
                                N   => character_length)
221
                        port map(
222
                                clk => clk,
223
                                rst => rst,
224
                                we  => leds_reg_we_o,
225
                                di  => leds_reg_o((i*character_length) + character_length - 1 downto (i*character_length)),
226
                                do  => leds_o((i*character_length) + character_length - 1 downto (i*character_length)));
227
        end generate;
228
 
229
        timer: entity work.timer_us
230
                generic map(
231
                        clock_frequency => clock_frequency,
232
                        timer_period_us => refresh_rate_us)
233
                port map(
234
                        clk             => clk,
235
                        rst             => rst,
236
                        co              => do_shift);
237
 
238
        process(clk, do_shift, shift_reg)
239
        begin
240
                if rising_edge(clk) then
241
                        if do_shift = '1' then
242
                                shift_reg <= shift_reg(number_of_led_displays - 2 downto 0) & shift_reg(number_of_led_displays - 1);
243
                        end if;
244
                else
245
                        shift_reg <= shift_reg;
246
                end if;
247
        end process;
248
 
249
        process(leds_o, shift_reg)
250
        begin
251
                ka <= (others => '0');
252
 
253
                for i in  number_of_led_displays - 1 downto 0 loop
254
                        if '1' = shift_reg(number_of_led_displays - i - 1) then
255
                                ka <= char_to_8segment(leds_o(i*character_length + character_length - 1 downto (i*character_length)));
256
                        end if;
257
                end loop;
258
        end process;
259
end architecture;
260
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.