1 |
37 |
leonardoar |
--! @file
|
2 |
|
|
--! @brief Baud generator http://www.fpga4fun.com/SerialInterface.html
|
3 |
6 |
leonardoar |
library ieee;
|
4 |
|
|
use ieee.std_logic_1164.all;
|
5 |
|
|
use ieee.std_logic_unsigned.all;
|
6 |
15 |
leonardoar |
use ieee.std_logic_arith.all;
|
7 |
|
|
use ieee.numeric_std.all;
|
8 |
6 |
leonardoar |
|
9 |
|
|
--! Use CPU Definitions package
|
10 |
|
|
use work.pkgDefinitions.all;
|
11 |
|
|
|
12 |
|
|
entity baud_generator is
|
13 |
37 |
leonardoar |
Port ( rst : in STD_LOGIC; --! Reset Input
|
14 |
|
|
clk : in STD_LOGIC; --! Clock input
|
15 |
|
|
cycle_wait : in STD_LOGIC_VECTOR ((nBitsLarge-1) downto 0); --! Number of cycles to wait for baud generation
|
16 |
|
|
baud_oversample : out std_logic; --! Oversample(8x) version of baud (Used on serial_receiver)
|
17 |
|
|
baud : out STD_LOGIC); --! Baud generation output (Used on serial_transmitter)
|
18 |
6 |
leonardoar |
end baud_generator;
|
19 |
|
|
|
20 |
37 |
leonardoar |
--! @brief Baud generator http://www.fpga4fun.com/SerialInterface.html
|
21 |
|
|
--! @details Implement block that will generate the desired baud (115200, 9600, etc...) from main clock (50Mhz)
|
22 |
6 |
leonardoar |
architecture Behavioral of baud_generator is
|
23 |
|
|
signal genTick : std_logic;
|
24 |
11 |
leonardoar |
signal genTickOverSample : std_logic;
|
25 |
6 |
leonardoar |
begin
|
26 |
14 |
leonardoar |
process (rst, clk, cycle_wait)
|
27 |
6 |
leonardoar |
variable wait_clk_cycles : STD_LOGIC_VECTOR ((nBitsLarge-1) downto 0);
|
28 |
|
|
variable half_cycle : STD_LOGIC_VECTOR ((nBitsLarge-1) downto 0);
|
29 |
|
|
begin
|
30 |
|
|
if rst = '1' then
|
31 |
|
|
wait_clk_cycles := (others => '0');
|
32 |
|
|
half_cycle := '0' & cycle_wait(cycle_wait'high downto 1);
|
33 |
|
|
genTick <= '0';
|
34 |
|
|
elsif rising_edge(clk) then
|
35 |
8 |
leonardoar |
-- Just decremented the cycle_wait by one because genTick would be updated on the next cycle
|
36 |
|
|
-- and we really want to bring genTick <= '1' when (wait_clk_cycles = cycle_wait)
|
37 |
15 |
leonardoar |
if wait_clk_cycles = (cycle_wait - conv_std_logic_vector(1, nBitsLarge)) then
|
38 |
6 |
leonardoar |
genTick <= '1';
|
39 |
|
|
wait_clk_cycles := (others => '0');
|
40 |
|
|
else
|
41 |
15 |
leonardoar |
wait_clk_cycles := wait_clk_cycles + conv_std_logic_vector(1, nBitsLarge);
|
42 |
6 |
leonardoar |
-- If we're at half of the cycle
|
43 |
|
|
if wait_clk_cycles = half_cycle then
|
44 |
16 |
leonardoar |
genTick <= '0';
|
45 |
6 |
leonardoar |
end if;
|
46 |
15 |
leonardoar |
end if;
|
47 |
|
|
|
48 |
|
|
-- Avoid creation of transparent latch (By default the VHDL will create an register for vectors that are assigned only in one
|
49 |
|
|
-- ocasion of a (if, case) instruction
|
50 |
|
|
half_cycle := '0' & cycle_wait(cycle_wait'high downto 1);
|
51 |
6 |
leonardoar |
end if;
|
52 |
|
|
end process;
|
53 |
|
|
|
54 |
|
|
baud <= genTick;
|
55 |
11 |
leonardoar |
baud_oversample <= genTickOverSample;
|
56 |
|
|
|
57 |
|
|
-- Process to generate the overclocked (8x) sample
|
58 |
14 |
leonardoar |
process (rst, clk, cycle_wait)
|
59 |
11 |
leonardoar |
variable wait_clk_cycles : STD_LOGIC_VECTOR ((nBitsLarge-1) downto 0);
|
60 |
|
|
variable half_cycle : STD_LOGIC_VECTOR ((nBitsLarge-1) downto 0);
|
61 |
15 |
leonardoar |
variable cycle_wait_oversample : STD_LOGIC_VECTOR ((nBitsLarge-1) downto 0);
|
62 |
11 |
leonardoar |
begin
|
63 |
|
|
if rst = '1' then
|
64 |
|
|
wait_clk_cycles := (others => '0');
|
65 |
|
|
|
66 |
32 |
leonardoar |
-- Divide cycle_wait by 8
|
67 |
15 |
leonardoar |
--cycle_wait_oversample := '0' & cycle_wait(cycle_wait'high downto 1);
|
68 |
|
|
--cycle_wait_oversample := '0' & cycle_wait_oversample(cycle_wait_oversample'high downto 1);
|
69 |
32 |
leonardoar |
--cycle_wait_oversample := '0' & cycle_wait_oversample(cycle_wait_oversample'high downto 1);
|
70 |
|
|
cycle_wait_oversample := "000" & cycle_wait(cycle_wait'high downto 3); -- Shift right by 3
|
71 |
11 |
leonardoar |
|
72 |
15 |
leonardoar |
|
73 |
11 |
leonardoar |
-- Half of cycle_wait_oversample
|
74 |
15 |
leonardoar |
half_cycle := '0' & cycle_wait_oversample(cycle_wait_oversample'high downto 1); -- Shift right by 1
|
75 |
11 |
leonardoar |
genTickOverSample <= '0';
|
76 |
|
|
elsif rising_edge(clk) then
|
77 |
|
|
-- Just decremented the cycle_wait by one because genTick would be updated on the next cycle
|
78 |
|
|
-- and we really want to bring genTick <= '1' when (wait_clk_cycles = cycle_wait)
|
79 |
15 |
leonardoar |
if wait_clk_cycles = (cycle_wait_oversample - conv_std_logic_vector(1, nBitsLarge)) then
|
80 |
11 |
leonardoar |
genTickOverSample <= '1';
|
81 |
|
|
wait_clk_cycles := (others => '0');
|
82 |
|
|
else
|
83 |
15 |
leonardoar |
wait_clk_cycles := wait_clk_cycles + conv_std_logic_vector(1, nBitsLarge);
|
84 |
11 |
leonardoar |
-- If we're at half of the cycle
|
85 |
|
|
if wait_clk_cycles = half_cycle then
|
86 |
|
|
genTickOverSample <= '0';
|
87 |
|
|
end if;
|
88 |
15 |
leonardoar |
end if;
|
89 |
|
|
|
90 |
|
|
-- Avoid creation of transparent latch (By default the VHDL will create an register for vectors that are assigned only in one
|
91 |
|
|
-- ocasion of a (if, case) instruction
|
92 |
32 |
leonardoar |
cycle_wait_oversample := "000" & cycle_wait(cycle_wait'high downto 3);
|
93 |
15 |
leonardoar |
half_cycle := '0' & cycle_wait_oversample(cycle_wait_oversample'high downto 1);
|
94 |
11 |
leonardoar |
end if;
|
95 |
|
|
end process;
|
96 |
6 |
leonardoar |
|
97 |
|
|
end Behavioral;
|
98 |
|
|
|