URL
https://opencores.org/ocsvn/System68/System68/trunk
Subversion Repositories System68
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 6 to Rev 7
- ↔ Reverse comparison
Rev 6 → Rev 7
/trunk/vhdl/txunit3.vhd
0,0 → 1,302
--===========================================================================-- |
-- |
-- S Y N T H E Z I A B L E miniUART C O R E |
-- |
-- www.OpenCores.Org - January 2000 |
-- This core adheres to the GNU public license |
-- |
-- Design units : miniUART core for the System68 |
-- |
-- File name : txunit2.vhd |
-- |
-- Purpose : Implements an miniUART device for communication purposes |
-- between the CPU68 processor and the Host computer through |
-- an RS-232 communication protocol. |
-- |
-- Dependencies : IEEE.Std_Logic_1164 |
-- |
--===========================================================================-- |
------------------------------------------------------------------------------- |
-- Revision list |
-- Version Author Date Changes |
-- |
-- 0.1 Ovidiu Lupas 15 January 2000 New model |
-- 2.0 Ovidiu Lupas 17 April 2000 unnecessary variable removed |
-- olupas@opencores.org |
-- |
-- 3.0 John Kent 5 January 2003 added 6850 word format control |
-- 3.1 John Kent 12 January 2003 Rearranged state machine code |
-- 3.2 John Kent 30 March 2003 Revamped State machine |
-- 3.3 John Kent 16 January 2004 Major re-write - added baud rate gen |
-- |
-- dilbert57@opencores.org |
-- |
------------------------------------------------------------------------------- |
-- Description : |
------------------------------------------------------------------------------- |
-- Entity for the Tx Unit -- |
------------------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
use ieee.std_logic_unsigned.all; |
|
------------------------------------------------------------------------------- |
-- Transmitter unit |
------------------------------------------------------------------------------- |
entity TxUnit is |
port ( |
Clk : in Std_Logic; -- Clock signal |
Reset : in Std_Logic; -- Reset input |
LoadD : in Std_Logic; -- Load transmit data |
DAIn : in Std_Logic_Vector(7 downto 0); |
WdFmt : in Std_Logic_Vector(2 downto 0); -- word format |
BdFmt : in Std_Logic_Vector(1 downto 0); -- baud format |
TxClk : in Std_Logic; -- Enable input |
TxDat : out Std_Logic; -- RS-232 data output |
TBE : out Std_Logic ); -- Tx buffer empty |
end; --================== End of entity ==============================-- |
------------------------------------------------------------------------------- |
-- Architecture for TxUnit |
------------------------------------------------------------------------------- |
architecture Behaviour of TxUnit is |
type TxStateType is ( TxIdle_State, Start_State, Data_State, Parity_State, Stop_State ); |
----------------------------------------------------------------------------- |
-- Signals |
----------------------------------------------------------------------------- |
signal TxClkDel : Std_Logic; -- Delayed Tx Input Clock |
signal TxClkEdge : Std_Logic; -- Tx Input Clock Edge pulse |
signal TxClkCnt : Std_Logic_Vector(5 downto 0); -- Tx Baud Clock Counter |
signal TxBdDel : Std_Logic; -- Delayed Tx Baud Clock |
signal TxBdEdge : Std_Logic; -- Tx Baud Clock Edge pulse |
signal TxBdClk : Std_Logic; -- Tx Baud Clock |
|
signal TBuff : Std_Logic_Vector(7 downto 0); -- transmit buffer |
signal TBufE : Std_Logic; -- Transmit Buffer Empty |
|
signal TReg : Std_Logic_Vector(7 downto 0); -- transmit register |
signal TxParity : Std_logic; -- Parity Bit |
signal DataCnt : Std_Logic_Vector(3 downto 0); -- Data Bit Counter |
signal TRegE : Std_Logic; -- Transmit Register empty |
signal TRegEDel : Std_Logic; -- Transmit Register empty |
signal TRegEEdge : Std_Logic; |
signal TxState : TxStateType; |
signal TxDbit : Std_Logic; |
begin |
|
--------------------------------------------------------------------- |
-- Transmit Clock Edge Detection |
-- A falling edge will produce a one clock cycle pulse |
--------------------------------------------------------------------- |
txunit_clock_edge : process(Clk, Reset, TxClk, TxClkDel ) |
begin |
if Reset = '1' then |
TxClkDel <= TxClk; |
TxClkEdge <= '0'; |
elsif Clk'event and Clk = '0' then |
TxClkDel <= TxClk; |
TxClkEdge <= TxClkDel and (not TxClk); |
end if; |
end process; |
|
|
--------------------------------------------------------------------- |
-- Transmit Clock Divider |
-- Advance the count only on an input clock pulse |
--------------------------------------------------------------------- |
txunit_clock_divide : process(Clk, Reset, TxClkEdge, TxClkCnt ) |
begin |
if Reset = '1' then |
TxClkCnt <= "000000"; |
elsif Clk'event and Clk = '0' then |
if TxClkEdge = '1' then |
TxClkCnt <= TxClkCnt + "000001"; |
else |
TxClkCnt <= TxClkCnt; |
end if; -- TxClkEdge |
end if; -- reset / clk |
end process; |
|
--------------------------------------------------------------------- |
-- Receiver Clock Selector |
-- Select output then look for rising edge |
--------------------------------------------------------------------- |
txunit_clock_select : process(Clk, Reset, BdFmt, TxClk, TxClkCnt, |
TxBdDel, TxBdEdge ) |
begin |
-- BdFmt |
-- 0 0 - Baud Clk divide by 1 |
-- 0 1 - Baud Clk divide by 16 |
-- 1 0 - Baud Clk divide by 64 |
-- 1 1 - reset |
case BdFmt is |
when "00" => -- Div by 1 |
TxBdClk <= TxClk; |
when "01" => -- Div by 16 |
TxBdClk <= TxClkCnt(3); |
when "10" => -- Div by 64 |
TxBdClk <= TxClkCnt(5); |
when others => -- reset |
TxBdClk <= '0'; |
end case; |
|
if Reset = '1' then |
TxBdDel <= TxBdClk; |
TxBdEdge <= '0'; |
elsif Clk'event and Clk = '0' then |
TxBdDel <= TxBdClk; |
TxBdEdge <= TxBdClk and (not TxBdDel); |
end if; |
end process; |
|
--------------------------------------------------------------------- |
-- Transmit Buffer Empty Edge |
-- generate a negative edge pulse |
--------------------------------------------------------------------- |
txunit_busy : process(Clk, Reset, TRegE, TRegEDel ) |
begin |
if Reset = '1' then |
TRegEDel <= '0'; |
TRegEEdge <= '0'; |
elsif Clk'event and Clk = '0' then |
TRegEDel <= TRegE; |
TRegEEdge <= TregEDel and (not TRegE ); -- falling edge |
end if; |
end process; |
|
--------------------------------------------------------------------- |
-- Transmitter activation process |
--------------------------------------------------------------------- |
txunit_write : process(Clk, Reset, LoadD, DAIn, TBufE, TRegEEdge ) |
begin |
if Reset = '1' then |
TBufE <= '1'; |
TBuff <= "00000000"; |
elsif Clk'event and Clk = '0' then |
if LoadD = '1' then |
TBuff <= DAIn; |
TBufE <= '0'; |
else |
TBuff <= TBuff; |
if (TBufE = '0') and (TRegEEdge = '1') then |
-- Once the transmitter is started |
-- We can flag the buffer empty again. |
TBufE <= '1'; |
else |
TBufE <= TBufE; |
end if; |
end if; |
end if; -- clk / reset |
TBE <= TBufE; |
|
end process; |
|
----------------------------------------------------------------------------- |
-- Implements the Tx unit |
----------------------------------------------------------------------------- |
txunit_transmit : process(Clk, TxState, TxDbit, TBuff, TReg, |
TxBdEdge, TxParity, DataCnt, WdFmt, |
TBufE, TRegE ) |
begin |
if Reset = '1' then |
TxDbit <= '1'; |
TReg <= "00000000"; |
TxParity <= '0'; |
DataCnt <= "0000"; |
TRegE <= '1'; |
TxState <= TxIdle_State; |
elsif Clk'event and Clk = '0' then |
if TxBdEdge = '1' then |
case TxState is |
when TxIdle_State => -- TxIdle_State (also 1st or 2nd Stop bit) |
TxDbit <= '1'; |
TReg <= TBuff; |
TxParity <= '0'; |
DataCnt <= "0000"; |
TRegE <= '1'; |
if TBufE = '0' then |
TxState <= Start_State; |
else |
TxState <= TxIdle_State; |
end if; |
|
when Start_State => |
TxDbit <= '0'; -- Start bit |
TReg <= TReg; |
TxParity <= '0'; |
if WdFmt(2) = '0' then |
DataCnt <= "0110"; -- 7 data + parity |
else |
DataCnt <= "0111"; -- 8 data |
end if; |
TRegE <= '0'; |
TxState <= Data_State; |
|
when Data_State => |
TxDbit <= TReg(0); |
TReg <= '1' & TReg(7 downto 1); |
TxParity <= TxParity xor TReg(0); |
TRegE <= '0'; |
DataCnt <= DataCnt - "0001"; |
if DataCnt = "0000" then |
if (WdFmt(2) = '1') and (WdFmt(1) = '0') then |
if WdFmt(0) = '0' then -- 8 data bits |
TxState <= Stop_State; -- 2 stops |
else |
TxState <= TxIdle_State; -- 1 stop |
end if; |
else |
TxState <= Parity_State; -- parity |
end if; |
else |
TxState <= Data_State; |
end if; |
|
when Parity_State => -- 7/8 data + parity bit |
if WdFmt(0) = '0' then |
TxDbit <= not( TxParity ); -- even parity |
else |
TXDbit <= TxParity; -- odd parity |
end if; |
Treg <= Treg; |
TxParity <= '0'; |
TRegE <= '0'; |
DataCnt <= "0000"; |
if WdFmt(1) = '0' then |
TxState <= Stop_State; -- 2 stops |
else |
TxState <= TxIdle_State; -- 1 stop |
end if; |
|
when Stop_State => -- first stop bit |
TxDbit <= '1'; -- 2 stop bits |
Treg <= Treg; |
TxParity <= '0'; |
DataCnt <= "0000"; |
TRegE <= '0'; |
TxState <= TxIdle_State; |
|
when others => -- Undefined |
TxDbit <= TxDbit; |
Treg <= Treg; |
TxParity <= '0'; |
DataCnt <= "0000"; |
TRegE <= TregE; |
TxState <= TxIdle_State; |
|
end case; -- TxState |
|
else -- TxBdEdge |
TxDbit <= TxDbit; |
TReg <= TReg; |
TxParity <= TxParity; |
DataCnt <= DataCnt; |
TRegE <= TRegE; |
TxState <= TxState; |
end if; -- TxBdEdge |
end if; -- clk / reset |
|
TxDat <= TxDbit; |
end process; |
|
end Behaviour; --=================== End of architecture ====================-- |