summaryrefslogtreecommitdiff
path: root/2004/n/fpga/src/portserie/uart/txmit.vhd
blob: 0088729afce7fa9c0bf77ce96cffcbc8403a5f9a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.ALL;

entity TXMIT is
   port (
         MCLKX16 : in  std_logic;
         WRITE   : in  std_logic;
         RESET   : in  std_logic;
	 DATA    : in  std_logic_vector(7 downto 0);

	 TX      : out std_logic;
	 TXRDY   : out std_logic
	 );
end TXMIT;

architecture RTL of TXMIT is

   signal   WRITE1      : std_logic;
   signal   WRITE2      : std_logic;
   signal   TXDONE1     : std_logic;
   signal   TXDONE      : std_logic;
   signal   THR         : std_logic_vector(7 downto 0);
   signal   TSR         : std_logic_vector(7 downto 0);
   signal   TAG1        : std_logic;
   signal   TAG2        : std_logic;
   constant PARITYMODE  : std_logic :='1';
   signal   TXPARITY    : std_logic;
   signal   TXCLK       : std_logic;
   signal   PARITYCYCLE : std_logic;
   signal   TXDATARDY   : std_logic;
   signal   CNT         : std_logic_vector(2 downto 0);


begin
   
   -- Paritycycle = 1 on next to last cycle, this means when tsr[1] gets tag2.

   PARITYCYCLE <= TSR(1) and not (TAG2 or TAG1 or TSR(7) or TSR(6) or TSR(5)
                  or TSR(4) or TSR(3) or TSR(2));


   -- txdone = 1 when done shifting, this means when tx gets tag2.

   TXDONE <= not (TAG2 or TAG1 or TSR(7) or TSR(6) or TSR(5) or TSR(4) or TSR(3)
             or TSR(2) or TSR(1) or TSR(0));


   -- Ready for new date to be written, when no data is in transmit hold register.

   TXRDY <= not TXDATARDY;


   -- Latch data[7:0] into the transmit hold register at posedge of write.

   THR_WRITE : process (RESET, WRITE)
   begin
      if (RESET = '1') then
         THR <= "00000000";
      elsif (WRITE'event and WRITE = '1') then
         THR <= DATA;
      end if;
   end process;


   -- Toggle txclk every 8 counts, which divides the clock by 16, to generate the baud clock

   BAUD_CLOCK_GEN : process (MCLKX16, RESET)
   begin
      if (RESET = '1') then
         TXCLK <= '0';
         CNT   <= "000";
      elsif (MCLKX16'event and MCLKX16 = '1') then
         if (CNT = "000") then
            TXCLK <= not TXCLK;
         end if;
         CNT <= CNT + 1;
      end if;
   end process;


   SHIFT_OUT : process (TXCLK, RESET)
   begin
      -- idle_reset;
      if (RESET = '1') then
      	 TSR      <= (others => '0');
         TAG2     <= '0';
         TAG1     <= '0';
         TXPARITY <= PARITYMODE;
         TX       <= '1';
      elsif (TXCLK'event and TXCLK = '1') then
         if (TXDONE = '1' and TXDATARDY = '1') then
            -- load_data;
            TSR      <= THR;
            TAG2     <= '1';
            TAG1     <= '1';
            TXPARITY <= PARITYMODE;
            TX       <= '0';
         else
            -- shift_data;
            TSR      <= '0'&tsr(7 downto 1);
            TSR(7)   <= TAG1;
            TAG1     <= TAG2;
			TAG2     <= '0';
            TXPARITY <= TXPARITY xor TSR(0);

            if (TXDONE = '1') then
               TX <= '1';
               elsif (PARITYCYCLE = '1') then
                  TX <= TXPARITY;
               else
                  TX <= TSR(0);
            end if;
         end if;
      end if;
   end process;
            

   process (MCLKX16, RESET)
   begin
      if (RESET = '1') then
         TXDATARDY <= '0';
         WRITE2    <= '1';
         WRITE1    <= '1';
         TXDONE1   <= '1';
      elsif (MCLKX16'event and MCLKX16 = '1') then
         if (WRITE1 = '1' and WRITE2 = '0') then
            TXDATARDY <= '1';
         elsif (TXDONE = '0' and TXDONE1 = '1') then
            TXDATARDY <= '0';
         end if;
         WRITE2  <= WRITE1;
         WRITE1  <= WRITE;
         TXDONE1 <= TXDONE;
      end if;
   end process;

end RTL;