URL
https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk
Subversion Repositories open8_urisc
Compare Revisions
- This comparison shows the changes necessary to convert path
/open8_urisc
- from Rev 277 to Rev 278
- ↔ Reverse comparison
Rev 277 → Rev 278
/trunk/VHDL/sdlc_serial_arbfsm.vhd
File deleted
/trunk/VHDL/sdlc_serial_txfsm.vhd
File deleted
\ No newline at end of file
/trunk/VHDL/sdlc_serial_clk.vhd
File deleted
\ No newline at end of file
/trunk/VHDL/sdlc_serial_rx.vhd
File deleted
\ No newline at end of file
/trunk/VHDL/sdlc_serial_tx.vhd
File deleted
\ No newline at end of file
/trunk/VHDL/sdlc_serial_pkg.vhd
File deleted
\ No newline at end of file
/trunk/VHDL/sdlc_serial_rxfsm.vhd
File deleted
\ No newline at end of file
/trunk/VHDL/sdlc_serial_frame.vhd
File deleted
\ No newline at end of file
/trunk/VHDL/o8_sdlc_if.vhd
64,21 → 64,17
-- Revision History |
-- Author Date Change |
------------------ -------- --------------------------------------------------- |
-- Seth Henry 04/16/20 Revision block added |
-- Seth Henry 05/18/20 Added write qualification input |
-- Seth Henry 11/01/20 Updated comments regarding SDLC support |
-- Seth Henry 12/09/20 Created from merged sub-entities into flat file |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
use ieee.std_logic_arith.all; |
use ieee.std_logic_misc.all; |
|
library work; |
use work.open8_pkg.all; |
|
library work; |
use work.sdlc_serial_pkg.all; |
|
entity o8_sdlc_if is |
generic( |
Poly_Init : std_logic_vector(15 downto 0) := x"0000"; |
104,6 → 100,10
|
architecture behave of o8_sdlc_if is |
|
-- convenient subtypes & constants |
subtype CRC_TYPE is std_logic_vector(15 downto 0); |
|
-- Bus interface |
alias Clock is Open8_Bus.Clock; |
alias Reset is Open8_Bus.Reset; |
|
125,214 → 125,632
alias Reg_Lower_Addr is Open8_Bus.Address(0); |
|
signal Reg_Addr : std_logic_vector(8 downto 1) := (others => '0'); |
signal Reg_Sel : std_logic := '0'; |
signal Reg_Wr_En_d : std_logic := '0'; |
signal Reg_Wr_En_q : std_logic := '0'; |
signal Reg_Clk_Sel : std_logic := '0'; |
signal Reg_TxS_Sel : std_logic := '0'; |
signal Reg_Sel : std_logic := '0'; |
signal Reg_Wr_En_d : std_logic := '0'; |
signal Reg_Wr_En_q : std_logic := '0'; |
signal TX_Ctl_Clk : std_logic := '0'; |
signal TX_Ctl_Len : std_logic := '0'; |
|
signal DP_B_Addr : std_logic_vector(8 downto 0) := (others => '0'); |
signal DP_B_Wr_Data : DATA_IN_TYPE := x"00"; |
signal DP_B_Wr_En : std_logic := '0'; |
signal DP_B_Rd_Data : DATA_IN_TYPE := x"00"; |
-- Dual-port memory |
signal DP_Addr : std_logic_vector(8 downto 0); |
signal DP_Wr_Data : DATA_TYPE; |
signal DP_Wr_En : std_logic; |
signal DP_Rd_Data : DATA_TYPE; |
|
signal DP_Port0_Addr : DATA_IN_TYPE := x"00"; |
signal DP_Port0_RWn : std_logic := '0'; |
signal DP_Port0_WrData : DATA_IN_TYPE := x"00"; |
signal DP_Port0_RdData : DATA_IN_TYPE := x"00"; |
signal DP_Port0_Req : std_logic := '0'; |
signal DP_Port0_Ack : std_logic := '0'; |
alias DP_B_Addr is DP_Addr; |
alias DP_B_Wr_Data is DP_Wr_Data; |
alias DP_B_Wr_En is DP_Wr_En; |
alias DP_B_Rd_Data is DP_Rd_Data; |
|
signal DP_Port1_Addr : DATA_IN_TYPE := x"00"; |
signal DP_Port1_RWn : std_logic := '0'; |
signal DP_Port1_WrData : DATA_IN_TYPE := x"00"; |
signal DP_Port1_RdData : DATA_IN_TYPE := x"00"; |
signal DP_Port1_Req : std_logic := '0'; |
signal DP_Port1_Ack : std_logic := '0'; |
-- Internal definitions |
constant SDLC_Flag : DATA_TYPE := x"7E"; |
|
signal BClk_RE : std_logic := '0'; |
signal BClk_FE : std_logic := '0'; |
signal BClk_Okay : std_logic := '0'; |
constant CK_REGISTER : DATA_TYPE := x"FE"; |
constant TX_REGISTER : DATA_TYPE := x"FF"; |
constant CS_REGISTER : DATA_TYPE := x"FE"; |
constant RX_REGISTER : DATA_TYPE := x"FF"; |
|
signal TX_Wr_En : std_logic := '0'; |
signal TX_Wr_Flag : std_logic := '0'; |
signal TX_Wr_Data : DATA_IN_TYPE := x"00"; |
signal TX_Req_Next : std_logic := '0'; |
constant TX_RESERVED_LOW : integer := 0; |
constant TX_RESERVED_HIGH : integer := 254; |
|
signal TX_CRC_Clr : std_logic := '0'; |
signal TX_CRC_En : std_logic := '0'; |
signal TX_CRC_Data : CRC_OUT_TYPE := x"0000"; |
signal TX_CRC_Valid : std_logic := '0'; |
constant FLAG_DONE : DATA_TYPE := x"FF"; |
|
signal RX_Valid : std_logic := '0'; |
signal RX_Flag : std_logic := '0'; |
signal RX_Data : DATA_IN_TYPE; |
signal RX_Idle : std_logic := '0'; |
constant ERR_LENGTH : DATA_TYPE := x"00"; |
|
signal RX_Frame_Start : std_logic := '0'; |
signal RX_Frame_Stop : std_logic := '0'; |
signal RX_Frame_Valid : std_logic := '0'; |
signal RX_Frame_Data : DATA_IN_TYPE := x"00"; |
-- RAM Arbitration logic |
type DP_ARB_STATES is (PAUSE, IDLE, |
PORT0_AD, PORT0_WR, PORT0_RD0, PORT0_RD1, |
PORT1_AD, PORT1_WR, PORT1_RD0, PORT1_RD1 ); |
signal DP_Arb_State : DP_ARB_STATES := IDLE; |
signal DP_Last_Port : std_logic := '0'; |
|
signal RX_CRC_Valid : std_logic := '0'; |
signal RX_CRC_Data : CRC_OUT_TYPE := x"0000"; |
signal DP_Port0_Addr : DATA_TYPE := x"00"; |
signal DP_Port0_RWn : std_logic := '0'; |
signal DP_Port0_WrData : DATA_TYPE := x"00"; |
signal DP_Port0_RdData : DATA_TYPE := x"00"; |
signal DP_Port0_Req : std_logic := '0'; |
signal DP_Port0_Ack : std_logic := '0'; |
|
signal DP_Port1_Addr : DATA_TYPE := x"00"; |
signal DP_Port1_RWn : std_logic := '0'; |
signal DP_Port1_WrData : DATA_TYPE := x"00"; |
signal DP_Port1_RdData : DATA_TYPE := x"00"; |
signal DP_Port1_Req : std_logic := '0'; |
signal DP_Port1_Ack : std_logic := '0'; |
|
-- Clock generation |
constant DLY_VAL : integer := integer(Clock_Frequency / (2.0 * BitClock_Frequency) ); |
constant DLY_WDT : integer := ceil_log2(DLY_VAL - 1); |
constant DLY_VEC : std_logic_vector := |
conv_std_logic_vector( DLY_VAL - 1, DLY_WDT); |
signal BClk_Cntr : std_logic_vector( DLY_WDT - 1 downto 0 ) := (others => '0'); |
|
signal BClk_Adv : std_logic := '0'; |
signal BClk_Accum : std_logic_vector(31 downto 0) := (others => '0'); |
signal BClk_Div : std_logic := '0'; |
signal BClk_Okay_SR : std_logic_vector(3 downto 0) := (others => '0'); |
|
|
signal BClk_SR : std_logic_vector(2 downto 0) := (others => '0'); |
|
constant CLK_RATIO_R : real := Clock_Frequency / (1.0 * BitClock_Frequency); |
constant CLK_DEVIATION_5P : real := CLK_RATIO_R * 0.05; |
constant CLK_RATIO_ADJ_R : real := CLK_RATIO_R + CLK_DEVIATION_5P; |
constant CLK_RATIO_ADJ_I : integer := integer(CLK_RATIO_ADJ_R); |
|
constant Threshold_bits : integer := ceil_log2(CLK_RATIO_ADJ_I); |
constant THRESHOLD : std_logic_vector(Threshold_bits - 1 downto 0) := |
conv_std_logic_vector(CLK_RATIO_ADJ_I,Threshold_bits); |
|
signal RE_Threshold_Ctr : std_logic_vector(Threshold_Bits - 1 downto 0) := |
(others => '0'); |
signal FE_Threshold_Ctr : std_logic_vector(Threshold_Bits - 1 downto 0) := |
(others => '0'); |
|
signal Ref_In_SR : std_logic_vector(2 downto 0) := (others => '0'); |
alias Ref_In_q1 is Ref_In_SR(1); |
alias Ref_In_q2 is Ref_In_SR(2); |
signal Ref_In_RE : std_logic := '0'; |
signal Ref_In_FE : std_logic := '0'; |
|
signal BClk_RE : std_logic := '0'; |
signal BClk_FE : std_logic := '0'; |
signal BClk_Okay : std_logic := '0'; |
|
-- Packet Transmit state logic |
type TX_FSM_STATES is ( INIT_FLAG, |
WR_CLOCK_STATE, WAIT_FOR_CLOCK, |
WAIT_FOR_UPDATE, |
RD_TX_REGISTER, TX_INIT, |
TX_START_FLAG, TX_WAIT_START_FLAG, |
TX_MESG_DATA, TX_ADV_ADDR, TX_WAIT_MESG_DATA, |
TX_CRC_LB_WR, TX_CRC_LB_WAIT, |
TX_CRC_UB_WR, TX_CRC_UB_WAIT, |
TX_STOP_FLAG, TX_WAIT_STOP_FLAG, TX_SET_FLAG ); |
|
signal TX_FSM_State : TX_FSM_STATES := WR_CLOCK_STATE; |
signal TX_Length : DATA_TYPE := x"00"; |
|
signal BClk_q1, BClk_CoS : std_logic := '0'; |
signal TX_Int_pend : std_logic := '0'; |
|
signal TX_Wr_En : std_logic := '0'; |
signal TX_Wr_Flag : std_logic := '0'; |
signal TX_Wr_Data : DATA_TYPE := x"00"; |
signal TX_Req_Next : std_logic := '0'; |
|
signal TX_CRC_Clr : std_logic := '0'; |
signal TX_CRC_En : std_logic := '0'; |
signal TX_CRC_Data : CRC_TYPE := x"0000"; |
signal TX_CRC_Valid : std_logic := '0'; |
|
alias TX_CRC_Data_LB is TX_CRC_Data(7 downto 0); |
alias TX_CRC_Data_UB is TX_CRC_Data(15 downto 8); |
|
signal TX_Arm : std_logic := '0'; |
signal TX_Flag : std_logic := '0'; |
signal TX_Buffer : std_logic_vector(8 downto 0) := (others => '0'); |
alias TX_Buffer_Flag is TX_Buffer(8); |
alias TX_Buffer_Data is TX_Buffer(7 downto 0); |
|
-- SDLC transmitter |
type TX_STATES is (INIT, IDLE, XMIT, SPACE, TERM, LD_NEXT); |
signal TX_State : TX_STATES := INIT; |
|
signal TX_ShftReg : DATA_TYPE := (others => '0'); |
signal TX_Next : std_logic := '0'; |
signal TX_BitStuff : std_logic_vector(4 downto 0) := (others => '0'); |
signal TX_BitCntr : std_logic_vector(3 downto 0) := (others => '0'); |
alias TX_BitSel is TX_BitCntr(2 downto 0); |
alias TX_Term is TX_BitCntr(3); |
|
-- SDLC receiver |
signal RX_LatchEn_SR : std_logic_vector(Clock_Offset downto 0) := (others => '0'); |
alias RX_LatchEn_M is RX_LatchEn_SR(Clock_Offset); |
alias RX_LatchEn_S is BClk_RE; |
signal RX_LatchEn : std_logic := '0'; |
|
signal RX_Serial_SR : std_logic_vector(1 downto 0) := (others => '0'); |
alias RX_Serial is RX_Serial_SR(1); |
|
type RX_STATES is (INIT, IDLE, RCV_DATA, SKIP_ZERO, WRITE_DATA); |
signal RX_State : RX_STATES := INIT; |
signal RX_Buffer : DATA_TYPE := x"00"; |
signal RX_BitStuff_SR : std_logic_vector(4 downto 0) := (others => '0'); |
signal RX_BitCntr : std_logic_vector(3 downto 0) := (others => '0'); |
alias RX_BitSel is RX_BitCntr(2 downto 0); |
alias RX_Term is RX_BitCntr(3); |
|
signal RX_Flag_SR : DATA_TYPE := x"00"; |
|
signal RX_Idle_Cntr : std_logic_vector(2 downto 0) := (others => '0'); |
|
signal RX_Valid : std_logic := '0'; |
signal RX_Flag : std_logic := '0'; |
signal RX_Data : DATA_TYPE := x"00"; |
signal RX_Idle : std_logic := '0'; |
|
-- Packet detection logic |
type PACKET_STATES is (IDLE, FRAME_START, FRAME_DATA, FRAME_STOP ); |
signal Pkt_State : PACKET_STATES := IDLE; |
signal First_Byte : std_logic := '0'; |
|
signal RX_Frame_Start : std_logic := '0'; |
signal RX_Frame_Stop : std_logic := '0'; |
signal RX_Frame_Valid : std_logic := '0'; |
signal RX_Frame_Data : DATA_TYPE := x"00"; |
|
-- Receive data CRC calculation |
signal RX_CRC_Valid : std_logic := '0'; |
signal RX_CRC_Data : CRC_TYPE := x"0000"; |
|
type CRC_HISTORY is array(0 to 2) of CRC_TYPE; |
signal RX_CRC_Hist : CRC_HISTORY := (x"0000",x"0000",x"0000"); |
alias RX_CRC_Calc is RX_CRC_Hist(2); |
|
signal RX_CRC_Rcvd : CRC_TYPE := x"0000"; |
alias RX_CRC_Rcvd_LB is RX_CRC_Rcvd(7 downto 0); |
alias RX_CRC_Rcvd_UB is RX_CRC_Rcvd(15 downto 8); |
|
-- Packet receive state logic |
type RX_FSM_STATES is ( WAIT_FOR_CLOCK, WAIT_FOR_FLAG, |
RX_MESG_DATA, RX_WR_DATA, |
RX_CRC_LB_RD, RX_CRC_UB_RD, |
RX_WR_CRC, RX_WR_COUNT ); |
|
signal RX_FSM_State : RX_FSM_STATES := WAIT_FOR_CLOCK; |
|
signal RX_Length : DATA_TYPE := x"00"; |
|
begin |
|
|
-- *************************************************************************** |
-- * Open8 Bus Interface and Control Register Detection * |
-- *************************************************************************** |
|
-- This decode needs to happen immediately, to give the RAM a chance to |
-- do the lookup before we have to set Rd_Data |
Base_Addr_Match <= '1' when Base_Addr = CPU_Upper_Addr else '0'; |
Reg_Wr_En_d <= Base_Addr_Match and |
Open8_Bus.Wr_En and |
Write_Qual; |
|
DP_A_Wr_En <= Base_Addr_Match and |
Open8_Bus.Wr_En and |
Write_Qual; |
|
DP_A_Rd_En_d <= Base_Addr_Match and Open8_Bus.Rd_En; |
|
CPU_IF_proc: process( Reset, Clock ) |
begin |
if( Reset = Reset_Level )then |
Reg_Addr <= (others => '0'); |
Reg_Wr_En_q <= '0'; |
TX_Ctl_Clk <= '0'; |
TX_Ctl_Len <= '0'; |
DP_A_Rd_En_q <= '0'; |
Rd_Data <= OPEN8_NULLBUS; |
elsif( rising_edge(Clock) )then |
Reg_Addr <= Reg_Upper_Addr; |
Reg_Sel <= Reg_Lower_Addr; |
Reg_Wr_En_q <= Reg_Wr_En_d; |
|
TX_Ctl_Clk <= '0'; |
TX_Ctl_Len <= '0'; |
if( Reg_Addr = Reg_Sub_Addr )then |
TX_Ctl_Clk <= Reg_Wr_En_q and not Reg_Sel; |
TX_Ctl_Len <= Reg_Wr_En_q and Reg_Sel; |
end if; |
|
DP_A_Rd_En_q <= DP_A_Rd_En_d; |
Rd_Data <= OPEN8_NULLBUS; |
if( DP_A_Rd_En_q = '1' )then |
Rd_Data <= DP_A_Rd_Data; |
end if; |
end if; |
end process; |
|
-- *************************************************************************** |
-- * Shared Dual-Port Memory * |
-- *************************************************************************** |
|
U_RAM : entity work.sdlc_dp512b_ram |
port map( |
clock => Clock, |
address_a => DP_A_Addr, |
address_b => DP_B_Addr, |
data_a => DP_A_Wr_Data, |
data_b => DP_B_Wr_Data, |
wren_a => DP_A_Wr_En, |
wren_b => DP_B_Wr_En, |
q_a => DP_A_Rd_Data, |
q_b => DP_B_Rd_Data |
); |
|
-- *************************************************************************** |
-- * Open8 Bus Interface and Control Register Detection * |
-- * Memory Arbitration * |
-- *************************************************************************** |
|
-- This decode needs to happen immediately, to give the RAM a chance to |
-- do the lookup before we have to set Rd_Data |
Base_Addr_Match <= '1' when Base_Addr = CPU_Upper_Addr else '0'; |
Reg_Wr_En_d <= Base_Addr_Match and |
Open8_Bus.Wr_En and |
Write_Qual; |
RAM_Arbitration_proc: process( Clock, Reset ) |
begin |
if( Reset = Reset_Level )then |
DP_Arb_State <= IDLE; |
DP_Last_Port <= '0'; |
DP_Addr <= (others => '0'); |
DP_Wr_Data <= x"00"; |
DP_Wr_En <= '0'; |
DP_Port0_RdData <= x"00"; |
DP_Port0_Ack <= '0'; |
DP_Port1_RdData <= x"00"; |
DP_Port1_Ack <= '0'; |
elsif( rising_edge(Clock) )then |
DP_Port0_Ack <= '0'; |
DP_Port1_Ack <= '0'; |
DP_Wr_En <= '0'; |
|
DP_A_Wr_En <= Base_Addr_Match and |
Open8_Bus.Wr_En and |
Write_Qual; |
case( DP_Arb_State )is |
when IDLE => |
if( DP_Port0_Req = '1' and (DP_Port1_Req = '0' or DP_Last_Port = '1') )then |
DP_Arb_State <= PORT0_AD; |
elsif( DP_Port1_Req = '1' and (DP_Port0_Req = '0' or DP_Last_Port = '0') )then |
DP_Arb_State <= PORT1_AD; |
end if; |
|
DP_A_Rd_En_d <= Base_Addr_Match and Open8_Bus.Rd_En; |
when PORT0_AD => |
DP_Last_Port <= '0'; |
DP_Addr <= '0' & DP_Port0_Addr; |
DP_Wr_Data <= DP_Port0_WrData; |
DP_Wr_En <= not DP_Port0_RWn; |
if( DP_Port0_RWn = '1' )then |
DP_Arb_State <= PORT0_RD0; |
else |
DP_Port0_Ack <= '1'; |
DP_Arb_State <= PORT0_WR; |
end if; |
|
CPU_IF_proc: process( Reset, Clock ) |
when PORT0_WR => |
DP_Arb_State <= IDLE; |
|
when PORT0_RD0 => |
DP_Arb_State <= PORT0_RD1; |
|
when PORT0_RD1 => |
DP_Port0_Ack <= '1'; |
DP_Port0_RdData <= DP_Rd_Data; |
DP_Arb_State <= PAUSE; |
|
when PORT1_AD => |
DP_Last_Port <= '1'; |
DP_Addr <= '1' & DP_Port1_Addr; |
DP_Wr_Data <= DP_Port1_WrData; |
DP_Wr_En <= not DP_Port1_RWn; |
if( DP_Port0_RWn = '1' )then |
DP_Arb_State <= PORT1_RD0; |
else |
DP_Port1_Ack <= '1'; |
DP_Arb_State <= PORT1_WR; |
end if; |
|
when PORT1_WR => |
DP_Arb_State <= IDLE; |
|
when PORT1_RD0 => |
DP_Arb_State <= PORT1_RD1; |
|
when PORT1_RD1 => |
DP_Port1_Ack <= '1'; |
DP_Port1_RdData <= DP_Rd_Data; |
DP_Arb_State <= PAUSE; |
|
when PAUSE => |
DP_Arb_State <= IDLE; |
|
when others => null; |
|
end case; |
end if; |
end process; |
|
-- **************************************************************************** |
-- * Bit clock generation * |
-- **************************************************************************** |
|
Clock_Master: if( Set_As_Master )generate |
|
Clock_Gen_proc: process( Clock, Reset ) |
begin |
if( Reset = Reset_Level )then |
Reg_Addr <= (others => '0'); |
Reg_Wr_En_q <= '0'; |
Reg_Clk_Sel <= '0'; |
Reg_TxS_Sel <= '0'; |
DP_A_Rd_En_q <= '0'; |
Rd_Data <= OPEN8_NULLBUS; |
BClk_Cntr <= DLY_VEC; |
BClk_Adv <= '0'; |
BClk_Accum <= (others => '0'); |
BClk_Div <= '0'; |
BClk_Okay_SR <= (others => '0'); |
BClk_RE <= '0'; |
BClk_FE <= '0'; |
SDLC_MClk <= '0'; |
elsif( rising_edge( Clock ) )then |
BClk_Cntr <= BClk_Cntr - 1; |
BClk_Adv <= '0'; |
if( or_reduce(BClk_Cntr) = '0' )then |
BClk_Cntr <= DLY_VEC; |
BClk_Adv <= '1'; |
BClk_Okay_SR <= BClk_Okay_SR(2 downto 0) & '1'; |
end if; |
BClk_Accum <= BClk_Accum + BClk_Adv; |
BClk_Div <= BClk_Div xor BClk_Adv; |
BClk_RE <= (not BClk_Div) and BClk_Adv; |
BClk_FE <= BClk_Div and BClk_Adv; |
SDLC_MClk <= BClk_Div; |
end if; |
end process; |
|
BClk_Okay <= BClk_Okay_SR(3); |
|
end generate; |
|
Clock_Slave: if( not Set_As_Master )generate |
|
Clock_Edge_proc: process( Clock, Reset ) |
begin |
if( Reset = Reset_Level )then |
BClk_SR <= (others => '0'); |
BClk_FE <= '0'; |
BClk_RE <= '0'; |
elsif( rising_edge(Clock) )then |
Reg_Addr <= Reg_Upper_Addr; |
Reg_Sel <= Reg_Lower_Addr; |
Reg_Wr_En_q <= Reg_Wr_En_d; |
BClk_SR <= BClk_SR(1 downto 0) & SDLC_SClk; |
BClk_FE <= BClk_SR(2) and (not BClk_SR(1)); |
BClk_RE <= (not BClk_SR(2)) and BClk_SR(1); |
end if; |
end process; |
|
Reg_Clk_Sel <= '0'; |
Reg_TxS_Sel <= '0'; |
if( Reg_Addr = Reg_Sub_Addr )then |
Reg_Clk_Sel <= Reg_Wr_En_q and not Reg_Sel; |
Reg_TxS_Sel <= Reg_Wr_En_q and Reg_Sel; |
SDLC_MClk <= '0'; |
|
Clock_Detect_proc: process( Clock, Reset ) |
begin |
if( Reset = Reset_Level )then |
Ref_In_SR <= (others => '0'); |
Ref_In_RE <= '0'; |
Ref_In_FE <= '0'; |
RE_Threshold_Ctr <= (others => '0'); |
FE_Threshold_Ctr <= (others => '0'); |
BClk_Okay <= '0'; |
|
elsif( rising_edge(Clock) )then |
Ref_In_SR <= Ref_In_SR(1 downto 0) & SDLC_SClk; |
Ref_In_RE <= Ref_In_q1 and (not Ref_In_q2); |
Ref_In_FE <= (not Ref_In_q1) and Ref_In_q2; |
|
RE_Threshold_Ctr <= RE_Threshold_Ctr - 1; |
if( Ref_In_RE = '1' )then |
RE_Threshold_Ctr <= THRESHOLD; |
elsif( or_reduce(RE_Threshold_Ctr) = '0' )then |
RE_Threshold_Ctr <= (others => '0'); |
end if; |
|
DP_A_Rd_En_q <= DP_A_Rd_En_d; |
Rd_Data <= OPEN8_NULLBUS; |
if( DP_A_Rd_En_q = '1' )then |
Rd_Data <= DP_A_Rd_Data; |
FE_Threshold_Ctr <= FE_Threshold_Ctr - 1; |
if( Ref_In_FE = '1' )then |
FE_Threshold_Ctr <= THRESHOLD; |
elsif( or_reduce(FE_Threshold_Ctr) = '0' )then |
FE_Threshold_Ctr <= (others => '0'); |
end if; |
|
|
BClk_Okay <= or_reduce(RE_Threshold_Ctr) and |
or_reduce(FE_Threshold_Ctr); |
|
end if; |
end process; |
|
end generate; |
|
-- *************************************************************************** |
-- * Shared Dual-Port Memory * |
-- * Serial Transmit Path * |
-- *************************************************************************** |
|
U_RAM : entity work.sdlc_dp512b_ram |
port map( |
clock => Clock, |
address_a => DP_A_Addr, |
address_b => DP_B_Addr, |
data_a => DP_A_Wr_Data, |
data_b => DP_B_Wr_Data, |
wren_a => DP_A_Wr_En, |
wren_b => DP_B_Wr_En, |
q_a => DP_A_Rd_Data, |
q_b => DP_B_Rd_Data |
); |
TX_Packet_RAM_proc: process( Reset, Clock ) |
begin |
if( Reset = Reset_Level )then |
TX_FSM_State <= INIT_FLAG; |
|
-- *************************************************************************** |
-- * Memory Arbitration * |
-- *************************************************************************** |
DP_Port0_Addr <= x"00"; |
DP_Port0_RWn <= '1'; |
DP_Port0_WrData <= x"00"; |
DP_Port0_Req <= '0'; |
|
U_ARB : entity work.sdlc_serial_arbfsm |
generic map( |
Reset_Level => Reset_Level |
) |
port map( |
Clock => Clock, |
Reset => Reset, |
-- |
DP_Addr => DP_B_Addr, |
DP_Wr_Data => DP_B_Wr_Data, |
DP_Wr_En => DP_B_Wr_En, |
DP_Rd_Data => DP_B_Rd_Data, |
-- |
DP_Port0_Addr => DP_Port0_Addr, |
DP_Port0_RWn => DP_Port0_RWn, |
DP_Port0_WrData => DP_Port0_WrData, |
DP_Port0_RdData => DP_Port0_RdData, |
DP_Port0_Req => DP_Port0_Req, |
DP_Port0_Ack => DP_Port0_Ack, |
-- |
DP_Port1_Addr => DP_Port1_Addr, |
DP_Port1_RWn => DP_Port1_RWn, |
DP_Port1_WrData => DP_Port1_WrData, |
DP_Port1_RdData => DP_Port1_RdData, |
DP_Port1_Req => DP_Port1_Req, |
DP_Port1_Ack => DP_Port1_Ack |
); |
TX_Length <= x"00"; |
|
-- *************************************************************************** |
-- * Serial BitClock * |
-- *************************************************************************** |
TX_Wr_En <= '0'; |
TX_Wr_Flag <= '0'; |
TX_Wr_Data <= x"00"; |
|
U_BCLK : entity work.sdlc_serial_clk |
generic map( |
Set_As_Master => Set_As_Master, |
BitClock_Freq => BitClock_Frequency, |
Reset_Level => Reset_Level, |
Sys_Freq => Clock_Frequency |
) |
port map( |
Clock => Clock, |
Reset => Reset, |
-- |
BClk_In => SDLC_SClk, |
BClk_Out => SDLC_MClk, |
BClk_FE => BClk_FE, |
BClk_RE => BClk_RE, |
BClk_Okay => BClk_Okay |
); |
TX_CRC_Clr <= '0'; |
TX_CRC_En <= '0'; |
|
-- *************************************************************************** |
-- * Serial Transmit Path * |
-- *************************************************************************** |
BClk_q1 <= '0'; |
BClk_CoS <= '0'; |
|
U_TXFSM: entity work.sdlc_serial_txfsm |
generic map( |
Reset_Level => Reset_Level |
) |
port map( |
Clock => Clock, |
Reset => Reset, |
-- |
BClk_Okay => BClk_Okay, |
-- |
Reg_Clk_Sel => Reg_Clk_Sel, |
Reg_TxS_Sel => Reg_TxS_Sel, |
-- |
DP_Port0_Addr => DP_Port0_Addr, |
DP_Port0_RWn => DP_Port0_RWn, |
DP_Port0_WrData => DP_Port0_WrData, |
DP_Port0_RdData => DP_Port0_RdData, |
DP_Port0_Req => DP_Port0_Req, |
DP_Port0_Ack => DP_Port0_Ack, |
-- |
TX_Wr_En => TX_Wr_En, |
TX_Wr_Flag => TX_Wr_Flag, |
TX_Wr_Data => TX_Wr_Data, |
TX_Req_Next => TX_Req_Next, |
-- |
TX_CRC_Clr => TX_CRC_Clr, |
TX_CRC_En => TX_CRC_En, |
TX_CRC_Data => TX_CRC_Data, |
TX_CRC_Valid => TX_CRC_Valid, |
-- |
TX_Interrupt => TX_Interrupt |
); |
TX_Int_pend <= '0'; |
TX_Interrupt <= '0'; |
|
elsif( rising_edge(Clock) )then |
|
DP_Port0_RWn <= '1'; |
DP_Port0_WrData <= x"00"; |
DP_Port0_Req <= '0'; |
|
TX_Wr_En <= '0'; |
TX_Wr_Flag <= '0'; |
TX_Wr_Data <= x"00"; |
|
TX_CRC_Clr <= '0'; |
TX_CRC_En <= '0'; |
|
BClk_q1 <= BClk_Okay; |
BClk_CoS <= BClk_q1 xor BClk_Okay; |
|
TX_Interrupt <= '0'; |
|
case( TX_FSM_State )is |
|
when INIT_FLAG => |
DP_Port0_Addr <= TX_REGISTER; |
DP_Port0_Req <= '1'; |
DP_Port0_WrData <= FLAG_DONE; |
DP_Port0_RWn <= '0'; |
if( DP_Port0_Ack = '1' )then |
DP_Port0_Req <= '0'; |
TX_FSM_State <= WR_CLOCK_STATE; |
end if; |
|
when WAIT_FOR_UPDATE => |
if( TX_Ctl_Clk = '1' )then |
TX_FSM_State <= WR_CLOCK_STATE; |
end if; |
if( TX_Ctl_Len = '1' )then |
TX_FSM_State <= RD_TX_REGISTER; |
end if; |
|
when WR_CLOCK_STATE => |
DP_Port0_Addr <= CK_REGISTER; |
DP_Port0_Req <= '1'; |
DP_Port0_WrData <= (others => BClk_Okay); |
DP_Port0_RWn <= '0'; |
if( DP_Port0_Ack = '1' )then |
TX_Interrupt <= TX_Int_pend; |
TX_Int_pend <= '0'; |
DP_Port0_Req <= '0'; |
TX_FSM_State <= WAIT_FOR_CLOCK; |
end if; |
|
when WAIT_FOR_CLOCK => |
if( BClk_Okay = '1' )then |
TX_FSM_State <= WAIT_FOR_UPDATE; |
end if; |
|
when RD_TX_REGISTER => |
DP_Port0_Addr <= TX_REGISTER; |
DP_Port0_Req <= '1'; |
if( DP_Port0_Ack = '1' )then |
DP_Port0_Req <= '0'; |
TX_Length <= DP_Port0_RdData; |
TX_FSM_State <= TX_INIT; |
end if; |
|
when TX_INIT => |
TX_FSM_State <= WAIT_FOR_UPDATE; |
if( TX_Length > TX_RESERVED_LOW and |
TX_Length < TX_RESERVED_HIGH )then |
TX_CRC_Clr <= '1'; |
TX_FSM_State <= TX_START_FLAG; |
end if; |
|
when TX_START_FLAG => |
TX_Wr_En <= '1'; |
TX_Wr_Flag <= '1'; |
TX_Wr_Data <= SDLC_FLAG; |
TX_FSM_State <= TX_WAIT_START_FLAG; |
|
when TX_WAIT_START_FLAG => |
if( TX_Req_Next = '1' )then |
DP_Port0_Addr <= x"00"; |
TX_FSM_State <= TX_ADV_ADDR; |
end if; |
|
when TX_ADV_ADDR => |
DP_Port0_Req <= '1'; |
if( DP_Port0_Ack = '1' )then |
DP_Port0_Req <= '0'; |
DP_Port0_Addr <= DP_Port0_Addr + 1; |
TX_Length <= TX_Length - 1; |
TX_FSM_State <= TX_MESG_DATA; |
end if; |
|
when TX_MESG_DATA => |
TX_Wr_En <= '1'; |
TX_Wr_Data <= DP_Port0_RdData; |
TX_CRC_En <= '1'; |
TX_FSM_State <= TX_WAIT_MESG_DATA; |
|
when TX_WAIT_MESG_DATA => |
if( TX_Req_Next = '1' )then |
TX_FSM_State <= TX_ADV_ADDR; |
if( TX_Length = 0 )then |
TX_FSM_State <= TX_CRC_LB_WR; |
end if; |
end if; |
|
when TX_CRC_LB_WR => |
TX_Wr_En <= '1'; |
TX_Wr_Data <= TX_CRC_Data_LB; |
TX_FSM_State <= TX_CRC_LB_WAIT; |
|
when TX_CRC_LB_WAIT => |
if( TX_Req_Next = '1' )then |
TX_FSM_State <= TX_CRC_UB_WR; |
end if; |
|
when TX_CRC_UB_WR => |
TX_Wr_En <= '1'; |
TX_Wr_Data <= TX_CRC_Data_UB; |
TX_FSM_State <= TX_CRC_UB_WAIT; |
|
when TX_CRC_UB_WAIT => |
if( TX_Req_Next = '1' )then |
TX_FSM_State <= TX_STOP_FLAG; |
end if; |
|
when TX_STOP_FLAG => |
TX_Wr_En <= '1'; |
TX_Wr_Flag <= '1'; |
TX_Wr_Data <= SDLC_FLAG; |
TX_FSM_State <= TX_WAIT_STOP_FLAG; |
|
when TX_WAIT_STOP_FLAG => |
if( TX_Req_Next = '1' )then |
TX_FSM_State <= TX_SET_FLAG; |
end if; |
|
when TX_SET_FLAG => |
DP_Port0_Addr <= TX_REGISTER; |
DP_Port0_Req <= '1'; |
DP_Port0_WrData <= FLAG_DONE; |
DP_Port0_RWn <= '0'; |
if( DP_Port0_Ack = '1' )then |
DP_Port0_Req <= '0'; |
TX_FSM_State <= WAIT_FOR_UPDATE; |
end if; |
|
when others => null; |
end case; |
|
if( BClk_CoS = '1' )then |
TX_Int_pend <= '1'; |
TX_FSM_State <= WR_CLOCK_STATE; |
end if; |
|
end if; |
end process; |
|
U_TX_CRC : entity work.sdlc_crc16_ccitt |
generic map( |
Poly_Init => Poly_Init, |
350,70 → 768,293
CRC16_Out => TX_CRC_Data |
); |
|
U_TX_SER : entity work.sdlc_serial_tx |
generic map( |
Reset_Level => Reset_Level |
) |
port map( |
Clock => Clock, |
Reset => Reset, |
-- |
BClk_FE => BClk_FE, |
BClk_RE => BClk_RE, |
BClk_Okay => BClk_Okay, |
-- |
TX_En => TX_Wr_En, |
TX_FSS_Flag => TX_Wr_Flag, |
TX_Data => TX_Wr_Data, |
TX_Req_Next => TX_Req_Next, |
-- |
Serial_Out => SDLC_Out |
); |
TX_Serial_proc: process( Clock, Reset ) |
begin |
if( Reset = Reset_Level )then |
TX_State <= IDLE; |
SDLC_Out <= '1'; |
TX_Arm <= '0'; |
TX_Buffer <= (others => '0'); |
TX_Flag <= '0'; |
TX_ShftReg <= (others => '0'); |
TX_BitStuff <= (others => '0'); |
TX_BitCntr <= (others => '1'); |
TX_Req_Next <= '0'; |
elsif( rising_edge(Clock) )then |
|
if( TX_Wr_En = '1' and TX_Arm = '0')then |
TX_Arm <= '1'; |
TX_Buffer_Flag <= TX_Wr_Flag; |
TX_Buffer_Data <= TX_Wr_Data; |
end if; |
|
TX_Req_Next <= '0'; |
|
case( TX_State )is |
when INIT => |
SDLC_Out <= '1'; |
TX_State <= IDLE; |
|
when IDLE => |
SDLC_Out <= '1'; |
if( TX_Arm = '1' and BClk_FE = '1' )then |
TX_Arm <= '0'; |
TX_BitCntr <= (others => '0'); |
TX_BitStuff <= (others => '0'); |
TX_Flag <= TX_Buffer_Flag; |
TX_ShftReg <= TX_Buffer_Data; |
TX_Req_Next <= '1'; |
TX_State <= XMIT; |
end if; |
|
when XMIT => |
SDLC_Out <= TX_ShftReg(conv_integer(TX_BitSel)); |
TX_BitCntr <= TX_BitCntr + BClk_FE; |
if( BClk_RE = '1' )then |
TX_BitStuff <= TX_BitStuff(3 downto 0) & |
TX_ShftReg(conv_integer(TX_BitSel)); |
end if; |
if( BClk_FE = '1' )then |
if( TX_BitCntr >= 7 )then |
TX_State <= TERM; |
elsif( and_reduce(TX_BitStuff) = '1' and TX_Flag = '0' )then |
TX_BitStuff <= (others => '0'); |
TX_State <= SPACE; |
else |
TX_BitCntr <= TX_BitCntr + 1; |
end if; |
end if; |
|
when SPACE => |
SDLC_Out <= '0'; |
if( BClk_FE = '1' )then |
TX_State <= XMIT; |
end if; |
|
when TERM => |
if( TX_Arm = '1' )then |
TX_State <= LD_NEXT; |
else |
TX_State <= IDLE; |
end if; |
|
when LD_NEXT => |
TX_Arm <= '0'; |
TX_BitCntr <= (others => '0'); |
TX_Flag <= TX_Buffer_Flag; |
TX_ShftReg <= TX_Buffer_Data; |
TX_Req_Next <= '1'; |
TX_State <= XMIT; |
if( and_reduce(TX_BitStuff) = '1' and TX_Flag = '0' )then |
TX_BitStuff <= (others => '0'); |
TX_State <= SPACE; |
end if; |
|
when others => null; |
end case; |
|
if( BClk_Okay = '0' )then |
TX_State <= INIT; |
end if; |
|
end if; |
end process; |
|
-- *************************************************************************** |
-- * Serial Receive Path * |
-- *************************************************************************** |
|
U_RX_SER : entity work.sdlc_serial_rx |
generic map( |
Set_As_Master => Set_As_Master, |
Clock_Offset => Clock_Offset, |
Reset_Level => Reset_Level |
) |
port map( |
Clock => Clock, |
Reset => Reset, |
-- |
BClk_RE => BClk_RE, |
BClk_Okay => BClk_Okay, |
-- |
Serial_In => SDLC_In, |
-- |
RX_Valid => RX_Valid, |
RX_Flag => RX_Flag, |
RX_Data => RX_Data, |
RX_Idle => RX_Idle |
); |
IF_Is_Master: if( Set_As_Master )generate |
|
U_RX_PKT : entity work.sdlc_serial_frame |
generic map( |
Reset_Level => Reset_Level |
) |
port map( |
Clock => Clock, |
Reset => Reset, |
-- |
RX_Valid => RX_Valid, |
RX_Flag => RX_Flag, |
RX_Data => RX_Data, |
RX_Idle => RX_Idle, |
-- |
RX_Frame_Start => RX_Frame_Start, |
RX_Frame_Stop => RX_Frame_Stop, |
RX_Frame_Valid => RX_Frame_Valid, |
RX_Frame_Data => RX_Frame_Data |
); |
Input_proc: process( Clock, Reset ) |
begin |
if( Reset = Reset_Level )then |
RX_LatchEn_SR <= (others => '0'); |
RX_Serial_SR <= (others => '0'); |
elsif( rising_edge(Clock) )then |
RX_LatchEn_SR <= RX_LatchEn_SR(Clock_Offset - 1 downto 0) & BClk_RE; |
RX_Serial_SR <= RX_Serial_SR(0) & SDLC_In; |
end if; |
end process; |
|
RX_LatchEn <= RX_LatchEn_M; |
|
end generate; |
|
IF_Is_Slave: if( not Set_As_Master )generate |
|
Input_proc: process( Clock, Reset ) |
begin |
if( Reset = Reset_Level )then |
RX_Serial_SR <= (others => '0'); |
elsif( rising_edge(Clock) )then |
RX_Serial_SR <= RX_Serial_SR(0) & SDLC_In; |
end if; |
end process; |
|
RX_LatchEn <= RX_LatchEn_S; |
|
end generate; |
|
RX_Serial_proc: process( Clock, Reset ) |
begin |
if( Reset = Reset_Level )then |
|
RX_BitStuff_SR <= (others => '0'); |
RX_Flag_SR <= (others => '0'); |
RX_Idle_Cntr <= (others => '0'); |
|
RX_State <= IDLE; |
RX_Idle <= '0'; |
|
RX_Buffer <= (others => '0'); |
RX_BitCntr <= (others => '0'); |
|
RX_Valid <= '0'; |
RX_Flag <= '0'; |
RX_Data <= (others => '0'); |
|
elsif( rising_edge(Clock) )then |
|
if( RX_LatchEn = '1' )then |
RX_Flag_SR <= RX_Flag_SR(6 downto 0) & RX_Serial; |
if( RX_State = IDLE )then |
RX_Flag_SR <= (others => '0'); |
end if; |
|
RX_Idle_Cntr <= RX_Idle_Cntr + RX_Serial; |
if( and_reduce(RX_Idle_Cntr) = '1' )then |
RX_Idle_Cntr <= "111"; |
end if; |
end if; |
|
if( RX_Serial = '0' )then |
RX_Idle_Cntr <= (others => '0'); |
end if; |
|
RX_Valid <= '0'; |
RX_Flag <= '0'; |
RX_Idle <= '0'; |
|
case( RX_State )is |
|
when INIT => |
RX_Idle <= '1'; |
RX_State <= IDLE; |
|
when IDLE => |
RX_Idle <= '1'; |
RX_BitCntr <= (others => '0'); |
RX_BitStuff_SR <= (others => '0'); |
if( RX_Serial = '0' )then |
RX_State <= RCV_DATA; |
end if; |
|
when RCV_DATA => |
if( RX_Term = '1' )then |
RX_State <= WRITE_DATA; |
end if; |
if( RX_LatchEn = '1' )then |
RX_Buffer(conv_integer(RX_BitSel)) <= RX_Serial; |
RX_BitStuff_SR <= RX_BitStuff_SR(3 downto 0) & RX_Serial; |
RX_BitCntr <= RX_BitCntr + 1; |
|
if( and_reduce(RX_BitStuff_SR) = '1' )then |
RX_BitStuff_SR <= (others => '0'); |
if( RX_Serial = '0' )then |
RX_BitCntr <= RX_BitCntr; |
RX_State <= SKIP_ZERO; |
end if; |
end if; |
end if; |
|
when SKIP_ZERO => |
RX_State <= RCV_DATA; |
|
when WRITE_DATA => |
RX_BitCntr <= (others => '0'); |
RX_Valid <= '1'; |
RX_Data <= RX_Buffer; |
if( RX_Flag_SR = SDLC_Flag )then |
RX_Flag <= '1'; |
end if; |
RX_State <= RCV_DATA; |
|
when others => null; |
end case; |
|
-- If we just shifted in the flag character, and the bit counter isn't |
-- 0x0, then our bit counter is out of alignment. Reset it to zero so |
-- that the next word is clocked in correctly. |
if( RX_Flag_SR = SDLC_Flag and RX_BitCntr > 0 )then |
RX_BitCntr <= (others => '0'); |
end if; |
|
-- If the serial line goes idle (In the marking state for more than 7 |
-- bit times), and the FSM isn't already in IDLE, force it to IDLE. |
if( and_reduce(RX_Idle_Cntr) = '1' and RX_State /= IDLE )then |
RX_State <= IDLE; |
end if; |
|
-- If the bit clock is no longer valid, soft-reset to the INIT state. |
if( BClk_Okay = '0' )then |
RX_State <= INIT; |
end if; |
|
end if; |
end process; |
|
Packet_Marker_proc: process( Clock, Reset ) |
begin |
if( Reset = Reset_Level )then |
Pkt_State <= IDLE; |
First_Byte <= '0'; |
RX_Frame_Start <= '0'; |
RX_Frame_Stop <= '0'; |
RX_Frame_Valid <= '0'; |
RX_Frame_Data <= x"00"; |
elsif( rising_edge(Clock) )then |
RX_Frame_Start <= '0'; |
RX_Frame_Stop <= '0'; |
RX_Frame_Valid <= '0'; |
|
case( Pkt_State )is |
when IDLE => |
if( RX_Valid = '1' and RX_Flag = '1' )then |
Pkt_State <= FRAME_START; |
end if; |
|
when FRAME_START => |
if( RX_Valid = '1' and RX_Flag = '0' )then |
RX_Frame_Start <= '1'; |
First_Byte <= '1'; |
Pkt_State <= FRAME_DATA; |
end if; |
|
when FRAME_DATA => |
First_Byte <= '0'; |
if( (RX_Valid = '1' and RX_Flag = '0') or |
First_Byte = '1' )then |
RX_Frame_Valid <= '1'; |
RX_Frame_Data <= RX_Data; |
elsif( RX_Valid = '1' and RX_Flag = '1' )then |
Pkt_State <= FRAME_STOP; |
end if; |
|
when FRAME_STOP => |
RX_Frame_Stop <= not RX_Idle; |
Pkt_State <= IDLE; |
|
when others => null; |
end case; |
|
if( RX_Idle = '1' and Pkt_State /= IDLE )then |
Pkt_State <= FRAME_STOP; |
end if; |
|
end if; |
end process; |
|
U_RX_CRC : entity work.sdlc_crc16_ccitt |
generic map( |
Poly_Init => Poly_Init, |
431,32 → 1072,131
CRC16_Out => RX_CRC_Data |
); |
|
U_RX_FSM : entity work.sdlc_serial_rxfsm |
generic map( |
Reset_Level => Reset_Level |
) |
port map( |
Clock => Clock, |
Reset => Reset, |
-- |
BClk_Okay => BClk_Okay, |
-- |
DP_Port1_Addr => DP_Port1_Addr, |
DP_Port1_RWn => DP_Port1_RWn, |
DP_Port1_WrData => DP_Port1_WrData, |
DP_Port1_RdData => DP_Port1_RdData, |
DP_Port1_Req => DP_Port1_Req, |
DP_Port1_Ack => DP_Port1_Ack, |
-- |
RX_CRC_Valid => RX_CRC_Valid, |
RX_CRC_Data => RX_CRC_Data, |
-- |
RX_Frame_Start => RX_Frame_Start, |
RX_Frame_Stop => RX_Frame_Stop, |
RX_Frame_Valid => RX_Frame_Valid, |
RX_Frame_Data => RX_Frame_Data, |
-- |
RX_Interrupt => RX_Interrupt |
); |
CRC_History_proc: process( Clock, Reset ) |
begin |
if( Reset = Reset_Level )then |
RX_CRC_Hist(0) <= x"0000"; |
RX_CRC_Hist(1) <= x"0000"; |
RX_CRC_Hist(2) <= x"0000"; |
elsif( rising_edge(Clock) )then |
if( RX_CRC_Valid = '1' )then |
RX_CRC_Hist(2) <= RX_CRC_Hist(1); |
RX_CRC_Hist(1) <= RX_CRC_Hist(0); |
RX_CRC_Hist(0) <= RX_CRC_Data; |
end if; |
end if; |
end process; |
|
RX_Packet_RAM_proc: process( Reset, Clock ) |
begin |
if( Reset = Reset_Level )then |
RX_FSM_State <= WAIT_FOR_CLOCK; |
|
DP_Port1_Addr <= x"00"; |
DP_Port1_RWn <= '1'; |
DP_Port1_WrData <= x"00"; |
DP_Port1_Req <= '0'; |
|
RX_Length <= x"00"; |
|
RX_CRC_Rcvd <= x"0000"; |
|
RX_Interrupt <= '0'; |
|
elsif( rising_edge(Clock) )then |
|
DP_Port1_Addr <= x"00"; |
DP_Port1_RWn <= '1'; |
DP_Port1_WrData <= x"00"; |
DP_Port1_Req <= '0'; |
|
RX_Interrupt <= '0'; |
|
case( RX_FSM_State )is |
|
when WAIT_FOR_CLOCK => |
RX_FSM_State <= WAIT_FOR_FLAG; |
|
when WAIT_FOR_FLAG => |
if( RX_Frame_Start = '1' )then |
RX_Length <= x"00"; |
RX_FSM_State <= RX_MESG_DATA; |
end if; |
|
when RX_MESG_DATA => |
if( RX_Frame_Stop = '1' )then |
RX_Length <= RX_Length - 1; |
RX_FSM_State <= RX_CRC_UB_RD; |
elsif( RX_Frame_Valid = '1' )then |
RX_FSM_State <= RX_WR_DATA; |
if( RX_Length > 254 )then |
RX_Length <= ERR_LENGTH; |
RX_FSM_State <= RX_WR_COUNT; |
end if; |
end if; |
|
when RX_WR_DATA => |
RX_Length <= RX_Length + DP_Port1_Ack; |
DP_Port1_Addr <= RX_Length; |
DP_Port1_WrData <= RX_Frame_Data; |
DP_Port1_RWn <= '0'; |
DP_Port1_Req <= '1'; |
if( DP_Port1_Ack = '1' )then |
DP_Port1_Req <= '0'; |
RX_FSM_State <= RX_MESG_DATA; |
end if; |
|
when RX_CRC_UB_RD => |
RX_Length <= RX_Length - DP_Port1_Ack; |
DP_Port1_Addr <= RX_Length; |
DP_Port1_Req <= '1'; |
if( DP_Port1_Ack = '1' )then |
DP_Port1_Req <= '0'; |
RX_CRC_Rcvd_UB <= DP_Port1_RdData; |
RX_FSM_State <= RX_CRC_LB_RD; |
end if; |
|
when RX_CRC_LB_RD => |
DP_Port1_Addr <= RX_Length; |
DP_Port1_Req <= '1'; |
if( DP_Port1_Ack = '1' )then |
DP_Port1_Req <= '0'; |
RX_CRC_Rcvd_LB <= DP_Port1_RdData; |
RX_FSM_State <= RX_WR_CRC; |
end if; |
|
when RX_WR_CRC => |
DP_Port1_Addr <= CS_REGISTER; |
DP_Port1_WrData <= x"FF"; |
if( RX_CRC_Rcvd /= RX_CRC_Calc )then |
DP_Port1_WrData <= x"00"; |
end if; |
DP_Port1_RWn <= '0'; |
DP_Port1_Req <= '1'; |
if( DP_Port1_Ack = '1' )then |
DP_Port1_Req <= '0'; |
RX_FSM_State <= RX_WR_COUNT; |
end if; |
|
when RX_WR_COUNT => |
DP_Port1_Addr <= RX_REGISTER; |
DP_Port1_WrData <= RX_Length; |
DP_Port1_RWn <= '0'; |
DP_Port1_Req <= '1'; |
if( DP_Port1_Ack = '1' )then |
DP_Port1_Req <= '0'; |
RX_Interrupt <= '1'; |
RX_FSM_State <= WAIT_FOR_FLAG; |
end if; |
|
when others => null; |
end case; |
|
if( BClk_Okay = '0' )then |
RX_FSM_State <= WAIT_FOR_FLAG; |
end if; |
|
end if; |
end process; |
|
end architecture; |
/trunk/VHDL/sdlc_crc16_ccitt.vhd
1,122 → 1,119
-- Copyright (c)2020 Jeremy Seth Henry |
-- All rights reserved. |
-- |
-- Redistribution and use in source and binary forms, with or without |
-- modification, are permitted provided that the following conditions are met: |
-- * Redistributions of source code must retain the above copyright |
-- notice, this list of conditions and the following disclaimer. |
-- * Redistributions in binary form must reproduce the above copyright |
-- notice, this list of conditions and the following disclaimer in the |
-- documentation and/or other materials provided with the distribution, |
-- where applicable (as part of a user interface, debugging port, etc.) |
-- |
-- THIS SOFTWARE IS PROVIDED BY JEREMY SETH HENRY ``AS IS'' AND ANY |
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
-- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
-- DISCLAIMED. IN NO EVENT SHALL JEREMY SETH HENRY BE LIABLE FOR ANY |
-- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
-- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
-- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
-- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
-- |
-- VHDL Units : crc16_ccitt |
-- Description: Implements the 16-bit CCITT CRC on byte-wide data. Logic |
-- equations were taken from Intel/Altera app note AN049. |
-- |
-- Revision History |
-- Author Date Change |
------------------ -------- --------------------------------------------------- |
-- Seth Henry 04/14/20 Code cleanup and revision section added |
|
library ieee; |
use ieee.std_logic_1164.all; |
|
library work; |
use work.sdlc_serial_pkg.all; |
|
entity sdlc_crc16_ccitt is |
generic( |
Poly_Init : std_logic_vector(15 downto 0) := x"0000"; |
Reset_Level : std_logic := '1' |
); |
port( |
Clock : in std_logic; |
Reset : in std_logic; |
-- |
Clear : in std_logic; |
Wr_En : in std_logic; |
Wr_Data : in DATA_IN_TYPE; |
-- |
CRC16_Valid : out std_logic; |
CRC16_Out : out CRC_OUT_TYPE |
); |
end entity; |
|
architecture behave of sdlc_crc16_ccitt is |
|
signal Calc_En : std_logic := '0'; |
signal Buffer_En : std_logic := '0'; |
signal Data : DATA_IN_TYPE := x"00"; |
signal Exr : DATA_IN_TYPE := x"00"; |
signal Reg : CRC_OUT_TYPE := x"0000"; |
|
begin |
|
Exr(0) <= Reg(0) xor Data(0); |
Exr(1) <= Reg(1) xor Data(1); |
Exr(2) <= Reg(2) xor Data(2); |
Exr(3) <= Reg(3) xor Data(3); |
Exr(4) <= Reg(4) xor Data(4); |
Exr(5) <= Reg(5) xor Data(5); |
Exr(6) <= Reg(6) xor Data(6); |
Exr(7) <= Reg(7) xor Data(7); |
|
CRC16_Calc: process( Clock, Reset ) |
begin |
if( Reset = Reset_Level )then |
Calc_En <= '0'; |
Buffer_En <= '0'; |
Data <= x"00"; |
Reg <= Poly_Init; |
CRC16_Out <= x"0000"; |
CRC16_Valid <= '0'; |
elsif( rising_edge(Clock) )then |
Calc_En <= Wr_En; |
if( Wr_En = '1' )then |
Data <= Wr_Data; |
end if; |
|
if( Calc_En = '1' )then |
Reg(0) <= Reg(8) xor Exr(4) xor Exr(0); |
Reg(1) <= Reg(9) xor Exr(5) xor Exr(1); |
Reg(2) <= Reg(10) xor Exr(6) xor Exr(2); |
Reg(3) <= Reg(11) xor Exr(0) xor Exr(7) xor Exr(3); |
Reg(4) <= Reg(12) xor Exr(1) ; |
Reg(5) <= Reg(13) xor Exr(2) ; |
Reg(6) <= Reg(14) xor Exr(3) ; |
Reg(7) <= Reg(15) xor Exr(4) xor Exr(0); |
Reg(8) <= Exr(0) xor Exr(5) xor Exr(1); |
Reg(9) <= Exr(1) xor Exr(6) xor Exr(2); |
Reg(10) <= Exr(2) xor Exr(7) xor Exr(3); |
Reg(11) <= Exr(3) ; |
Reg(12) <= Exr(4) xor Exr(0); |
Reg(13) <= Exr(5) xor Exr(1); |
Reg(14) <= Exr(6) xor Exr(2); |
Reg(15) <= Exr(7) xor Exr(3); |
end if; |
|
if( Clear = '1' )then |
Reg <= Poly_Init; |
end if; |
|
Buffer_En <= Calc_En; |
if( Buffer_En = '1' )then |
CRC16_Out <= Reg xor x"FFFF"; |
end if; |
CRC16_Valid <= Buffer_En; |
end if; |
end process; |
|
end architecture; |
-- Copyright (c)2020 Jeremy Seth Henry |
-- All rights reserved. |
-- |
-- Redistribution and use in source and binary forms, with or without |
-- modification, are permitted provided that the following conditions are met: |
-- * Redistributions of source code must retain the above copyright |
-- notice, this list of conditions and the following disclaimer. |
-- * Redistributions in binary form must reproduce the above copyright |
-- notice, this list of conditions and the following disclaimer in the |
-- documentation and/or other materials provided with the distribution, |
-- where applicable (as part of a user interface, debugging port, etc.) |
-- |
-- THIS SOFTWARE IS PROVIDED BY JEREMY SETH HENRY ``AS IS'' AND ANY |
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
-- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
-- DISCLAIMED. IN NO EVENT SHALL JEREMY SETH HENRY BE LIABLE FOR ANY |
-- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
-- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
-- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
-- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
-- |
-- VHDL Units : crc16_ccitt |
-- Description: Implements the 16-bit CCITT CRC on byte-wide data. Logic |
-- equations were taken from Intel/Altera app note AN049. |
-- |
-- Revision History |
-- Author Date Change |
------------------ -------- --------------------------------------------------- |
-- Seth Henry 12/09/20 Created from original version |
|
library ieee; |
use ieee.std_logic_1164.all; |
|
entity sdlc_crc16_ccitt is |
generic( |
Poly_Init : std_logic_vector(15 downto 0) := x"0000"; |
Reset_Level : std_logic := '1' |
); |
port( |
Clock : in std_logic; |
Reset : in std_logic; |
-- |
Clear : in std_logic; |
Wr_En : in std_logic; |
Wr_Data : in std_logic_vector(7 downto 0); |
-- |
CRC16_Valid : out std_logic; |
CRC16_Out : out std_logic_vector(15 downto 0) |
); |
end entity; |
|
architecture behave of sdlc_crc16_ccitt is |
|
signal Calc_En : std_logic := '0'; |
signal Buffer_En : std_logic := '0'; |
signal Data : std_logic_vector(7 downto 0) := x"00"; |
signal Exr : std_logic_vector(7 downto 0) := x"00"; |
signal Reg : std_logic_vector(15 downto 0) := x"0000"; |
|
begin |
|
Exr(0) <= Reg(0) xor Data(0); |
Exr(1) <= Reg(1) xor Data(1); |
Exr(2) <= Reg(2) xor Data(2); |
Exr(3) <= Reg(3) xor Data(3); |
Exr(4) <= Reg(4) xor Data(4); |
Exr(5) <= Reg(5) xor Data(5); |
Exr(6) <= Reg(6) xor Data(6); |
Exr(7) <= Reg(7) xor Data(7); |
|
CRC16_Calc: process( Clock, Reset ) |
begin |
if( Reset = Reset_Level )then |
Calc_En <= '0'; |
Buffer_En <= '0'; |
Data <= x"00"; |
Reg <= Poly_Init; |
CRC16_Out <= x"0000"; |
CRC16_Valid <= '0'; |
elsif( rising_edge(Clock) )then |
Calc_En <= Wr_En; |
if( Wr_En = '1' )then |
Data <= Wr_Data; |
end if; |
|
if( Calc_En = '1' )then |
Reg(0) <= Reg(8) xor Exr(4) xor Exr(0); |
Reg(1) <= Reg(9) xor Exr(5) xor Exr(1); |
Reg(2) <= Reg(10) xor Exr(6) xor Exr(2); |
Reg(3) <= Reg(11) xor Exr(0) xor Exr(7) xor Exr(3); |
Reg(4) <= Reg(12) xor Exr(1) ; |
Reg(5) <= Reg(13) xor Exr(2) ; |
Reg(6) <= Reg(14) xor Exr(3) ; |
Reg(7) <= Reg(15) xor Exr(4) xor Exr(0); |
Reg(8) <= Exr(0) xor Exr(5) xor Exr(1); |
Reg(9) <= Exr(1) xor Exr(6) xor Exr(2); |
Reg(10) <= Exr(2) xor Exr(7) xor Exr(3); |
Reg(11) <= Exr(3) ; |
Reg(12) <= Exr(4) xor Exr(0); |
Reg(13) <= Exr(5) xor Exr(1); |
Reg(14) <= Exr(6) xor Exr(2); |
Reg(15) <= Exr(7) xor Exr(3); |
end if; |
|
if( Clear = '1' )then |
Reg <= Poly_Init; |
end if; |
|
Buffer_En <= Calc_En; |
if( Buffer_En = '1' )then |
CRC16_Out <= Reg xor x"FFFF"; |
end if; |
CRC16_Valid <= Buffer_En; |
end if; |
end process; |
|
end architecture; |