📄 ex_7_1_uart.vhd
字号:
library ieee ;use ieee.std_logic_1164.all ;use ieee.std_logic_arith.all ;entity tx_datapath is port( din : in std_logic_vector (7 downto 0) ; state : in std_logic_vector (3 downto 0) ; rst,wrn,clk1x: in std_logic; sdo,tsre : out std_logic );end tx_datapath;architecture a of tx_datapath is signal tsr : std_logic_vector (7 downto 0) ; --Tx shift reg signal tbr : std_logic_vector (7 downto 0) ; --Tx buffer regbegin --TBR process - load tbr with wrn process (rst,wrn,din) begin if rst = '1' then tbr <= (others => '0') ; elsif wrn'event and wrn = '0' then tbr <= din ; end if ; end process ; --Main shifter process process (rst,clk1x,state,tbr) begin if rst = '1' then sdo <= '1' ;--serial data out(sdo)=1 in idle state tsre <= '1' ; tsr <= "00000000" ; elsif clk1x'event and clk1x = '1' then if state = "0001" then tsr <= tbr ;--trans tbr to tsr tsre <= '0' ;--tsr is not empty now elsif state = "0010" then sdo <= '0' ;--send start bit elsif state >= "0011" and state <= "1011" then --between count 3 to 11, shift left tsr tsr <= '1' & tsr(7 downto 1); sdo <= tsr(0) ;--rightmost bit is output elsif state = "1100" then tsre <= '1' ; end if ; end if ; end process ;end a;library ieee ;use ieee.std_logic_1164.all ;use ieee.std_logic_arith.all ;use ieee.std_logic_unsigned.all ;entity tx_clockgen is port( state : in std_logic_vector (3 downto 0) ; rst,wrn,clk16x : in std_logic; clk1x,clk1x_enable,tbre: out std_logic );end tx_clockgen;architecture a of tx_clockgen is signal clkdiv : std_logic_vector (3 downto 0) ; signal clk_enable,wrn1,wrn2,tbre_int:std_logic;begin process (rst,clk16x,clk_enable) begin if rst = '1' then clkdiv <= "0000" ; elsif clk16x'event and clk16x = '1' then if clk_enable = '1' then clkdiv <= clkdiv + 1 ; end if ; end if ; end process ; clk1x <= clkdiv(3) ;--MSB of Divide counter is clk1x clk1x_enable<=clk_enable; --Clock enable process --Neg edge of wrn sets clk1x_enable and bit counter --reaching 1101 resets it process (rst,clk16x,wrn,wrn1,wrn2,tbre_int) begin if rst = '1' then clk_enable <= '0' ;--Initially div cntr is disabled tbre_int <= '1' ; --Initial tbr is empty wrn1<='1';wrn2<='1'; elsif clk16x'event and clk16x = '1' then wrn1<=wrn;wrn2<=wrn1; --Produce delayed wrn if wrn1 = '0' and wrn2 = '1' then --fall edge of wrn tbre_int <= '0' ; --Make tbr not empty clk_enable <= '1' ; --Enable div clk elsif std_logic_vector(state) = "0010" then tbre_int <= '1' ; --After sending 2 bits, tbr is ready elsif std_logic_vector(state) = "1101" then clk_enable <= '0' ; --stop clk after 13 pulses elsif (state = 0) and (tbre_int='0') then clk_enable <= '1' ; end if ; end if ; tbre<=tbre_int; end process ; end a;library ieee ;use ieee.std_logic_1164.all ;use ieee.std_logic_arith.all ;use ieee.std_logic_unsigned.all ;entity tx_control is port( state : out std_logic_vector (3 downto 0) ; rst : in std_logic; clk1x,clk1x_enable: in std_logic );end tx_control;architecture a of tx_control is signal state_cntr : std_logic_vector (3 downto 0) ;begin --state counter logic process (rst,clk1x,clk1x_enable) begin if rst = '1' or clk1x_enable = '0' then state_cntr <= "0000" ; elsif clk1x'event and clk1x = '1' then if clk1x_enable = '1' then state_cntr <= state_cntr + 1 ; end if ; end if ; end process ; state<=state_cntr;end a;library ieee ;use ieee.std_logic_1164.all ;use ieee.std_logic_arith.all ;entity txmit1 isport (rst,clk16x,wrn : in std_logic ;--wrn is write enable bar din : in std_logic_vector(7 downto 0) ;--Parallel data in tbre : out std_logic ;--Tx buffer empty tsre : out std_logic ;--Tx shift reg empty sdo : out std_logic --serial data out ) ;end txmit1 ;architecture v1 of txmit1 is component tx_datapath port( din : in std_logic_vector (7 downto 0) ; state : in std_logic_vector (3 downto 0) ; rst,wrn,clk1x : in std_logic; sdo,tsre : out std_logic ); end component; component tx_clockgen port( state : in std_logic_vector (3 downto 0) ; rst,wrn,clk16x : in std_logic; clk1x,clk1x_enable,tbre: out std_logic ); end component; component tx_control port( state : out std_logic_vector (3 downto 0) ; rst : in std_logic; clk1x,clk1x_enable: in std_logic ); end component; signal state: std_logic_vector (3 downto 0) ; signal clk1x,clk1x_enable :std_logic;begin dat:tx_datapath port map(din,state,rst,wrn,clk1x,sdo,tsre); cgn:tx_clockgen port map(state,rst,wrn,clk16x,clk1x,clk1x_enable,tbre); ctr:tx_control port map(state,rst,clk1x,clk1x_enable);end v1;--UART receiver--************************library ieee ;use ieee.std_logic_1164.all ;use ieee.std_logic_arith.all ;use ieee.std_logic_unsigned.all ;entity rcvr_ctrl is port ( rst,clk16x,rxd,rdn : in std_logic ; no_bits_rcvd:out std_logic_vector (3 downto 0); clk1x,data_ready : out std_logic ) ;end rcvr_ctrl ;architecture a of rcvr_ctrl is signal rxd1,rxd2 : std_logic ;--delayed rxd signal clk1x_enable : std_logic ;--twice delayed rxd signal bits_rcvd : std_logic_vector(3 downto 0) ; signal clkdiv : std_logic_vector(3 downto 0) ;begin --Clock generator logic process (rst,clk16x,rxd1,rxd2,rxd,bits_rcvd,clkdiv) begin if rst = '1' or bits_rcvd = 12 then rxd1 <= '1' ; rxd2 <= '1' ; clk1x_enable <= '0';clkdiv <= "0000" ; elsif clk16x'event and clk16x = '1' then rxd2 <= rxd1 ; rxd1 <= rxd ; if rxd1 = '0' and rxd2 = '1' then clk1x_enable <= '1' ; end if ; if clk1x_enable = '1' then clkdiv <= clkdiv + "0001" ; end if ; end if ; clk1x <= clkdiv(3); end process ; --bit counting logic process (rst,clkdiv,clk1x_enable,bits_rcvd) beginif rst = '1' or (bits_rcvd = 12 and clk1x_enable = '0') then bits_rcvd <= "0000" ; elsif clkdiv(3)'event and clkdiv(3) = '1' then if clk1x_enable = '1' then bits_rcvd <= bits_rcvd + 1 ; end if ; end if ; end process ; --data ready logic - data_ready =1 when no_bits_rcvd = "1100" process (rst,clkdiv,rdn,bits_rcvd) begin if rst = '1' or rdn = '0' then data_ready <= '0' ; elsif clkdiv(3)'event and clkdiv(3) = '1' then if bits_rcvd = 10 then data_ready <= '1' ; end if ; end if ; end process ; no_bits_rcvd <= bits_rcvd;end a;--receiver shift registerslibrary ieee ;use ieee.std_logic_1164.all ;use ieee.std_logic_arith.all ;use ieee.std_logic_unsigned.all ;entity rcvr_regs is port ( rst,clk1x,rdn,rxd : in std_logic ; no_bits_rcvd:in std_logic_vector (3 downto 0); dout : out std_logic_vector (7 downto 0) ) ;end rcvr_regs ;architecture a of rcvr_regs is signal rsr : std_logic_vector (7 downto 0) ;--rcv shift reg signal rbr : std_logic_vector (7 downto 0) ;--rcv buf regbegin --rbr and rsr logic process (clk1x,rst) begin if rst = '1' then rsr <= "00000000" ; rbr <= "00000000" ; elsif clk1x'event and clk1x = '1' then if no_bits_rcvd >= 1 and no_bits_rcvd <= 8 then rsr(7) <= rxd ; rsr(6 downto 0) <= rsr(7 downto 1) ; elsif no_bits_rcvd = 10 then rbr <= rsr ; end if ; end if ; end process ; dout <= rbr;end a;library ieee ;use ieee.std_logic_1164.all ;use ieee.std_logic_arith.all ;entity rcvr is port ( rst,clk16x,rxd,rdn : in std_logic ; dout : out std_logic_vector (7 downto 0) ; data_ready : out std_logic ) ;end rcvr ;architecture v2 of rcvr is component rcvr_ctrl port ( rst,clk16x,rxd,rdn : in std_logic ; no_bits_rcvd:out std_logic_vector (3 downto 0); clk1x,data_ready : out std_logic ) ; end component; component rcvr_regs port ( rst,clk1x,rdn,rxd : in std_logic ; no_bits_rcvd:in std_logic_vector (3 downto 0); dout : out std_logic_vector (7 downto 0) ) ; end component; signal no_bits_rcvd: std_logic_vector (3 downto 0); signal dout_int: std_logic_vector (7 downto 0); signal clk1x : std_logic ;begin ctrl:rcvr_ctrl port map(rst,clk16x,rxd,rdn,no_bits_rcvd,clk1x,data_ready); regs:rcvr_regs port map(rst,clk1x,rdn,rxd,no_bits_rcvd,dout_int); dout <= dout_int when rdn = '0' else "ZZZZZZZZ" ;end v2;--UART--************************library ieee ;use ieee.std_logic_1164.all ;use ieee.std_logic_arith.all ;entity uart is port ( rst,clk16x,rxd,rdn,wrn : in std_logic ; dout : out std_logic_vector (7 downto 0) ; din : in std_logic_vector (7 downto 0) ; data_ready,tbre,tsre,sdo : out std_logic ) ;end uart ;architecture a of uart is component txmit1 port (rst,clk16x,wrn : in std_logic ;--wrn is wr enable bar din : in std_logic_vector(7 downto 0) ;--Parallel data in tbre : out std_logic ;--Tx buffer empty tsre : out std_logic ;--Tx shift reg empty sdo : out std_logic --serial data out ) ; end component; component rcvr port ( rst,clk16x,rxd,rdn : in std_logic ; dout : out std_logic_vector (7 downto 0) ; data_ready : out std_logic ) ; end component;begin r:rcvr port map(rst,clk16x,rxd,rdn,dout,data_ready); t:txmit1 port map(rst,clk16x,wrn,din,tbre,tsre,sdo);end a;library ieee ;use ieee.std_logic_1164.all ;entity uart_tb is end uart_tb;architecture beh of uart_tb is signal rst,clk16x,rdn,wrn: std_logic ; signal dout: std_logic_vector (7 downto 0); signal din : std_logic_vector (7 downto 0); signal data_ready,tbre,tsre:std_logic; signal run:std_logic:='0'; signal rxd_sdo:std_logic;begin clk16X <= not clk16X after 10 ns when run = '1' else '0'; U:entity work.UART port map ( rst, clk16x, rxd_sdo, rdn, wrn, dout, din, data_ready,tbre,tsre,rxd_sdo ) ; process begin rst <='1';din <= "11110101";rdn<='1'; wrn <= '1'; wait for 10 ns; rst <='0';wait for 10 ns; run <= '1'; wrn <='0';wait for 10 ns; wrn <='1';wait for 10 ns; wait until tsre = '1'; report "Byte transmitted"; wait until data_ready = '1'; report "Byte received"; wait; end process;end beh;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -