📄 mc8051_siu.vhd
字号:
-------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
-----------------------------ENTITY DECLARATION--------------------------------
entity mc8051_siu is
port (clk : in std_logic; --< system clock
reset : in std_logic; --< system reset
tf_i : in std_logic; --< timer1 overflow flag
trans_i : in std_logic; --< 1 activates transm.
rxd_i : in std_logic; --< serial data input
scon_i : in std_logic_vector(5 downto 0); --< from SFR register
--< bits 7 to 3
sbuf_i : in std_logic_vector(7 downto 0); --< data for transm.
smod_i : in std_logic; --< low(0)/high baudrate
sbuf_o : out std_logic_vector(7 downto 0); --< received data
scon_o : out std_logic_vector(2 downto 0); --< to SFR register
--< bits 0 to 2
rxdwr_o : out std_logic; --< rxd direction signal
rxd_o : out std_logic; --< mode0 data output
txd_o : out std_logic); --< serial data output
end mc8051_siu;
-------------------------------------------------------------------------------
architecture rtl of mc8051_siu is
signal s_rxpre_count : unsigned(5 downto 0); -- Receive prescaler
signal s_txpre_count : unsigned(5 downto 0); -- Transmit prescaler
signal s_m0_shift_en : std_logic; -- masks out every sixteenth
-- rising edge of clk
signal s_m2_rxshift_en : std_logic; -- mode 2 shift enable
signal s_m13_rxshift_en : std_logic; -- mode 1 and 3 shift enable
signal s_m2_txshift_en : std_logic; -- mode 2 shift enable
signal s_m13_txshift_en : std_logic; -- mode 1 and 3 shift enable
signal s_ff0 : std_logic; -- flipflop for edge dedection
signal s_ff1 : std_logic; -- flipflop for edge dedection
signal s_tf : std_logic; -- synchronised timer flag
signal s_mode : unsigned(1 downto 0); -- mode
signal s_sm2 : std_logic; -- multi processor comm. bit
signal s_detect : std_logic; -- indicates start of recept.
signal s_ren : std_logic; -- receive enable
signal s_rxd_val : std_logic; -- received data bit
signal s_txdm0 : std_logic; -- shift clock for m0
signal s_ri : std_logic; -- external receive interrupt
signal s_trans : std_logic; -- enable transmission
signal s_recv_done : std_logic; -- receive interrupt
signal s_tran_done : std_logic; -- transmit interrupt
signal s_rb8 : std_logic; -- 8th data bit
signal s_tb8 : std_logic; -- 8th data bit
signal s_recv_state : unsigned(3 downto 0); -- state reg. of receive unit
signal s_tran_state : unsigned(3 downto 0); -- state reg. of transmit unit
signal s_rxd_ff0 : std_logic; -- sample flip-flop
signal s_rxd_ff1 : std_logic; -- sample flip-flop
signal s_rxd_ff2 : std_logic; -- sample flip-flop
signal s_det_ff0 : std_logic; -- rec. detect flip-flop
signal s_det_ff1 : std_logic; -- rec. detect flip-flop
signal s_tran_sh : unsigned(10 downto 0); -- transmission shift register
signal s_recv_sh : unsigned(7 downto 0); -- reception shift register
signal s_recv_buf : unsigned(7 downto 0); -- reception buffer register
signal s_rxm13_ff0 : std_logic; -- generates an enable singal
signal s_rxm13_ff1 : std_logic; -- generates an enable singal
signal s_txm13_ff0 : std_logic; -- generates an enable singal
signal s_txm13_ff1 : std_logic; -- generates an enable singal
begin -- architecture rtl
s_mode(1) <= scon_i(4); -- defines the 4 operating modes
s_mode(0) <= scon_i(3);
s_ren <= scon_i(1); -- receive enable
s_sm2 <= scon_i(2); -- 1 time or half time baud rate
s_tb8 <= scon_i(0); -- 9th data bit for transmission
s_ri <= scon_i(5); -- the receive interrupt bit of the
-- control unit
sbuf_o <= std_logic_vector(s_recv_buf); -- the receive buffer output
scon_o(0) <= s_recv_done; -- set when reception is completed
scon_o(1) <= s_tran_done; -- set when transmission is completed
scon_o(2) <= s_rb8; -- 9th data bit of reception
-------------------------------------------------------------------------------
-- The two flip flops are updated every rising clock edge of clk.
-- If a rising edge
-- on the port tf_i is dedected the signal s_tf is set to 1 for one period.
--
-- The transmission start signal s_trans is generated and held high till
-- the statemachine has been launched with its first shift.
--
-- The shift clock for mode0 is generated. It toggles with the half
-- s_m0_shift_en rate.
s_tf <= '1' when (s_ff0 = '1' and s_ff1 = '0') else '0';
p_sample_tf: process (clk,
reset)
begin
if reset = '1' then
s_ff0 <= '0';
s_ff1 <= '0';
s_trans <= '0';
else
if clk'event and clk = '1' then
s_ff0 <= tf_i;
s_ff1 <= s_ff0;
if trans_i = '1' then
s_trans <= '1';
else
case s_mode is
when ("00") =>
if s_m0_shift_en = '1' then
s_trans <= '0';
end if;
when ("01") =>
if s_m13_txshift_en = '1' then
s_trans <= '0';
end if;
when ("10") =>
if s_m2_txshift_en = '1' then
s_trans <= '0';
end if;
when others =>
if s_m13_txshift_en = '1' then
s_trans <= '0';
end if;
end case;
end if;
end if;
end if;
end process p_sample_tf;
-------------------------------------------------------------------------------
-- The register s_rxpre_count is driven with the system clock clk. So a
-- good enable signal (which is stable when clk has its rising edge) can be
-- derived to mask out every pulse of clk needed.
-- s_m0_shift_en activates every sixteenth clock cycle
-- s_m2_shift_en activates baud rates of 1/32 or 1/64 the clock frequenzy
-- depending on signal smod_i
-- s_m13_shift_en activates baud rates depending on timer/counter1 flag
s_m0_shift_en <= '1' when s_txpre_count(3 downto 0) = conv_unsigned(15,5)
else '0';
s_m2_rxshift_en <= '1' when (s_rxpre_count(4 downto 0) = conv_unsigned(31,5)
and smod_i = '1') or
(s_rxpre_count = conv_unsigned(63,6)
and smod_i = '0')
else '0';
s_m13_rxshift_en <= '1' when s_rxm13_ff0 = '1' and s_rxm13_ff1 = '0'
else '0';
s_m2_txshift_en <= '1' when (s_txpre_count(4 downto 0) = conv_unsigned(31,5)
and smod_i = '1') or
(s_txpre_count = conv_unsigned(63,6)
and smod_i = '0')
else '0';
s_m13_txshift_en <= '1' when s_txm13_ff0 = '1' and s_txm13_ff1 = '0'
else '0';
p_divide_clk: process (clk, reset)
begin
if reset = '1' then
s_rxpre_count <= conv_unsigned(0,6);
s_txpre_count <= conv_unsigned(0,6);
s_rxm13_ff0 <= '0';
s_rxm13_ff1 <= '0';
s_txm13_ff0 <= '0';
s_txm13_ff1 <= '0';
else
if clk'event and clk='1' then
s_rxm13_ff1 <= s_rxm13_ff0;
s_txm13_ff1 <= s_txm13_ff0;
if smod_i = '1' then
if s_rxpre_count(3 downto 0) = conv_unsigned(15,4) then
s_rxm13_ff0 <= '1';
else
s_rxm13_ff0 <= '0';
end if;
else
if s_rxpre_count(4 downto 0) = conv_unsigned(31,5) then
s_rxm13_ff0 <= '1';
else
s_rxm13_ff0 <= '0';
end if;
end if;
if smod_i = '1' then
if s_txpre_count(3 downto 0) = conv_unsigned(15,4) then
s_txm13_ff0 <= '1';
else
s_txm13_ff0 <= '0';
end if;
else
if s_txpre_count(4 downto 0) = conv_unsigned(31,5) then
s_txm13_ff0 <= '1';
else
s_txm13_ff0 <= '0';
end if;
end if;
if trans_i = '1' then
s_txpre_count <= conv_unsigned(0,6);
else
if s_mode=conv_unsigned(0,2) or s_mode=conv_unsigned(2,2) then
s_txpre_count <= s_txpre_count + conv_unsigned(1,1);
else
if s_tf = '1' then
s_txpre_count <= s_txpre_count + conv_unsigned(1,1);
end if;
end if;
end if;
if s_detect = '1' then
s_rxpre_count <= conv_unsigned(0,6);
else
if s_mode=conv_unsigned(0,2) or s_mode=conv_unsigned(2,2) then
s_rxpre_count <= s_rxpre_count + conv_unsigned(1,1);
else
if s_tf = '1' then
s_rxpre_count <= s_rxpre_count + conv_unsigned(1,1);
end if;
end if;
end if;
end if;
end if;
end process p_divide_clk;
-------------------------------------------------------------------------------
-- This section samples the serial input for data detection, that is a
-- 1-to-0 transition at rxd in state "0000".
-- In all other states this unit reads the data bits depending on the baud
-- rate. In mode0 this section is not active.
s_detect <= '1' when s_det_ff0 = '0' and s_det_ff1 = '1' else '0';
s_rxd_val <= '1' when (s_rxd_ff0 = '1' and s_rxd_ff1 = '1') or
(s_rxd_ff0 = '1' and s_rxd_ff2 = '1') or
(s_rxd_ff1 = '1' and s_rxd_ff2 = '1') else '0';
p_sample_rx: process (clk,
reset)
begin
if reset = '1' then
s_rxd_ff0 <= '0';
s_rxd_ff1 <= '0';
s_rxd_ff2 <= '0';
s_det_ff0 <= '0';
s_det_ff1 <= '0';
else
if clk'event and clk='1' then
if s_recv_state = conv_unsigned(0,4) then -- state "0000" means
if s_ren = '1' then -- to listen for a 1 to 0
case s_mode is -- transition
when ("01") | ("11") =>
if smod_i = '1' then
if s_tf = '1' then
s_det_ff0 <= rxd_i;
s_det_ff1 <= s_det_ff0;
end if;
else
if s_rxpre_count(0) = '1' then
s_det_ff0 <= rxd_i;
s_det_ff1 <= s_det_ff0;
end if;
end if;
when ("10") =>
if smod_i = '1' then
if s_rxpre_count(0) = '1' then
s_det_ff0 <= rxd_i;
s_det_ff1 <= s_det_ff0;
end if;
else
if s_rxpre_count(1) = '1' then
s_det_ff0 <= rxd_i;
s_det_ff1 <= s_det_ff0;
end if;
end if;
when others =>
null;
end case;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -