OpenCores
URL https://opencores.org/ocsvn/hdbn/hdbn/trunk

Subversion Repositories hdbn

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 3 to Rev 4
    Reverse comparison

Rev 3 → Rev 4

/tags/arelease/doc/hdbn.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
tags/arelease/doc/hdbn.pdf Property changes : Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: tags/arelease/doc/src/hdbn.doc =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/arelease/doc/src/hdbn.doc =================================================================== --- tags/arelease/doc/src/hdbn.doc (revision 3) +++ tags/arelease/doc/src/hdbn.doc (nonexistent)
tags/arelease/doc/src/hdbn.doc Property changes : Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: trunk/bench/vhdl/hdbn_tb.vhd =================================================================== --- trunk/bench/vhdl/hdbn_tb.vhd (revision 3) +++ trunk/bench/vhdl/hdbn_tb.vhd (nonexistent) @@ -1,341 +0,0 @@ -------------------------------------------------------------------------------- --- Title : hdbn_tb --- Project : hdbn -------------------------------------------------------------------------------- --- File : hdbn_tb.vhd --- Author : Allan Herriman --- Organization : Opencores --- Created : 9 Aug 1999 --- Platform : ? --- Simulators : Should work in any VHDL '93 or '00 compliant simulator. --- (Strict '87 compliant simulators will not work, as some --- '93 features have been used.) --- Tested with several versions of Modelsim and Simili. --- Most recently tested with Modelsim PE 5.6d and Simili 2.1b10 --- on Windows 2000 --- Synthesizers : N/A (this is a testbench) --- Targets : N/A (this is a testbench) --- Dependency : entities hdbne and hdbnd -------------------------------------------------------------------------------- --- Description : testbench for entities hdbne and hdbnd. --- This is an "assertion based" test. If it runs to --- completion (about 16ms) without errors, it has passed. --- --- Reference : ITU-T G.703 --- -------------------------------------------------------------------------------- --- Copyright (c) notice --- http://www.opensource.org/licenses/bsd-license.html --- -------------------------------------------------------------------------------- --- --- CVS Revision History --- --- $Log: not supported by cvs2svn $ --- ------------------------------------------------------------------------------- - -library ieee; -use ieee.std_logic_1164.all; - -use std.textio.all; - - -entity hdbn_tb is - generic ( - HalfWidthOutputs : boolean := FALSE; -- set TRUE to use 2x clock on encoder - InjectError : boolean := FALSE; -- set TRUE to test decoder error detection - SwapPandN : boolean := FALSE; -- set TRUE to swap P,N signals between enc and dec - EncoderType : integer range 2 to 3 := 3; -- 3: HDB3 2: HDB2/B3ZS - PulseActiveState : std_logic := '1'; -- active state of P and N signals - LogSpiceFile : boolean := FALSE; -- set TRUE to log encoder output in Spice PWL format - LogFileName : string := "hdbn.txt"; - StartupTransient : time := 15 us -- disables assertions for this long - ); -end hdbn_tb; -- End entity hdbn_tb - - -architecture tb of hdbn_tb is - - signal Reset : std_logic := '1'; - signal Clk : std_logic := '0'; - signal TxClk : std_logic := '0'; - signal TxClkEnable : std_logic; - signal Data : std_logic; -- encoder input (stimulus) - signal DataOut : std_logic; -- decoder output - signal CodeError : std_logic; - signal P : std_logic; - signal N : std_logic; - - signal PwithErrors : std_logic; - signal NwithErrors : std_logic; - - signal InjectedError : std_logic := '0'; - - signal DataDelayed : std_logic; -- Matches delay of encoder - signal DataDelayedSomeMore : std_logic; -- Matches delay of encoder and decoder - signal Violation : std_logic; - - signal SimulationFinished : boolean := FALSE; - -begin - - -------------------------------------------------------------------------------- --- Instantiation of entity 'hdbne' - hdbn encoder under test -------------------------------------------------------------------------------- - eUT : entity work.hdbne - generic map ( - EncoderType => EncoderType, - PulseActiveState => PulseActiveState - ) - port map ( - Reset_i => Reset, - Clk_i => TxClk, - ClkEnable_i => TxClkEnable, - Data_i => Data, - OutputGate_i => TxClkEnable, - P_o => P, - N_o => N - ); - - -------------------------------------------------------------------------------- --- Instantiation of entity 'hdbnd' - hdbn decoder under test -------------------------------------------------------------------------------- - dUT : entity work.hdbnd - generic map ( - EncoderType => EncoderType, - PulseActiveState => PulseActiveState - ) - port map ( - Reset_i => Reset, - Clk_i => Clk, - ClkEnable_i => '1', - P_i => PwithErrors, - N_i => NwithErrors, - Data_o => DataOut, - CodeError_o => CodeError - ); - - -------------------------------------------------------------------------------- --- make two clocks, 4.096MHz and 2.048MHz. --- Use HalfWidthOutputs to select which one is used for encoder --- Note: care must be taken to balance delta delays, otherwise races between --- the clocks may cause unpredictable results. -------------------------------------------------------------------------------- - MakeClk: process - variable Clkv : std_logic := '0'; - variable Clk2xv : std_logic := '0'; - begin - wait for 122 ns; - if SimulationFinished then - wait until not SimulationFinished; - end if; - Clk2xv := not Clk2xv; - if Clk2xv = '1' then - Clkv := not Clkv; - end if; - - -- assign to signals, all in the same delta cycle - Clk <= Clkv; - if HalfWidthOutputs then - -- run Encoder twice as fast, with every 2nd clock enabled - TxClk <= Clk2xv; - TxClkEnable <= not Clkv; - else - -- run Encoder at normal speed, with all clocks enabled - TxClk <= Clkv; - TxClkEnable <= '1'; - end if; - - end process MakeClk; - -------------------------------------------------------------------------------- --- Make async, active high Reset signal -------------------------------------------------------------------------------- - Reset <= '1', '0' after 50 ns; - - -------------------------------------------------------------------------------- --- PROCESS : StimulusGen, makes pseudo random bit sequence for testing. --- DESCRIPTION: 15 bit LFSR --- See ITU-T O.151 for details of this LFSR (this is the "official" PRBS to --- use for 2.048Mbps testing). -------------------------------------------------------------------------------- - StimulusGen: process (Reset, Clk) - variable shiftreg : Std_logic_vector(14 downto 0) := (others => '0'); - begin - if Reset = '1' then - shiftreg := (others => '0'); - Data <= '0'; - elsif rising_edge(Clk) then - shiftreg := shiftreg(13 downto 0) & (not (shiftreg(14) xor shiftreg(13))); - - if HalfWidthOutputs then - Data <= shiftreg(1); -- compensate for earlier sampling in hdbne when run from Clk2x - else - Data <= shiftreg(0); - end if; - DataDelayed <= shiftreg(3 + EncoderType); -- for violation visualisation - DataDelayedSomeMore <= shiftreg(5 + 2 * EncoderType); -- for decoder testing - - if shiftreg = (shiftreg'range => '0') then - report "hdbn simulation finished"; - SimulationFinished <= TRUE after 10 us; - end if; - - end if; - end process StimulusGen; - - --------------------------------------------------------------------------------- --- optionally inject errors, to test decoder error detection --- and optionally crossover P&N on the line --------------------------------------------------------------------------------- - InjectErrors : if InjectError generate - InjectedError <= '0', - '1' after StartupTransient + 1 us, - '0' after StartupTransient + 1.500 us; - end generate InjectErrors; - - -- normal connection, P->P, N->N - NoSwapLines : if not SwapPandN generate - PwithErrors <= P xor InjectedError; - NwithErrors <= N; - end generate NoSwapLines; - - -- check that it still works with P and N crossed over - SwapLines : if SwapPandN generate - PwithErrors <= N xor InjectedError; - NwithErrors <= P; - end generate SwapLines; - - -------------------------------------------------------------------------------- --- PROCESS : Checker --- DESCRIPTION: Checks aspects of the hdb2/hdb3 encoder against the spec, --- and checks the decoder against the encoder -------------------------------------------------------------------------------- - Checker: process (Clk) - variable RunningSum : integer := 0; - variable ZeroCount : integer := 0; - begin - if rising_edge(Clk) then - - -- Encoder P and N outputs should never be active at the same time - assert (not ((P = PulseActiveState) and (N = PulseActiveState))) - report "Simultaneous P and N Pulse Error on HDBNE output" - severity error; - - -- There should be no DC component on the line - if P = PulseActiveState then - RunningSum := RunningSum + 1; - elsif N = PulseActiveState then - RunningSum := RunningSum - 1; - end if; - - assert RunningSum < 2 and RunningSum > -2 - report "Running Sum Error on HDBNE output" - severity error; - - -- There shouldn't be too many zeros in a row at encoder output - if P = PulseActiveState or N = PulseActiveState then - ZeroCount := 0; - else - ZeroCount := ZeroCount + 1; - end if; - - assert (ZeroCount <= EncoderType) or (now < StartupTransient) - report "Long String Of Zeros on HDBNE output" - severity error; - - -- The decoder output should match the encoder input - assert ((DataDelayedSomeMore xor DataOut) = '0') or (now < StartupTransient) - report "Decoder Bit Error on HDBND output" - severity error; - - -- The decoder shouldn't detect any errors - assert (CodeError = '0') or (now < StartupTransient) - report "Decoder Code Error on HDBND output" - severity error; - - end if; - end process Checker; - - - Violation <= DataDelayed xor (P or N); -- for visualisation only - -- (only useful if HalfWidthOutputs is FALSE) - - -------------------------------------------------------------------------------- --- Log values to a file in PSpice "PWL" format, for testing of E1 LIU, etc. --- --- Note: this process isn't an essential part of the test bench. --- --- Example spice usage: --- --- .PARAM PH = 2.37V ; G.703 2.048Mbps pulse height --- .PARAM PW = 244ns ; G.703 2.048Mbps pulse width --- --- Vdrive 1 0 PWL --- + TIME_SCALE_FACTOR={PW} --- + VALUE_SCALE_FACTOR={PH} --- + FILE hdbn.txt --- -------------------------------------------------------------------------------- -GenLogger : if LogSpiceFile generate - - Logger : process (Clk) - FILE log_file : text open write_mode IS LogFileName; - VARIABLE l : line; - variable LineNumber : integer := 0; - variable value : integer; - variable FirstTime : boolean := TRUE; - begin - if rising_edge(Clk) then - - if FirstTime then - -- output (0, 0) as the first line in the file - write(l, '(' & integer'image(LineNumber) & ", 0)"); - writeline(log_file, l); - FirstTime := FALSE; - end if; - - if P = PulseActiveState then - value := 1; - elsif N = PulseActiveState then - value := -1; - else - value := 0; - end if; - - if value = 0 then - -- don't bother to print it (as the voltage is already 0), but do update the time! - LineNumber := LineNumber + 2; - else - -- ramp the voltage from 0 to the peak value - write(l, '(' & integer'image(LineNumber) & ".49, 0)"); - writeline(log_file, l); - write(l, '(' & integer'image(LineNumber) & ".5, " & integer'image(value) & ')'); - writeline(log_file, l); - LineNumber := LineNumber + 1; - - -- ramp the voltage from the peak value back to 0 - write(l, '(' & integer'image(LineNumber) & ".49, " & integer'image(value) & ')'); - writeline(log_file, l); - write(l, '(' & integer'image(LineNumber) & ".5, 0)"); - writeline(log_file, l); - LineNumber := LineNumber + 1; - end if; - end if; - end process Logger; - -end generate GenLogger; - - -end architecture tb; -------------------------------------------------------------------------------- --- End of hdbn_tb.vhd -------------------------------------------------------------------------------- Index: trunk/rtl/vhdl/hdbnd.vhd =================================================================== --- trunk/rtl/vhdl/hdbnd.vhd (revision 3) +++ trunk/rtl/vhdl/hdbnd.vhd (nonexistent) @@ -1,262 +0,0 @@ -------------------------------------------------------------------------------- --- Title : hdbnd --- Project : hdbn -------------------------------------------------------------------------------- --- File : hdbnd.vhd --- Author : Allan Herriman --- Organization : Opencores --- Created : 9 Aug 1999 --- Platform : ? --- Simulators : Any VHDL '87, '93 or '00 compliant simulator will work. --- Tested with several versions of Modelsim and Simili. --- Synthesizers : Any VHDL compliant synthesiser will work (tested with --- Synplify Pro and Leonardo). --- Targets : Anything (contains no target dependent features except --- combinatorial logic and D flip flops with async --- reset or set). --- Dependency : None. Complementary encoder is hdb3e. -------------------------------------------------------------------------------- --- Description : HDB3 or HDB2 (B3ZS) decoder. --- Note: this module does not include clock recovery. --- A separate CDR (Clock and Data Recovery) circuit must be --- used. --- --- HDB3 is typically used to encode data at 2.048, 8.448 and 34.368Mb/s --- B3ZS is typically used to encode data at 44.736Mb/s --- These encodings are polarity insensitive, so the P and N inputs may be --- used interchangeably (swapped). --- --- Reference : ITU-T G.703 --- -------------------------------------------------------------------------------- --- Copyright (c) notice --- http://www.opensource.org/licenses/bsd-license.html --- -------------------------------------------------------------------------------- --- --- CVS Revision History --- --- $Log: not supported by cvs2svn $ --- ------------------------------------------------------------------------------- - -library ieee; -use ieee.std_logic_1164.all; - - -entity hdbnd is - generic ( - EncoderType : integer range 2 to 3 := 3; -- 3: HDB3 2: HDB2/B3ZS - PulseActiveState : std_logic := '1' -- active state of P and N inputs - ); - port ( - Reset_i : in std_logic := '0'; -- active high async reset - Clk_i : in std_logic; -- rising edge clock - ClkEnable_i : in std_logic := '1'; -- active high clock enable - P_i : in std_logic; -- +ve pulse input - N_i : in std_logic; -- -ve pulse input - Data_o : out std_logic; -- active high data output - CodeError_o : out std_logic -- active high error indicator - ); -end hdbnd; -- End entity hdbnd - - -architecture rtl of hdbnd is - - signal PinRaw : std_logic; -- registered P input - signal NinRaw : std_logic; -- registered N input - signal Pin : std_logic; -- registered P input (with polarity corrected) - signal Nin : std_logic; -- registered N input (with polarity corrected) - signal Violation : std_logic; -- pulse violation detected - signal LastPulsePolarity : std_logic; -- last pulse sense 1=P, 0=N - signal LastViolationPolarity : std_logic; -- last violation sense " - - -- shift register bits (to align data with violations, so we can delete them) - signal Q1 : std_logic; - signal Q2 : std_logic; - signal Q3 : std_logic; - - -- signals used for calculating CodeError - signal ViolationError : std_logic; -- indicates bad violation - signal ZeroCount : integer range 0 to 3; -- counts 0s in input - signal TooManyZeros : std_logic; -- indicates 4 consecutive zeros detected - signal PulseError : std_logic; -- indicates simultaneous P and N pulse - -begin - -------------------------------------------------------------------------------- --- PROCESS : RegisterInput --- DESCRIPTION: DFF to register P and N inputs (reduces fan-in, etc) --- Most applications of this core will be taking inputs from --- off-chip, so these FF will be in the I/O blocks. --- Metastability issues: None. --- Either (1) the external CDR provides adequate --- timing margin (which ensures no metastability issues) --- or (2) it doesn't provide adequate timing margin (which could happen --- if the input cable is unplugged) and any metastable states are irrelevant, --- as the downstream decoding logic is free of lockup states, --- and will recover within a few clocks once the --- CDR is providing normal input again. -------------------------------------------------------------------------------- - RegisterInput: process (Reset_i, Clk_i) - begin - if Reset_i = '1' then - PinRaw <= '0'; - NinRaw <= '0'; - elsif rising_edge(Clk_i) then - if ClkEnable_i = '1' then - PinRaw <= to_X01(P_i); - NinRaw <= to_X01(N_i); - end if; - end if; - end process RegisterInput; - - - -- Restore active low pulse inputs to active high for internal use. - Pin <= PinRaw xor (not PulseActiveState); - Nin <= NinRaw xor (not PulseActiveState); - - -------------------------------------------------------------------------------- --- PROCESS : DecodeViolation --- DESCRIPTION: Work out whether there has been a pulse violation, and --- remember the sense of the last input pulse. -------------------------------------------------------------------------------- - DecodeViolation: process (Reset_i, Clk_i) - variable tmp : std_logic_vector(1 downto 0); - begin - if Reset_i = '1' then - LastPulsePolarity <= '0'; - elsif rising_edge(Clk_i) then - if ClkEnable_i = '1' then - tmp := Pin & Nin; - case tmp is - when "00" => LastPulsePolarity <= LastPulsePolarity; --hold - when "10" => LastPulsePolarity <= '1'; -- set - when "01" => LastPulsePolarity <= '0'; -- reset - when others => LastPulsePolarity <= '0'; -- don't care - end case; - end if; - end if; - end process DecodeViolation; - - Violation <= (Pin and LastPulsePolarity) or (Nin and (not LastPulsePolarity)); - - -------------------------------------------------------------------------------- --- PROCESS : DelayData --- DESCRIPTION: Delay the data input so that it lines up with the violation --- signal, so we can remove the B bit (in process DecodeData). -------------------------------------------------------------------------------- - DelayData: process (Reset_i, Clk_i) - begin - if Reset_i = '1' then - Q1 <= '0'; - Q2 <= '0'; - Q3 <= '0'; - elsif rising_edge(Clk_i) then - if ClkEnable_i = '1' then - Q1 <= (Pin or Nin) and (not Violation); -- delete V bit - Q2 <= Q1; - if EncoderType = 3 then - -- HDB3, delay by 3 clocks - Q3 <= Q2; - else - -- HDB2, delay by 2 clocks - Q3 <= Q1; -- skip Q2 - end if; - end if; - end if; - end process DelayData; - - -------------------------------------------------------------------------------- --- PROCESS : DecodeData --- DESCRIPTION: remove B bits from data, and register output -------------------------------------------------------------------------------- - DecodeData: process (Reset_i, Clk_i) - begin - if Reset_i = '1' then - Data_o <= '0'; - elsif rising_edge(Clk_i) then - if ClkEnable_i = '1' then - Data_o <= Q3 and (not Violation); -- delete B bit - end if; - end if; - end process DecodeData; - - -------------------------------------------------------------------------------- --- PROCESS : CountZeros --- DESCRIPTION: count number of contiguous zeros in input (mod 3 or 4) -------------------------------------------------------------------------------- - CountZeros: process (Reset_i, Clk_i) - begin - if Reset_i = '1' then - ZeroCount <= 0; - elsif rising_edge(Clk_i) then - if ClkEnable_i = '1' then - if (Pin or Nin) = '1' then - ZeroCount <= 0; -- have seen a 1, reset count - elsif ZeroCount >= EncoderType then - ZeroCount <= EncoderType; -- hold - else - ZeroCount <= ZeroCount + 1; -- increment - end if; - end if; - end if; - end process CountZeros; - - -------------------------------------------------------------------------------- --- PROCESS : DecodeViolationError --- DESCRIPTION: Remember the polarity of this violation, so that we can work --- out whether the next violation is an error. -------------------------------------------------------------------------------- - DecodeViolationError: process (Reset_i, Clk_i) - begin - if Reset_i = '1' then - LastViolationPolarity <= '0'; - elsif rising_edge(Clk_i) then - if ClkEnable_i = '1' then - if Violation = '1' then - LastViolationPolarity <= LastPulsePolarity; - else - LastViolationPolarity <= LastViolationPolarity; -- latch - end if; - end if; - end if; - end process DecodeViolationError; - - -------------------------------------------------------------------------------- --- The follow logic checks for various error conditions. -------------------------------------------------------------------------------- - - ViolationError <= Violation and (not (Pin xor LastViolationPolarity)); - - PulseError <= Pin and Nin; - - TooManyZeros <= (not (Pin or Nin)) when (ZeroCount = EncoderType) else '0'; - - -------------------------------------------------------------------------------- --- PROCESS : RegisterCodeError --- DESCRIPTION: combine all error signals and register the output -------------------------------------------------------------------------------- - RegisterCodeError: process (Reset_i, Clk_i) - begin - if Reset_i = '1' then - CodeError_o <= '0'; - elsif rising_edge(Clk_i) then - if ClkEnable_i = '1' then - CodeError_o <= ViolationError or PulseError or TooManyZeros; - end if; - end if; - end process RegisterCodeError; - - -end rtl; -- End architecture rtl; -------------------------------------------------------------------------------- --- End of hdbnd.vhd -------------------------------------------------------------------------------- Index: trunk/rtl/vhdl/hdbne.vhd =================================================================== --- trunk/rtl/vhdl/hdbne.vhd (revision 3) +++ trunk/rtl/vhdl/hdbne.vhd (nonexistent) @@ -1,273 +0,0 @@ -------------------------------------------------------------------------------- --- Title : hdbne --- Project : hdbn -------------------------------------------------------------------------------- --- File : hdbne.vhd --- Author : Allan Herriman --- Organization : Opencores --- Created : 9 Aug 1999 --- Platform : ? --- Simulators : Any VHDL '87, '93 or '00 compliant simulator will work. --- Tested with several versions of Modelsim and Simili. --- Synthesizers : Any VHDL compliant synthesiser will work (tested with --- Synplify Pro and Leonardo). --- Targets : Anything (contains no target dependent features except --- combinatorial logic and D flip flops with async --- reset or set). --- Dependency : None. Complementary decoder is hdb3d. -------------------------------------------------------------------------------- --- Description : HDB3 or HDB2 (B3ZS) encoder. --- P and N outputs are full width by default. --- Half width pulses can be created by using a double rate clock and --- strobing ClkEnable and OutputEnable appropriately (high every second clock). --- --- HDB3 is typically used to encode data at 2.048, 8.448 and 34.368Mb/s --- B3ZS is typically used to encode data at 44.736Mb/s --- The outputs will require pulse shaping if used to drive the line. --- These encodings are polarity insensitive, so the P and N outputs may be --- used interchangeably (swapped). --- --- Reference : ITU-T G.703 --- -------------------------------------------------------------------------------- --- Copyright (c) notice --- http://www.opensource.org/licenses/bsd-license.html --- -------------------------------------------------------------------------------- --- --- CVS Revision History --- --- $Log: not supported by cvs2svn $ --- ------------------------------------------------------------------------------- - -library ieee; -use ieee.std_logic_1164.all; - - -entity hdbne is - generic ( - EncoderType : integer range 2 to 3 := 3; -- 3: HDB3 2: HDB2/B3ZS - PulseActiveState : std_logic := '1' -- active state of P and N outputs - ); - port ( - Reset_i : in std_logic := '0'; -- active high async reset - Clk_i : in std_logic; -- rising edge clock - ClkEnable_i : in std_logic := '1'; -- active high clock enable - Data_i : in std_logic; -- active high data input - OutputGate_i : in std_logic := '1'; -- '0' forces P and N to not PulseActiveState (synchronously, but ignoring ClkEnable) - P_o : out std_logic; -- encoded +ve pulse output - N_o : out std_logic -- encoded -ve pulse output - ); -end hdbne; -- End entity hdbne - - -architecture rtl of hdbne is - - signal Q1 : std_logic; -- Q1 through Q5 form a shift - signal Q2 : std_logic; -- register for aligning - signal Q3 : std_logic; -- the data so we can insert - signal Q4 : std_logic; -- the violations - signal Q5 : std_logic; - - signal AMI : std_logic; -- sense of pulse (P or N) - signal ViolationType : std_logic; -- sense of violation - signal ZeroCount : integer range 0 to 3; -- counts 0s in input - signal ZeroString : std_logic; -- goes to '1' when 3 or 4 0s seen - signal ZeroStringDelayed : std_logic; -- above delayed by 1 clock - -begin - -------------------------------------------------------------------------------- --- PROCESS : RegisterInput --- DESCRIPTION: DFF (Q1) to register input data (reduces fan-in, etc) -------------------------------------------------------------------------------- - RegisterInput: process (Reset_i, Clk_i) - begin - if Reset_i = '1' then - Q1 <= '0'; - elsif rising_edge(Clk_i) then - if ClkEnable_i = '1' then - Q1 <= to_X01(Data_i); - end if; - end if; - end process RegisterInput; - - -------------------------------------------------------------------------------- --- PROCESS : CountZeros --- DESCRIPTION: count number of contiguous zeros in input (mod 4 or mod 3) -------------------------------------------------------------------------------- - CountZeros: process (Reset_i, Clk_i) - begin - if Reset_i = '1' then - ZeroCount <= 0; - elsif rising_edge(Clk_i) then - if ClkEnable_i = '1' then - if Q1 = '1' then - ZeroCount <= 0; -- have seen a 1, reset count - elsif ZeroCount >= EncoderType then - ZeroCount <= 0; -- increment modulo 3 or 4 - else - ZeroCount <= ZeroCount + 1; -- increment - end if; - end if; - end if; - end process CountZeros; - - -------------------------------------------------------------------------------- --- PROCESS : DecodeCount (combinatorial) --- DESCRIPTION: decode ZeroCount to indicate when string of 3 or 4 zeros is present --- Note: this process is not clocked -------------------------------------------------------------------------------- - DecodeCount: process (Q1, ZeroCount) - begin - if ZeroCount = EncoderType and Q1 = '0' then - ZeroString <= '1'; - else - ZeroString <= '0'; - end if; - end process DecodeCount; - - -------------------------------------------------------------------------------- --- PROCESS : RegisterZeroString --- DESCRIPTION: DFF to register the ZeroString signal -------------------------------------------------------------------------------- - RegisterZeroString: process (Reset_i, Clk_i) - begin - if Reset_i = '1' then - ZeroStringDelayed <= '0'; - elsif rising_edge(Clk_i) then - if ClkEnable_i = '1' then - ZeroStringDelayed <= ZeroString; - end if; - end if; - end process RegisterZeroString; - - -------------------------------------------------------------------------------- --- PROCESS : DelayData --- DESCRIPTION: insert 1 if needed for violation, and delay data by 2 or 3 clocks --- to line up with ZeroString detection. -------------------------------------------------------------------------------- - DelayData: process (Reset_i, Clk_i) - begin - if Reset_i = '1' then - Q2 <= '0'; - Q3 <= '0'; - Q4 <= '0'; - elsif rising_edge(Clk_i) then - if ClkEnable_i = '1' then - Q2 <= Q1 or ZeroString; -- insert Violation bit - Q3 <= Q2; - if EncoderType = 3 then - -- HDB3, delay by 3 clocks - Q4 <= Q3; - else - -- HDB2, delay by 2 clocks - Q4 <= Q2; -- skip Q3 - end if; - end if; - end if; - end process DelayData; - - -------------------------------------------------------------------------------- --- PROCESS : InsertBBit --- DESCRIPTION: Delay Q4 by one clock, and insert B bit if needed. -------------------------------------------------------------------------------- - InsertBBit: process (Reset_i, Clk_i) - begin - if Reset_i = '1' then - Q5 <= '0'; - elsif rising_edge(Clk_i) then - if ClkEnable_i = '1' then - Q5 <= Q4 or (ZeroString and (not ViolationType)); - end if; - end if; - end process InsertBBit; - - -------------------------------------------------------------------------------- --- PROCESS : ToggleViolationType --- DESCRIPTION: Toggle ViolationType whenever Q5 is 1 -------------------------------------------------------------------------------- - ToggleViolationType: process (Reset_i, Clk_i) - begin - if Reset_i = '1' then - ViolationType <= '0'; - elsif rising_edge(Clk_i) then - if ClkEnable_i = '1' then - ViolationType <= ViolationType xor Q5; - end if; - end if; - end process ToggleViolationType; - - -------------------------------------------------------------------------------- --- PROCESS : AMIFlipFlop --- DESCRIPTION: toggle AMI to alternate P and N pulses. Force a violation (no --- toggle) occasionally. -------------------------------------------------------------------------------- - AMIFlipFlop: process (Reset_i, Clk_i) - begin - if Reset_i = '1' then - AMI <= '0'; - elsif rising_edge(Clk_i) then - if ClkEnable_i = '1' then - AMI <= AMI xor (Q5 and (ViolationType nand (ZeroString or ZeroStringDelayed))); - end if; - end if; - end process AMIFlipFlop; - - -------------------------------------------------------------------------------- --- PROCESS : MakePandNPulses --- DESCRIPTION: Gate Q5 with AMI to produce the P and N outputs --- Note that OutputEnable overrides ClkEnable, to allow creation of --- half width pulses. --- The flip flops P and N will drive the outputs to the LIU, and these --- flip flops should be in the IOBs in an FPGA. Clk to output delay --- should be matched for P and N to avoid pulse shape distortion at the LIU --- output. -------------------------------------------------------------------------------- - MakePandNPulses: process (Reset_i, Clk_i) - begin - if Reset_i = '1' then - P_o <= not PulseActiveState; - N_o <= not PulseActiveState; - elsif rising_edge(Clk_i) then - if ClkEnable_i = '1' or OutputGate_i /= '1' then - if OutputGate_i /= '1' then - -- force output to '0' - P_o <= not PulseActiveState; - N_o <= not PulseActiveState; - else - -- normal operation - if Q5 = '1' then - if AMI = '1' then - -- output '1' on P - P_o <= PulseActiveState; - N_o <= not PulseActiveState; - else - -- output '1' on N - P_o <= not PulseActiveState; - N_o <= PulseActiveState; - end if; - else - -- output '0' - P_o <= not PulseActiveState; - N_o <= not PulseActiveState; - end if; - end if; - end if; - end if; - end process MakePandNPulses; - - -end rtl; -- End architecture rtl; -------------------------------------------------------------------------------- --- End of hdbne.vhd -------------------------------------------------------------------------------- Index: trunk/doc/src/hdbn.doc =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/doc/src/hdbn.doc =================================================================== --- trunk/doc/src/hdbn.doc (revision 3) +++ trunk/doc/src/hdbn.doc (nonexistent)
trunk/doc/src/hdbn.doc Property changes : Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: trunk/doc/hdbn.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/doc/hdbn.pdf =================================================================== --- trunk/doc/hdbn.pdf (revision 3) +++ trunk/doc/hdbn.pdf (nonexistent)
trunk/doc/hdbn.pdf Property changes : Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: hdbn/trunk/bench/vhdl/hdbn_tb.vhd =================================================================== --- hdbn/trunk/bench/vhdl/hdbn_tb.vhd (nonexistent) +++ hdbn/trunk/bench/vhdl/hdbn_tb.vhd (revision 4) @@ -0,0 +1,341 @@ +------------------------------------------------------------------------------- +-- Title : hdbn_tb +-- Project : hdbn +------------------------------------------------------------------------------- +-- File : hdbn_tb.vhd +-- Author : Allan Herriman +-- Organization : Opencores +-- Created : 9 Aug 1999 +-- Platform : ? +-- Simulators : Should work in any VHDL '93 or '00 compliant simulator. +-- (Strict '87 compliant simulators will not work, as some +-- '93 features have been used.) +-- Tested with several versions of Modelsim and Simili. +-- Most recently tested with Modelsim PE 5.6d and Simili 2.1b10 +-- on Windows 2000 +-- Synthesizers : N/A (this is a testbench) +-- Targets : N/A (this is a testbench) +-- Dependency : entities hdbne and hdbnd +------------------------------------------------------------------------------- +-- Description : testbench for entities hdbne and hdbnd. +-- This is an "assertion based" test. If it runs to +-- completion (about 16ms) without errors, it has passed. +-- +-- Reference : ITU-T G.703 +-- +------------------------------------------------------------------------------- +-- Copyright (c) notice +-- http://www.opensource.org/licenses/bsd-license.html +-- +------------------------------------------------------------------------------- +-- +-- CVS Revision History +-- +-- $Log: not supported by cvs2svn $ +-- +------------------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; + +use std.textio.all; + + +entity hdbn_tb is + generic ( + HalfWidthOutputs : boolean := FALSE; -- set TRUE to use 2x clock on encoder + InjectError : boolean := FALSE; -- set TRUE to test decoder error detection + SwapPandN : boolean := FALSE; -- set TRUE to swap P,N signals between enc and dec + EncoderType : integer range 2 to 3 := 3; -- 3: HDB3 2: HDB2/B3ZS + PulseActiveState : std_logic := '1'; -- active state of P and N signals + LogSpiceFile : boolean := FALSE; -- set TRUE to log encoder output in Spice PWL format + LogFileName : string := "hdbn.txt"; + StartupTransient : time := 15 us -- disables assertions for this long + ); +end hdbn_tb; -- End entity hdbn_tb + + +architecture tb of hdbn_tb is + + signal Reset : std_logic := '1'; + signal Clk : std_logic := '0'; + signal TxClk : std_logic := '0'; + signal TxClkEnable : std_logic; + signal Data : std_logic; -- encoder input (stimulus) + signal DataOut : std_logic; -- decoder output + signal CodeError : std_logic; + signal P : std_logic; + signal N : std_logic; + + signal PwithErrors : std_logic; + signal NwithErrors : std_logic; + + signal InjectedError : std_logic := '0'; + + signal DataDelayed : std_logic; -- Matches delay of encoder + signal DataDelayedSomeMore : std_logic; -- Matches delay of encoder and decoder + signal Violation : std_logic; + + signal SimulationFinished : boolean := FALSE; + +begin + + +------------------------------------------------------------------------------- +-- Instantiation of entity 'hdbne' - hdbn encoder under test +------------------------------------------------------------------------------- + eUT : entity work.hdbne + generic map ( + EncoderType => EncoderType, + PulseActiveState => PulseActiveState + ) + port map ( + Reset_i => Reset, + Clk_i => TxClk, + ClkEnable_i => TxClkEnable, + Data_i => Data, + OutputGate_i => TxClkEnable, + P_o => P, + N_o => N + ); + + +------------------------------------------------------------------------------- +-- Instantiation of entity 'hdbnd' - hdbn decoder under test +------------------------------------------------------------------------------- + dUT : entity work.hdbnd + generic map ( + EncoderType => EncoderType, + PulseActiveState => PulseActiveState + ) + port map ( + Reset_i => Reset, + Clk_i => Clk, + ClkEnable_i => '1', + P_i => PwithErrors, + N_i => NwithErrors, + Data_o => DataOut, + CodeError_o => CodeError + ); + + +------------------------------------------------------------------------------- +-- make two clocks, 4.096MHz and 2.048MHz. +-- Use HalfWidthOutputs to select which one is used for encoder +-- Note: care must be taken to balance delta delays, otherwise races between +-- the clocks may cause unpredictable results. +------------------------------------------------------------------------------- + MakeClk: process + variable Clkv : std_logic := '0'; + variable Clk2xv : std_logic := '0'; + begin + wait for 122 ns; + if SimulationFinished then + wait until not SimulationFinished; + end if; + Clk2xv := not Clk2xv; + if Clk2xv = '1' then + Clkv := not Clkv; + end if; + + -- assign to signals, all in the same delta cycle + Clk <= Clkv; + if HalfWidthOutputs then + -- run Encoder twice as fast, with every 2nd clock enabled + TxClk <= Clk2xv; + TxClkEnable <= not Clkv; + else + -- run Encoder at normal speed, with all clocks enabled + TxClk <= Clkv; + TxClkEnable <= '1'; + end if; + + end process MakeClk; + +------------------------------------------------------------------------------- +-- Make async, active high Reset signal +------------------------------------------------------------------------------- + Reset <= '1', '0' after 50 ns; + + +------------------------------------------------------------------------------- +-- PROCESS : StimulusGen, makes pseudo random bit sequence for testing. +-- DESCRIPTION: 15 bit LFSR +-- See ITU-T O.151 for details of this LFSR (this is the "official" PRBS to +-- use for 2.048Mbps testing). +------------------------------------------------------------------------------- + StimulusGen: process (Reset, Clk) + variable shiftreg : Std_logic_vector(14 downto 0) := (others => '0'); + begin + if Reset = '1' then + shiftreg := (others => '0'); + Data <= '0'; + elsif rising_edge(Clk) then + shiftreg := shiftreg(13 downto 0) & (not (shiftreg(14) xor shiftreg(13))); + + if HalfWidthOutputs then + Data <= shiftreg(1); -- compensate for earlier sampling in hdbne when run from Clk2x + else + Data <= shiftreg(0); + end if; + DataDelayed <= shiftreg(3 + EncoderType); -- for violation visualisation + DataDelayedSomeMore <= shiftreg(5 + 2 * EncoderType); -- for decoder testing + + if shiftreg = (shiftreg'range => '0') then + report "hdbn simulation finished"; + SimulationFinished <= TRUE after 10 us; + end if; + + end if; + end process StimulusGen; + + +-------------------------------------------------------------------------------- +-- optionally inject errors, to test decoder error detection +-- and optionally crossover P&N on the line +-------------------------------------------------------------------------------- + InjectErrors : if InjectError generate + InjectedError <= '0', + '1' after StartupTransient + 1 us, + '0' after StartupTransient + 1.500 us; + end generate InjectErrors; + + -- normal connection, P->P, N->N + NoSwapLines : if not SwapPandN generate + PwithErrors <= P xor InjectedError; + NwithErrors <= N; + end generate NoSwapLines; + + -- check that it still works with P and N crossed over + SwapLines : if SwapPandN generate + PwithErrors <= N xor InjectedError; + NwithErrors <= P; + end generate SwapLines; + + +------------------------------------------------------------------------------- +-- PROCESS : Checker +-- DESCRIPTION: Checks aspects of the hdb2/hdb3 encoder against the spec, +-- and checks the decoder against the encoder +------------------------------------------------------------------------------- + Checker: process (Clk) + variable RunningSum : integer := 0; + variable ZeroCount : integer := 0; + begin + if rising_edge(Clk) then + + -- Encoder P and N outputs should never be active at the same time + assert (not ((P = PulseActiveState) and (N = PulseActiveState))) + report "Simultaneous P and N Pulse Error on HDBNE output" + severity error; + + -- There should be no DC component on the line + if P = PulseActiveState then + RunningSum := RunningSum + 1; + elsif N = PulseActiveState then + RunningSum := RunningSum - 1; + end if; + + assert RunningSum < 2 and RunningSum > -2 + report "Running Sum Error on HDBNE output" + severity error; + + -- There shouldn't be too many zeros in a row at encoder output + if P = PulseActiveState or N = PulseActiveState then + ZeroCount := 0; + else + ZeroCount := ZeroCount + 1; + end if; + + assert (ZeroCount <= EncoderType) or (now < StartupTransient) + report "Long String Of Zeros on HDBNE output" + severity error; + + -- The decoder output should match the encoder input + assert ((DataDelayedSomeMore xor DataOut) = '0') or (now < StartupTransient) + report "Decoder Bit Error on HDBND output" + severity error; + + -- The decoder shouldn't detect any errors + assert (CodeError = '0') or (now < StartupTransient) + report "Decoder Code Error on HDBND output" + severity error; + + end if; + end process Checker; + + + Violation <= DataDelayed xor (P or N); -- for visualisation only + -- (only useful if HalfWidthOutputs is FALSE) + + +------------------------------------------------------------------------------- +-- Log values to a file in PSpice "PWL" format, for testing of E1 LIU, etc. +-- +-- Note: this process isn't an essential part of the test bench. +-- +-- Example spice usage: +-- +-- .PARAM PH = 2.37V ; G.703 2.048Mbps pulse height +-- .PARAM PW = 244ns ; G.703 2.048Mbps pulse width +-- +-- Vdrive 1 0 PWL +-- + TIME_SCALE_FACTOR={PW} +-- + VALUE_SCALE_FACTOR={PH} +-- + FILE hdbn.txt +-- +------------------------------------------------------------------------------- +GenLogger : if LogSpiceFile generate + + Logger : process (Clk) + FILE log_file : text open write_mode IS LogFileName; + VARIABLE l : line; + variable LineNumber : integer := 0; + variable value : integer; + variable FirstTime : boolean := TRUE; + begin + if rising_edge(Clk) then + + if FirstTime then + -- output (0, 0) as the first line in the file + write(l, '(' & integer'image(LineNumber) & ", 0)"); + writeline(log_file, l); + FirstTime := FALSE; + end if; + + if P = PulseActiveState then + value := 1; + elsif N = PulseActiveState then + value := -1; + else + value := 0; + end if; + + if value = 0 then + -- don't bother to print it (as the voltage is already 0), but do update the time! + LineNumber := LineNumber + 2; + else + -- ramp the voltage from 0 to the peak value + write(l, '(' & integer'image(LineNumber) & ".49, 0)"); + writeline(log_file, l); + write(l, '(' & integer'image(LineNumber) & ".5, " & integer'image(value) & ')'); + writeline(log_file, l); + LineNumber := LineNumber + 1; + + -- ramp the voltage from the peak value back to 0 + write(l, '(' & integer'image(LineNumber) & ".49, " & integer'image(value) & ')'); + writeline(log_file, l); + write(l, '(' & integer'image(LineNumber) & ".5, 0)"); + writeline(log_file, l); + LineNumber := LineNumber + 1; + end if; + end if; + end process Logger; + +end generate GenLogger; + + +end architecture tb; +------------------------------------------------------------------------------- +-- End of hdbn_tb.vhd +------------------------------------------------------------------------------- Index: hdbn/trunk/rtl/vhdl/hdbnd.vhd =================================================================== --- hdbn/trunk/rtl/vhdl/hdbnd.vhd (nonexistent) +++ hdbn/trunk/rtl/vhdl/hdbnd.vhd (revision 4) @@ -0,0 +1,262 @@ +------------------------------------------------------------------------------- +-- Title : hdbnd +-- Project : hdbn +------------------------------------------------------------------------------- +-- File : hdbnd.vhd +-- Author : Allan Herriman +-- Organization : Opencores +-- Created : 9 Aug 1999 +-- Platform : ? +-- Simulators : Any VHDL '87, '93 or '00 compliant simulator will work. +-- Tested with several versions of Modelsim and Simili. +-- Synthesizers : Any VHDL compliant synthesiser will work (tested with +-- Synplify Pro and Leonardo). +-- Targets : Anything (contains no target dependent features except +-- combinatorial logic and D flip flops with async +-- reset or set). +-- Dependency : None. Complementary encoder is hdb3e. +------------------------------------------------------------------------------- +-- Description : HDB3 or HDB2 (B3ZS) decoder. +-- Note: this module does not include clock recovery. +-- A separate CDR (Clock and Data Recovery) circuit must be +-- used. +-- +-- HDB3 is typically used to encode data at 2.048, 8.448 and 34.368Mb/s +-- B3ZS is typically used to encode data at 44.736Mb/s +-- These encodings are polarity insensitive, so the P and N inputs may be +-- used interchangeably (swapped). +-- +-- Reference : ITU-T G.703 +-- +------------------------------------------------------------------------------- +-- Copyright (c) notice +-- http://www.opensource.org/licenses/bsd-license.html +-- +------------------------------------------------------------------------------- +-- +-- CVS Revision History +-- +-- $Log: not supported by cvs2svn $ +-- +------------------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; + + +entity hdbnd is + generic ( + EncoderType : integer range 2 to 3 := 3; -- 3: HDB3 2: HDB2/B3ZS + PulseActiveState : std_logic := '1' -- active state of P and N inputs + ); + port ( + Reset_i : in std_logic := '0'; -- active high async reset + Clk_i : in std_logic; -- rising edge clock + ClkEnable_i : in std_logic := '1'; -- active high clock enable + P_i : in std_logic; -- +ve pulse input + N_i : in std_logic; -- -ve pulse input + Data_o : out std_logic; -- active high data output + CodeError_o : out std_logic -- active high error indicator + ); +end hdbnd; -- End entity hdbnd + + +architecture rtl of hdbnd is + + signal PinRaw : std_logic; -- registered P input + signal NinRaw : std_logic; -- registered N input + signal Pin : std_logic; -- registered P input (with polarity corrected) + signal Nin : std_logic; -- registered N input (with polarity corrected) + signal Violation : std_logic; -- pulse violation detected + signal LastPulsePolarity : std_logic; -- last pulse sense 1=P, 0=N + signal LastViolationPolarity : std_logic; -- last violation sense " + + -- shift register bits (to align data with violations, so we can delete them) + signal Q1 : std_logic; + signal Q2 : std_logic; + signal Q3 : std_logic; + + -- signals used for calculating CodeError + signal ViolationError : std_logic; -- indicates bad violation + signal ZeroCount : integer range 0 to 3; -- counts 0s in input + signal TooManyZeros : std_logic; -- indicates 4 consecutive zeros detected + signal PulseError : std_logic; -- indicates simultaneous P and N pulse + +begin + +------------------------------------------------------------------------------- +-- PROCESS : RegisterInput +-- DESCRIPTION: DFF to register P and N inputs (reduces fan-in, etc) +-- Most applications of this core will be taking inputs from +-- off-chip, so these FF will be in the I/O blocks. +-- Metastability issues: None. +-- Either (1) the external CDR provides adequate +-- timing margin (which ensures no metastability issues) +-- or (2) it doesn't provide adequate timing margin (which could happen +-- if the input cable is unplugged) and any metastable states are irrelevant, +-- as the downstream decoding logic is free of lockup states, +-- and will recover within a few clocks once the +-- CDR is providing normal input again. +------------------------------------------------------------------------------- + RegisterInput: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + PinRaw <= '0'; + NinRaw <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + PinRaw <= to_X01(P_i); + NinRaw <= to_X01(N_i); + end if; + end if; + end process RegisterInput; + + + -- Restore active low pulse inputs to active high for internal use. + Pin <= PinRaw xor (not PulseActiveState); + Nin <= NinRaw xor (not PulseActiveState); + + +------------------------------------------------------------------------------- +-- PROCESS : DecodeViolation +-- DESCRIPTION: Work out whether there has been a pulse violation, and +-- remember the sense of the last input pulse. +------------------------------------------------------------------------------- + DecodeViolation: process (Reset_i, Clk_i) + variable tmp : std_logic_vector(1 downto 0); + begin + if Reset_i = '1' then + LastPulsePolarity <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + tmp := Pin & Nin; + case tmp is + when "00" => LastPulsePolarity <= LastPulsePolarity; --hold + when "10" => LastPulsePolarity <= '1'; -- set + when "01" => LastPulsePolarity <= '0'; -- reset + when others => LastPulsePolarity <= '0'; -- don't care + end case; + end if; + end if; + end process DecodeViolation; + + Violation <= (Pin and LastPulsePolarity) or (Nin and (not LastPulsePolarity)); + + +------------------------------------------------------------------------------- +-- PROCESS : DelayData +-- DESCRIPTION: Delay the data input so that it lines up with the violation +-- signal, so we can remove the B bit (in process DecodeData). +------------------------------------------------------------------------------- + DelayData: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + Q1 <= '0'; + Q2 <= '0'; + Q3 <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + Q1 <= (Pin or Nin) and (not Violation); -- delete V bit + Q2 <= Q1; + if EncoderType = 3 then + -- HDB3, delay by 3 clocks + Q3 <= Q2; + else + -- HDB2, delay by 2 clocks + Q3 <= Q1; -- skip Q2 + end if; + end if; + end if; + end process DelayData; + + +------------------------------------------------------------------------------- +-- PROCESS : DecodeData +-- DESCRIPTION: remove B bits from data, and register output +------------------------------------------------------------------------------- + DecodeData: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + Data_o <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + Data_o <= Q3 and (not Violation); -- delete B bit + end if; + end if; + end process DecodeData; + + +------------------------------------------------------------------------------- +-- PROCESS : CountZeros +-- DESCRIPTION: count number of contiguous zeros in input (mod 3 or 4) +------------------------------------------------------------------------------- + CountZeros: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + ZeroCount <= 0; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + if (Pin or Nin) = '1' then + ZeroCount <= 0; -- have seen a 1, reset count + elsif ZeroCount >= EncoderType then + ZeroCount <= EncoderType; -- hold + else + ZeroCount <= ZeroCount + 1; -- increment + end if; + end if; + end if; + end process CountZeros; + + +------------------------------------------------------------------------------- +-- PROCESS : DecodeViolationError +-- DESCRIPTION: Remember the polarity of this violation, so that we can work +-- out whether the next violation is an error. +------------------------------------------------------------------------------- + DecodeViolationError: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + LastViolationPolarity <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + if Violation = '1' then + LastViolationPolarity <= LastPulsePolarity; + else + LastViolationPolarity <= LastViolationPolarity; -- latch + end if; + end if; + end if; + end process DecodeViolationError; + + +------------------------------------------------------------------------------- +-- The follow logic checks for various error conditions. +------------------------------------------------------------------------------- + + ViolationError <= Violation and (not (Pin xor LastViolationPolarity)); + + PulseError <= Pin and Nin; + + TooManyZeros <= (not (Pin or Nin)) when (ZeroCount = EncoderType) else '0'; + + +------------------------------------------------------------------------------- +-- PROCESS : RegisterCodeError +-- DESCRIPTION: combine all error signals and register the output +------------------------------------------------------------------------------- + RegisterCodeError: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + CodeError_o <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + CodeError_o <= ViolationError or PulseError or TooManyZeros; + end if; + end if; + end process RegisterCodeError; + + +end rtl; -- End architecture rtl; +------------------------------------------------------------------------------- +-- End of hdbnd.vhd +------------------------------------------------------------------------------- Index: hdbn/trunk/rtl/vhdl/hdbne.vhd =================================================================== --- hdbn/trunk/rtl/vhdl/hdbne.vhd (nonexistent) +++ hdbn/trunk/rtl/vhdl/hdbne.vhd (revision 4) @@ -0,0 +1,273 @@ +------------------------------------------------------------------------------- +-- Title : hdbne +-- Project : hdbn +------------------------------------------------------------------------------- +-- File : hdbne.vhd +-- Author : Allan Herriman +-- Organization : Opencores +-- Created : 9 Aug 1999 +-- Platform : ? +-- Simulators : Any VHDL '87, '93 or '00 compliant simulator will work. +-- Tested with several versions of Modelsim and Simili. +-- Synthesizers : Any VHDL compliant synthesiser will work (tested with +-- Synplify Pro and Leonardo). +-- Targets : Anything (contains no target dependent features except +-- combinatorial logic and D flip flops with async +-- reset or set). +-- Dependency : None. Complementary decoder is hdb3d. +------------------------------------------------------------------------------- +-- Description : HDB3 or HDB2 (B3ZS) encoder. +-- P and N outputs are full width by default. +-- Half width pulses can be created by using a double rate clock and +-- strobing ClkEnable and OutputEnable appropriately (high every second clock). +-- +-- HDB3 is typically used to encode data at 2.048, 8.448 and 34.368Mb/s +-- B3ZS is typically used to encode data at 44.736Mb/s +-- The outputs will require pulse shaping if used to drive the line. +-- These encodings are polarity insensitive, so the P and N outputs may be +-- used interchangeably (swapped). +-- +-- Reference : ITU-T G.703 +-- +------------------------------------------------------------------------------- +-- Copyright (c) notice +-- http://www.opensource.org/licenses/bsd-license.html +-- +------------------------------------------------------------------------------- +-- +-- CVS Revision History +-- +-- $Log: not supported by cvs2svn $ +-- +------------------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; + + +entity hdbne is + generic ( + EncoderType : integer range 2 to 3 := 3; -- 3: HDB3 2: HDB2/B3ZS + PulseActiveState : std_logic := '1' -- active state of P and N outputs + ); + port ( + Reset_i : in std_logic := '0'; -- active high async reset + Clk_i : in std_logic; -- rising edge clock + ClkEnable_i : in std_logic := '1'; -- active high clock enable + Data_i : in std_logic; -- active high data input + OutputGate_i : in std_logic := '1'; -- '0' forces P and N to not PulseActiveState (synchronously, but ignoring ClkEnable) + P_o : out std_logic; -- encoded +ve pulse output + N_o : out std_logic -- encoded -ve pulse output + ); +end hdbne; -- End entity hdbne + + +architecture rtl of hdbne is + + signal Q1 : std_logic; -- Q1 through Q5 form a shift + signal Q2 : std_logic; -- register for aligning + signal Q3 : std_logic; -- the data so we can insert + signal Q4 : std_logic; -- the violations + signal Q5 : std_logic; + + signal AMI : std_logic; -- sense of pulse (P or N) + signal ViolationType : std_logic; -- sense of violation + signal ZeroCount : integer range 0 to 3; -- counts 0s in input + signal ZeroString : std_logic; -- goes to '1' when 3 or 4 0s seen + signal ZeroStringDelayed : std_logic; -- above delayed by 1 clock + +begin + +------------------------------------------------------------------------------- +-- PROCESS : RegisterInput +-- DESCRIPTION: DFF (Q1) to register input data (reduces fan-in, etc) +------------------------------------------------------------------------------- + RegisterInput: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + Q1 <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + Q1 <= to_X01(Data_i); + end if; + end if; + end process RegisterInput; + + +------------------------------------------------------------------------------- +-- PROCESS : CountZeros +-- DESCRIPTION: count number of contiguous zeros in input (mod 4 or mod 3) +------------------------------------------------------------------------------- + CountZeros: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + ZeroCount <= 0; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + if Q1 = '1' then + ZeroCount <= 0; -- have seen a 1, reset count + elsif ZeroCount >= EncoderType then + ZeroCount <= 0; -- increment modulo 3 or 4 + else + ZeroCount <= ZeroCount + 1; -- increment + end if; + end if; + end if; + end process CountZeros; + + +------------------------------------------------------------------------------- +-- PROCESS : DecodeCount (combinatorial) +-- DESCRIPTION: decode ZeroCount to indicate when string of 3 or 4 zeros is present +-- Note: this process is not clocked +------------------------------------------------------------------------------- + DecodeCount: process (Q1, ZeroCount) + begin + if ZeroCount = EncoderType and Q1 = '0' then + ZeroString <= '1'; + else + ZeroString <= '0'; + end if; + end process DecodeCount; + + +------------------------------------------------------------------------------- +-- PROCESS : RegisterZeroString +-- DESCRIPTION: DFF to register the ZeroString signal +------------------------------------------------------------------------------- + RegisterZeroString: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + ZeroStringDelayed <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + ZeroStringDelayed <= ZeroString; + end if; + end if; + end process RegisterZeroString; + + +------------------------------------------------------------------------------- +-- PROCESS : DelayData +-- DESCRIPTION: insert 1 if needed for violation, and delay data by 2 or 3 clocks +-- to line up with ZeroString detection. +------------------------------------------------------------------------------- + DelayData: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + Q2 <= '0'; + Q3 <= '0'; + Q4 <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + Q2 <= Q1 or ZeroString; -- insert Violation bit + Q3 <= Q2; + if EncoderType = 3 then + -- HDB3, delay by 3 clocks + Q4 <= Q3; + else + -- HDB2, delay by 2 clocks + Q4 <= Q2; -- skip Q3 + end if; + end if; + end if; + end process DelayData; + + +------------------------------------------------------------------------------- +-- PROCESS : InsertBBit +-- DESCRIPTION: Delay Q4 by one clock, and insert B bit if needed. +------------------------------------------------------------------------------- + InsertBBit: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + Q5 <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + Q5 <= Q4 or (ZeroString and (not ViolationType)); + end if; + end if; + end process InsertBBit; + + +------------------------------------------------------------------------------- +-- PROCESS : ToggleViolationType +-- DESCRIPTION: Toggle ViolationType whenever Q5 is 1 +------------------------------------------------------------------------------- + ToggleViolationType: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + ViolationType <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + ViolationType <= ViolationType xor Q5; + end if; + end if; + end process ToggleViolationType; + + +------------------------------------------------------------------------------- +-- PROCESS : AMIFlipFlop +-- DESCRIPTION: toggle AMI to alternate P and N pulses. Force a violation (no +-- toggle) occasionally. +------------------------------------------------------------------------------- + AMIFlipFlop: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + AMI <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + AMI <= AMI xor (Q5 and (ViolationType nand (ZeroString or ZeroStringDelayed))); + end if; + end if; + end process AMIFlipFlop; + + +------------------------------------------------------------------------------- +-- PROCESS : MakePandNPulses +-- DESCRIPTION: Gate Q5 with AMI to produce the P and N outputs +-- Note that OutputEnable overrides ClkEnable, to allow creation of +-- half width pulses. +-- The flip flops P and N will drive the outputs to the LIU, and these +-- flip flops should be in the IOBs in an FPGA. Clk to output delay +-- should be matched for P and N to avoid pulse shape distortion at the LIU +-- output. +------------------------------------------------------------------------------- + MakePandNPulses: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + P_o <= not PulseActiveState; + N_o <= not PulseActiveState; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' or OutputGate_i /= '1' then + if OutputGate_i /= '1' then + -- force output to '0' + P_o <= not PulseActiveState; + N_o <= not PulseActiveState; + else + -- normal operation + if Q5 = '1' then + if AMI = '1' then + -- output '1' on P + P_o <= PulseActiveState; + N_o <= not PulseActiveState; + else + -- output '1' on N + P_o <= not PulseActiveState; + N_o <= PulseActiveState; + end if; + else + -- output '0' + P_o <= not PulseActiveState; + N_o <= not PulseActiveState; + end if; + end if; + end if; + end if; + end process MakePandNPulses; + + +end rtl; -- End architecture rtl; +------------------------------------------------------------------------------- +-- End of hdbne.vhd +------------------------------------------------------------------------------- Index: hdbn/trunk/doc/hdbn.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: hdbn/trunk/doc/hdbn.pdf =================================================================== --- hdbn/trunk/doc/hdbn.pdf (nonexistent) +++ hdbn/trunk/doc/hdbn.pdf (revision 4)
hdbn/trunk/doc/hdbn.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: hdbn/trunk/doc/src/hdbn.doc =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: hdbn/trunk/doc/src/hdbn.doc =================================================================== --- hdbn/trunk/doc/src/hdbn.doc (nonexistent) +++ hdbn/trunk/doc/src/hdbn.doc (revision 4)
hdbn/trunk/doc/src/hdbn.doc Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: hdbn/trunk =================================================================== --- hdbn/trunk (nonexistent) +++ hdbn/trunk (revision 4)
hdbn/trunk Property changes : Added: svn:mergeinfo ## -0,0 +0,0 ## Index: hdbn/web_uploads =================================================================== --- hdbn/web_uploads (nonexistent) +++ hdbn/web_uploads (revision 4)
hdbn/web_uploads Property changes : Added: svn:mergeinfo ## -0,0 +0,0 ## Index: hdbn/branches =================================================================== --- hdbn/branches (nonexistent) +++ hdbn/branches (revision 4)
hdbn/branches Property changes : Added: svn:mergeinfo ## -0,0 +0,0 ## Index: hdbn/tags/arelease/bench/vhdl/hdbn_tb.vhd =================================================================== --- hdbn/tags/arelease/bench/vhdl/hdbn_tb.vhd (nonexistent) +++ hdbn/tags/arelease/bench/vhdl/hdbn_tb.vhd (revision 4) @@ -0,0 +1,341 @@ +------------------------------------------------------------------------------- +-- Title : hdbn_tb +-- Project : hdbn +------------------------------------------------------------------------------- +-- File : hdbn_tb.vhd +-- Author : Allan Herriman +-- Organization : Opencores +-- Created : 9 Aug 1999 +-- Platform : ? +-- Simulators : Should work in any VHDL '93 or '00 compliant simulator. +-- (Strict '87 compliant simulators will not work, as some +-- '93 features have been used.) +-- Tested with several versions of Modelsim and Simili. +-- Most recently tested with Modelsim PE 5.6d and Simili 2.1b10 +-- on Windows 2000 +-- Synthesizers : N/A (this is a testbench) +-- Targets : N/A (this is a testbench) +-- Dependency : entities hdbne and hdbnd +------------------------------------------------------------------------------- +-- Description : testbench for entities hdbne and hdbnd. +-- This is an "assertion based" test. If it runs to +-- completion (about 16ms) without errors, it has passed. +-- +-- Reference : ITU-T G.703 +-- +------------------------------------------------------------------------------- +-- Copyright (c) notice +-- http://www.opensource.org/licenses/bsd-license.html +-- +------------------------------------------------------------------------------- +-- +-- CVS Revision History +-- +-- $Log: not supported by cvs2svn $ +-- +------------------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; + +use std.textio.all; + + +entity hdbn_tb is + generic ( + HalfWidthOutputs : boolean := FALSE; -- set TRUE to use 2x clock on encoder + InjectError : boolean := FALSE; -- set TRUE to test decoder error detection + SwapPandN : boolean := FALSE; -- set TRUE to swap P,N signals between enc and dec + EncoderType : integer range 2 to 3 := 3; -- 3: HDB3 2: HDB2/B3ZS + PulseActiveState : std_logic := '1'; -- active state of P and N signals + LogSpiceFile : boolean := FALSE; -- set TRUE to log encoder output in Spice PWL format + LogFileName : string := "hdbn.txt"; + StartupTransient : time := 15 us -- disables assertions for this long + ); +end hdbn_tb; -- End entity hdbn_tb + + +architecture tb of hdbn_tb is + + signal Reset : std_logic := '1'; + signal Clk : std_logic := '0'; + signal TxClk : std_logic := '0'; + signal TxClkEnable : std_logic; + signal Data : std_logic; -- encoder input (stimulus) + signal DataOut : std_logic; -- decoder output + signal CodeError : std_logic; + signal P : std_logic; + signal N : std_logic; + + signal PwithErrors : std_logic; + signal NwithErrors : std_logic; + + signal InjectedError : std_logic := '0'; + + signal DataDelayed : std_logic; -- Matches delay of encoder + signal DataDelayedSomeMore : std_logic; -- Matches delay of encoder and decoder + signal Violation : std_logic; + + signal SimulationFinished : boolean := FALSE; + +begin + + +------------------------------------------------------------------------------- +-- Instantiation of entity 'hdbne' - hdbn encoder under test +------------------------------------------------------------------------------- + eUT : entity work.hdbne + generic map ( + EncoderType => EncoderType, + PulseActiveState => PulseActiveState + ) + port map ( + Reset_i => Reset, + Clk_i => TxClk, + ClkEnable_i => TxClkEnable, + Data_i => Data, + OutputGate_i => TxClkEnable, + P_o => P, + N_o => N + ); + + +------------------------------------------------------------------------------- +-- Instantiation of entity 'hdbnd' - hdbn decoder under test +------------------------------------------------------------------------------- + dUT : entity work.hdbnd + generic map ( + EncoderType => EncoderType, + PulseActiveState => PulseActiveState + ) + port map ( + Reset_i => Reset, + Clk_i => Clk, + ClkEnable_i => '1', + P_i => PwithErrors, + N_i => NwithErrors, + Data_o => DataOut, + CodeError_o => CodeError + ); + + +------------------------------------------------------------------------------- +-- make two clocks, 4.096MHz and 2.048MHz. +-- Use HalfWidthOutputs to select which one is used for encoder +-- Note: care must be taken to balance delta delays, otherwise races between +-- the clocks may cause unpredictable results. +------------------------------------------------------------------------------- + MakeClk: process + variable Clkv : std_logic := '0'; + variable Clk2xv : std_logic := '0'; + begin + wait for 122 ns; + if SimulationFinished then + wait until not SimulationFinished; + end if; + Clk2xv := not Clk2xv; + if Clk2xv = '1' then + Clkv := not Clkv; + end if; + + -- assign to signals, all in the same delta cycle + Clk <= Clkv; + if HalfWidthOutputs then + -- run Encoder twice as fast, with every 2nd clock enabled + TxClk <= Clk2xv; + TxClkEnable <= not Clkv; + else + -- run Encoder at normal speed, with all clocks enabled + TxClk <= Clkv; + TxClkEnable <= '1'; + end if; + + end process MakeClk; + +------------------------------------------------------------------------------- +-- Make async, active high Reset signal +------------------------------------------------------------------------------- + Reset <= '1', '0' after 50 ns; + + +------------------------------------------------------------------------------- +-- PROCESS : StimulusGen, makes pseudo random bit sequence for testing. +-- DESCRIPTION: 15 bit LFSR +-- See ITU-T O.151 for details of this LFSR (this is the "official" PRBS to +-- use for 2.048Mbps testing). +------------------------------------------------------------------------------- + StimulusGen: process (Reset, Clk) + variable shiftreg : Std_logic_vector(14 downto 0) := (others => '0'); + begin + if Reset = '1' then + shiftreg := (others => '0'); + Data <= '0'; + elsif rising_edge(Clk) then + shiftreg := shiftreg(13 downto 0) & (not (shiftreg(14) xor shiftreg(13))); + + if HalfWidthOutputs then + Data <= shiftreg(1); -- compensate for earlier sampling in hdbne when run from Clk2x + else + Data <= shiftreg(0); + end if; + DataDelayed <= shiftreg(3 + EncoderType); -- for violation visualisation + DataDelayedSomeMore <= shiftreg(5 + 2 * EncoderType); -- for decoder testing + + if shiftreg = (shiftreg'range => '0') then + report "hdbn simulation finished"; + SimulationFinished <= TRUE after 10 us; + end if; + + end if; + end process StimulusGen; + + +-------------------------------------------------------------------------------- +-- optionally inject errors, to test decoder error detection +-- and optionally crossover P&N on the line +-------------------------------------------------------------------------------- + InjectErrors : if InjectError generate + InjectedError <= '0', + '1' after StartupTransient + 1 us, + '0' after StartupTransient + 1.500 us; + end generate InjectErrors; + + -- normal connection, P->P, N->N + NoSwapLines : if not SwapPandN generate + PwithErrors <= P xor InjectedError; + NwithErrors <= N; + end generate NoSwapLines; + + -- check that it still works with P and N crossed over + SwapLines : if SwapPandN generate + PwithErrors <= N xor InjectedError; + NwithErrors <= P; + end generate SwapLines; + + +------------------------------------------------------------------------------- +-- PROCESS : Checker +-- DESCRIPTION: Checks aspects of the hdb2/hdb3 encoder against the spec, +-- and checks the decoder against the encoder +------------------------------------------------------------------------------- + Checker: process (Clk) + variable RunningSum : integer := 0; + variable ZeroCount : integer := 0; + begin + if rising_edge(Clk) then + + -- Encoder P and N outputs should never be active at the same time + assert (not ((P = PulseActiveState) and (N = PulseActiveState))) + report "Simultaneous P and N Pulse Error on HDBNE output" + severity error; + + -- There should be no DC component on the line + if P = PulseActiveState then + RunningSum := RunningSum + 1; + elsif N = PulseActiveState then + RunningSum := RunningSum - 1; + end if; + + assert RunningSum < 2 and RunningSum > -2 + report "Running Sum Error on HDBNE output" + severity error; + + -- There shouldn't be too many zeros in a row at encoder output + if P = PulseActiveState or N = PulseActiveState then + ZeroCount := 0; + else + ZeroCount := ZeroCount + 1; + end if; + + assert (ZeroCount <= EncoderType) or (now < StartupTransient) + report "Long String Of Zeros on HDBNE output" + severity error; + + -- The decoder output should match the encoder input + assert ((DataDelayedSomeMore xor DataOut) = '0') or (now < StartupTransient) + report "Decoder Bit Error on HDBND output" + severity error; + + -- The decoder shouldn't detect any errors + assert (CodeError = '0') or (now < StartupTransient) + report "Decoder Code Error on HDBND output" + severity error; + + end if; + end process Checker; + + + Violation <= DataDelayed xor (P or N); -- for visualisation only + -- (only useful if HalfWidthOutputs is FALSE) + + +------------------------------------------------------------------------------- +-- Log values to a file in PSpice "PWL" format, for testing of E1 LIU, etc. +-- +-- Note: this process isn't an essential part of the test bench. +-- +-- Example spice usage: +-- +-- .PARAM PH = 2.37V ; G.703 2.048Mbps pulse height +-- .PARAM PW = 244ns ; G.703 2.048Mbps pulse width +-- +-- Vdrive 1 0 PWL +-- + TIME_SCALE_FACTOR={PW} +-- + VALUE_SCALE_FACTOR={PH} +-- + FILE hdbn.txt +-- +------------------------------------------------------------------------------- +GenLogger : if LogSpiceFile generate + + Logger : process (Clk) + FILE log_file : text open write_mode IS LogFileName; + VARIABLE l : line; + variable LineNumber : integer := 0; + variable value : integer; + variable FirstTime : boolean := TRUE; + begin + if rising_edge(Clk) then + + if FirstTime then + -- output (0, 0) as the first line in the file + write(l, '(' & integer'image(LineNumber) & ", 0)"); + writeline(log_file, l); + FirstTime := FALSE; + end if; + + if P = PulseActiveState then + value := 1; + elsif N = PulseActiveState then + value := -1; + else + value := 0; + end if; + + if value = 0 then + -- don't bother to print it (as the voltage is already 0), but do update the time! + LineNumber := LineNumber + 2; + else + -- ramp the voltage from 0 to the peak value + write(l, '(' & integer'image(LineNumber) & ".49, 0)"); + writeline(log_file, l); + write(l, '(' & integer'image(LineNumber) & ".5, " & integer'image(value) & ')'); + writeline(log_file, l); + LineNumber := LineNumber + 1; + + -- ramp the voltage from the peak value back to 0 + write(l, '(' & integer'image(LineNumber) & ".49, " & integer'image(value) & ')'); + writeline(log_file, l); + write(l, '(' & integer'image(LineNumber) & ".5, 0)"); + writeline(log_file, l); + LineNumber := LineNumber + 1; + end if; + end if; + end process Logger; + +end generate GenLogger; + + +end architecture tb; +------------------------------------------------------------------------------- +-- End of hdbn_tb.vhd +------------------------------------------------------------------------------- Index: hdbn/tags/arelease/rtl/vhdl/hdbnd.vhd =================================================================== --- hdbn/tags/arelease/rtl/vhdl/hdbnd.vhd (nonexistent) +++ hdbn/tags/arelease/rtl/vhdl/hdbnd.vhd (revision 4) @@ -0,0 +1,262 @@ +------------------------------------------------------------------------------- +-- Title : hdbnd +-- Project : hdbn +------------------------------------------------------------------------------- +-- File : hdbnd.vhd +-- Author : Allan Herriman +-- Organization : Opencores +-- Created : 9 Aug 1999 +-- Platform : ? +-- Simulators : Any VHDL '87, '93 or '00 compliant simulator will work. +-- Tested with several versions of Modelsim and Simili. +-- Synthesizers : Any VHDL compliant synthesiser will work (tested with +-- Synplify Pro and Leonardo). +-- Targets : Anything (contains no target dependent features except +-- combinatorial logic and D flip flops with async +-- reset or set). +-- Dependency : None. Complementary encoder is hdb3e. +------------------------------------------------------------------------------- +-- Description : HDB3 or HDB2 (B3ZS) decoder. +-- Note: this module does not include clock recovery. +-- A separate CDR (Clock and Data Recovery) circuit must be +-- used. +-- +-- HDB3 is typically used to encode data at 2.048, 8.448 and 34.368Mb/s +-- B3ZS is typically used to encode data at 44.736Mb/s +-- These encodings are polarity insensitive, so the P and N inputs may be +-- used interchangeably (swapped). +-- +-- Reference : ITU-T G.703 +-- +------------------------------------------------------------------------------- +-- Copyright (c) notice +-- http://www.opensource.org/licenses/bsd-license.html +-- +------------------------------------------------------------------------------- +-- +-- CVS Revision History +-- +-- $Log: not supported by cvs2svn $ +-- +------------------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; + + +entity hdbnd is + generic ( + EncoderType : integer range 2 to 3 := 3; -- 3: HDB3 2: HDB2/B3ZS + PulseActiveState : std_logic := '1' -- active state of P and N inputs + ); + port ( + Reset_i : in std_logic := '0'; -- active high async reset + Clk_i : in std_logic; -- rising edge clock + ClkEnable_i : in std_logic := '1'; -- active high clock enable + P_i : in std_logic; -- +ve pulse input + N_i : in std_logic; -- -ve pulse input + Data_o : out std_logic; -- active high data output + CodeError_o : out std_logic -- active high error indicator + ); +end hdbnd; -- End entity hdbnd + + +architecture rtl of hdbnd is + + signal PinRaw : std_logic; -- registered P input + signal NinRaw : std_logic; -- registered N input + signal Pin : std_logic; -- registered P input (with polarity corrected) + signal Nin : std_logic; -- registered N input (with polarity corrected) + signal Violation : std_logic; -- pulse violation detected + signal LastPulsePolarity : std_logic; -- last pulse sense 1=P, 0=N + signal LastViolationPolarity : std_logic; -- last violation sense " + + -- shift register bits (to align data with violations, so we can delete them) + signal Q1 : std_logic; + signal Q2 : std_logic; + signal Q3 : std_logic; + + -- signals used for calculating CodeError + signal ViolationError : std_logic; -- indicates bad violation + signal ZeroCount : integer range 0 to 3; -- counts 0s in input + signal TooManyZeros : std_logic; -- indicates 4 consecutive zeros detected + signal PulseError : std_logic; -- indicates simultaneous P and N pulse + +begin + +------------------------------------------------------------------------------- +-- PROCESS : RegisterInput +-- DESCRIPTION: DFF to register P and N inputs (reduces fan-in, etc) +-- Most applications of this core will be taking inputs from +-- off-chip, so these FF will be in the I/O blocks. +-- Metastability issues: None. +-- Either (1) the external CDR provides adequate +-- timing margin (which ensures no metastability issues) +-- or (2) it doesn't provide adequate timing margin (which could happen +-- if the input cable is unplugged) and any metastable states are irrelevant, +-- as the downstream decoding logic is free of lockup states, +-- and will recover within a few clocks once the +-- CDR is providing normal input again. +------------------------------------------------------------------------------- + RegisterInput: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + PinRaw <= '0'; + NinRaw <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + PinRaw <= to_X01(P_i); + NinRaw <= to_X01(N_i); + end if; + end if; + end process RegisterInput; + + + -- Restore active low pulse inputs to active high for internal use. + Pin <= PinRaw xor (not PulseActiveState); + Nin <= NinRaw xor (not PulseActiveState); + + +------------------------------------------------------------------------------- +-- PROCESS : DecodeViolation +-- DESCRIPTION: Work out whether there has been a pulse violation, and +-- remember the sense of the last input pulse. +------------------------------------------------------------------------------- + DecodeViolation: process (Reset_i, Clk_i) + variable tmp : std_logic_vector(1 downto 0); + begin + if Reset_i = '1' then + LastPulsePolarity <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + tmp := Pin & Nin; + case tmp is + when "00" => LastPulsePolarity <= LastPulsePolarity; --hold + when "10" => LastPulsePolarity <= '1'; -- set + when "01" => LastPulsePolarity <= '0'; -- reset + when others => LastPulsePolarity <= '0'; -- don't care + end case; + end if; + end if; + end process DecodeViolation; + + Violation <= (Pin and LastPulsePolarity) or (Nin and (not LastPulsePolarity)); + + +------------------------------------------------------------------------------- +-- PROCESS : DelayData +-- DESCRIPTION: Delay the data input so that it lines up with the violation +-- signal, so we can remove the B bit (in process DecodeData). +------------------------------------------------------------------------------- + DelayData: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + Q1 <= '0'; + Q2 <= '0'; + Q3 <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + Q1 <= (Pin or Nin) and (not Violation); -- delete V bit + Q2 <= Q1; + if EncoderType = 3 then + -- HDB3, delay by 3 clocks + Q3 <= Q2; + else + -- HDB2, delay by 2 clocks + Q3 <= Q1; -- skip Q2 + end if; + end if; + end if; + end process DelayData; + + +------------------------------------------------------------------------------- +-- PROCESS : DecodeData +-- DESCRIPTION: remove B bits from data, and register output +------------------------------------------------------------------------------- + DecodeData: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + Data_o <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + Data_o <= Q3 and (not Violation); -- delete B bit + end if; + end if; + end process DecodeData; + + +------------------------------------------------------------------------------- +-- PROCESS : CountZeros +-- DESCRIPTION: count number of contiguous zeros in input (mod 3 or 4) +------------------------------------------------------------------------------- + CountZeros: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + ZeroCount <= 0; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + if (Pin or Nin) = '1' then + ZeroCount <= 0; -- have seen a 1, reset count + elsif ZeroCount >= EncoderType then + ZeroCount <= EncoderType; -- hold + else + ZeroCount <= ZeroCount + 1; -- increment + end if; + end if; + end if; + end process CountZeros; + + +------------------------------------------------------------------------------- +-- PROCESS : DecodeViolationError +-- DESCRIPTION: Remember the polarity of this violation, so that we can work +-- out whether the next violation is an error. +------------------------------------------------------------------------------- + DecodeViolationError: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + LastViolationPolarity <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + if Violation = '1' then + LastViolationPolarity <= LastPulsePolarity; + else + LastViolationPolarity <= LastViolationPolarity; -- latch + end if; + end if; + end if; + end process DecodeViolationError; + + +------------------------------------------------------------------------------- +-- The follow logic checks for various error conditions. +------------------------------------------------------------------------------- + + ViolationError <= Violation and (not (Pin xor LastViolationPolarity)); + + PulseError <= Pin and Nin; + + TooManyZeros <= (not (Pin or Nin)) when (ZeroCount = EncoderType) else '0'; + + +------------------------------------------------------------------------------- +-- PROCESS : RegisterCodeError +-- DESCRIPTION: combine all error signals and register the output +------------------------------------------------------------------------------- + RegisterCodeError: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + CodeError_o <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + CodeError_o <= ViolationError or PulseError or TooManyZeros; + end if; + end if; + end process RegisterCodeError; + + +end rtl; -- End architecture rtl; +------------------------------------------------------------------------------- +-- End of hdbnd.vhd +------------------------------------------------------------------------------- Index: hdbn/tags/arelease/rtl/vhdl/hdbne.vhd =================================================================== --- hdbn/tags/arelease/rtl/vhdl/hdbne.vhd (nonexistent) +++ hdbn/tags/arelease/rtl/vhdl/hdbne.vhd (revision 4) @@ -0,0 +1,273 @@ +------------------------------------------------------------------------------- +-- Title : hdbne +-- Project : hdbn +------------------------------------------------------------------------------- +-- File : hdbne.vhd +-- Author : Allan Herriman +-- Organization : Opencores +-- Created : 9 Aug 1999 +-- Platform : ? +-- Simulators : Any VHDL '87, '93 or '00 compliant simulator will work. +-- Tested with several versions of Modelsim and Simili. +-- Synthesizers : Any VHDL compliant synthesiser will work (tested with +-- Synplify Pro and Leonardo). +-- Targets : Anything (contains no target dependent features except +-- combinatorial logic and D flip flops with async +-- reset or set). +-- Dependency : None. Complementary decoder is hdb3d. +------------------------------------------------------------------------------- +-- Description : HDB3 or HDB2 (B3ZS) encoder. +-- P and N outputs are full width by default. +-- Half width pulses can be created by using a double rate clock and +-- strobing ClkEnable and OutputEnable appropriately (high every second clock). +-- +-- HDB3 is typically used to encode data at 2.048, 8.448 and 34.368Mb/s +-- B3ZS is typically used to encode data at 44.736Mb/s +-- The outputs will require pulse shaping if used to drive the line. +-- These encodings are polarity insensitive, so the P and N outputs may be +-- used interchangeably (swapped). +-- +-- Reference : ITU-T G.703 +-- +------------------------------------------------------------------------------- +-- Copyright (c) notice +-- http://www.opensource.org/licenses/bsd-license.html +-- +------------------------------------------------------------------------------- +-- +-- CVS Revision History +-- +-- $Log: not supported by cvs2svn $ +-- +------------------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; + + +entity hdbne is + generic ( + EncoderType : integer range 2 to 3 := 3; -- 3: HDB3 2: HDB2/B3ZS + PulseActiveState : std_logic := '1' -- active state of P and N outputs + ); + port ( + Reset_i : in std_logic := '0'; -- active high async reset + Clk_i : in std_logic; -- rising edge clock + ClkEnable_i : in std_logic := '1'; -- active high clock enable + Data_i : in std_logic; -- active high data input + OutputGate_i : in std_logic := '1'; -- '0' forces P and N to not PulseActiveState (synchronously, but ignoring ClkEnable) + P_o : out std_logic; -- encoded +ve pulse output + N_o : out std_logic -- encoded -ve pulse output + ); +end hdbne; -- End entity hdbne + + +architecture rtl of hdbne is + + signal Q1 : std_logic; -- Q1 through Q5 form a shift + signal Q2 : std_logic; -- register for aligning + signal Q3 : std_logic; -- the data so we can insert + signal Q4 : std_logic; -- the violations + signal Q5 : std_logic; + + signal AMI : std_logic; -- sense of pulse (P or N) + signal ViolationType : std_logic; -- sense of violation + signal ZeroCount : integer range 0 to 3; -- counts 0s in input + signal ZeroString : std_logic; -- goes to '1' when 3 or 4 0s seen + signal ZeroStringDelayed : std_logic; -- above delayed by 1 clock + +begin + +------------------------------------------------------------------------------- +-- PROCESS : RegisterInput +-- DESCRIPTION: DFF (Q1) to register input data (reduces fan-in, etc) +------------------------------------------------------------------------------- + RegisterInput: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + Q1 <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + Q1 <= to_X01(Data_i); + end if; + end if; + end process RegisterInput; + + +------------------------------------------------------------------------------- +-- PROCESS : CountZeros +-- DESCRIPTION: count number of contiguous zeros in input (mod 4 or mod 3) +------------------------------------------------------------------------------- + CountZeros: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + ZeroCount <= 0; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + if Q1 = '1' then + ZeroCount <= 0; -- have seen a 1, reset count + elsif ZeroCount >= EncoderType then + ZeroCount <= 0; -- increment modulo 3 or 4 + else + ZeroCount <= ZeroCount + 1; -- increment + end if; + end if; + end if; + end process CountZeros; + + +------------------------------------------------------------------------------- +-- PROCESS : DecodeCount (combinatorial) +-- DESCRIPTION: decode ZeroCount to indicate when string of 3 or 4 zeros is present +-- Note: this process is not clocked +------------------------------------------------------------------------------- + DecodeCount: process (Q1, ZeroCount) + begin + if ZeroCount = EncoderType and Q1 = '0' then + ZeroString <= '1'; + else + ZeroString <= '0'; + end if; + end process DecodeCount; + + +------------------------------------------------------------------------------- +-- PROCESS : RegisterZeroString +-- DESCRIPTION: DFF to register the ZeroString signal +------------------------------------------------------------------------------- + RegisterZeroString: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + ZeroStringDelayed <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + ZeroStringDelayed <= ZeroString; + end if; + end if; + end process RegisterZeroString; + + +------------------------------------------------------------------------------- +-- PROCESS : DelayData +-- DESCRIPTION: insert 1 if needed for violation, and delay data by 2 or 3 clocks +-- to line up with ZeroString detection. +------------------------------------------------------------------------------- + DelayData: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + Q2 <= '0'; + Q3 <= '0'; + Q4 <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + Q2 <= Q1 or ZeroString; -- insert Violation bit + Q3 <= Q2; + if EncoderType = 3 then + -- HDB3, delay by 3 clocks + Q4 <= Q3; + else + -- HDB2, delay by 2 clocks + Q4 <= Q2; -- skip Q3 + end if; + end if; + end if; + end process DelayData; + + +------------------------------------------------------------------------------- +-- PROCESS : InsertBBit +-- DESCRIPTION: Delay Q4 by one clock, and insert B bit if needed. +------------------------------------------------------------------------------- + InsertBBit: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + Q5 <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + Q5 <= Q4 or (ZeroString and (not ViolationType)); + end if; + end if; + end process InsertBBit; + + +------------------------------------------------------------------------------- +-- PROCESS : ToggleViolationType +-- DESCRIPTION: Toggle ViolationType whenever Q5 is 1 +------------------------------------------------------------------------------- + ToggleViolationType: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + ViolationType <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + ViolationType <= ViolationType xor Q5; + end if; + end if; + end process ToggleViolationType; + + +------------------------------------------------------------------------------- +-- PROCESS : AMIFlipFlop +-- DESCRIPTION: toggle AMI to alternate P and N pulses. Force a violation (no +-- toggle) occasionally. +------------------------------------------------------------------------------- + AMIFlipFlop: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + AMI <= '0'; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' then + AMI <= AMI xor (Q5 and (ViolationType nand (ZeroString or ZeroStringDelayed))); + end if; + end if; + end process AMIFlipFlop; + + +------------------------------------------------------------------------------- +-- PROCESS : MakePandNPulses +-- DESCRIPTION: Gate Q5 with AMI to produce the P and N outputs +-- Note that OutputEnable overrides ClkEnable, to allow creation of +-- half width pulses. +-- The flip flops P and N will drive the outputs to the LIU, and these +-- flip flops should be in the IOBs in an FPGA. Clk to output delay +-- should be matched for P and N to avoid pulse shape distortion at the LIU +-- output. +------------------------------------------------------------------------------- + MakePandNPulses: process (Reset_i, Clk_i) + begin + if Reset_i = '1' then + P_o <= not PulseActiveState; + N_o <= not PulseActiveState; + elsif rising_edge(Clk_i) then + if ClkEnable_i = '1' or OutputGate_i /= '1' then + if OutputGate_i /= '1' then + -- force output to '0' + P_o <= not PulseActiveState; + N_o <= not PulseActiveState; + else + -- normal operation + if Q5 = '1' then + if AMI = '1' then + -- output '1' on P + P_o <= PulseActiveState; + N_o <= not PulseActiveState; + else + -- output '1' on N + P_o <= not PulseActiveState; + N_o <= PulseActiveState; + end if; + else + -- output '0' + P_o <= not PulseActiveState; + N_o <= not PulseActiveState; + end if; + end if; + end if; + end if; + end process MakePandNPulses; + + +end rtl; -- End architecture rtl; +------------------------------------------------------------------------------- +-- End of hdbne.vhd +------------------------------------------------------------------------------- Index: hdbn/tags/arelease/doc/hdbn.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: hdbn/tags/arelease/doc/hdbn.pdf =================================================================== --- hdbn/tags/arelease/doc/hdbn.pdf (nonexistent) +++ hdbn/tags/arelease/doc/hdbn.pdf (revision 4)
hdbn/tags/arelease/doc/hdbn.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: hdbn/tags/arelease/doc/src/hdbn.doc =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: hdbn/tags/arelease/doc/src/hdbn.doc =================================================================== --- hdbn/tags/arelease/doc/src/hdbn.doc (nonexistent) +++ hdbn/tags/arelease/doc/src/hdbn.doc (revision 4)
hdbn/tags/arelease/doc/src/hdbn.doc Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: hdbn/tags =================================================================== --- hdbn/tags (nonexistent) +++ hdbn/tags (revision 4)
hdbn/tags Property changes : Added: svn:mergeinfo ## -0,0 +0,0 ##

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.