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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [VHDL/] [o8_vector_rx.vhd] - Diff between revs 285 and 296

Show entire file | Details | Blame | View Log

Rev 285 Rev 296
Line 1... Line 1...
-- Copyright (c)2020 Jeremy Seth Henry
-- Copyright (c)2021 Jeremy Seth Henry
-- All rights reserved.
-- All rights reserved.
--
--
-- Redistribution and use in source and binary forms, with or without
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
-- modification, are permitted provided that the following conditions are met:
--     * Redistributions of source code must retain the above copyright
--     * Redistributions of source code must retain the above copyright
Line 40... Line 40...
-- Seth Henry      04/16/20 Modified to make use of Open8 bus record
-- Seth Henry      04/16/20 Modified to make use of Open8 bus record
-- Seth Henry      05/06/20 Modified to eliminate request line and detect idle
-- Seth Henry      05/06/20 Modified to eliminate request line and detect idle
--                           conditions instead
--                           conditions instead
-- Seth Henry      05/23/20 Added the parallel interface
-- Seth Henry      05/23/20 Added the parallel interface
-- Seth Henry      04/07/21 Added checksum to prevent glitching on serial noise
-- Seth Henry      04/07/21 Added checksum to prevent glitching on serial noise
 
-- Seth Henry      09/15/21 Removed parallel interface and increased checksum
 
--                           to 16-bits. Also made the magic number a generic.
 
 
library ieee;
library ieee;
  use ieee.std_logic_1164.all;
  use ieee.std_logic_1164.all;
  use ieee.std_logic_unsigned.all;
  use ieee.std_logic_unsigned.all;
  use ieee.std_logic_arith.all;
  use ieee.std_logic_arith.all;
Line 52... Line 54...
library work;
library work;
  use work.Open8_pkg.all;
  use work.Open8_pkg.all;
 
 
entity o8_vector_rx is
entity o8_vector_rx is
generic(
generic(
 
  Magic_Num                  : DATA_TYPE;
  Bit_Rate                   : real;
  Bit_Rate                   : real;
  Enable_Parity              : boolean;
  Enable_Parity              : boolean;
  Parity_Odd_Even_n          : std_logic;
  Parity_Odd_Even_n          : std_logic;
  Clock_Frequency            : real;
  Clock_Frequency            : real;
  Address                    : ADDRESS_TYPE
  Address                    : ADDRESS_TYPE
);
);
port(
port(
  Open8_Bus                  : in  OPEN8_BUS_TYPE;
  Open8_Bus                  : in  OPEN8_BUS_TYPE;
  Rd_Data                    : out DATA_TYPE;
  Rd_Data                    : out DATA_TYPE;
  Interrupt                  : out std_logic;
  Interrupt                  : out std_logic;
  -- Parallel Interface
 
  Vec_Req                    : in  std_logic;
 
  Vec_Index                  : in  std_logic_vector(5 downto 0);
 
  Vec_Data                   : in  std_logic_vector(15 downto 0);
 
  -- Serial Interface
  -- Serial Interface
  Vec_Rx                     : in  std_logic
  Rx_In                      : in  std_logic;
 
  RX_FC                      : out std_logic
);
);
end entity;
end entity;
 
 
architecture behave of o8_vector_rx is
architecture behave of o8_vector_rx is
 
 
Line 83... Line 83...
  alias  Comp_Addr           is Open8_Bus.Address(15 downto 2);
  alias  Comp_Addr           is Open8_Bus.Address(15 downto 2);
  signal Addr_Match          : std_logic := '0';
  signal Addr_Match          : std_logic := '0';
 
 
  alias  Reg_Sel_d           is Open8_Bus.Address(1 downto 0);
  alias  Reg_Sel_d           is Open8_Bus.Address(1 downto 0);
  signal Reg_Sel_q           : std_logic_vector(1 downto 0) := "00";
  signal Reg_Sel_q           : std_logic_vector(1 downto 0) := "00";
 
 
 
  signal Wr_En_d             : std_logic := '0';
 
  signal Wr_En_q             : std_logic := '0';
 
 
  signal Rd_En_d             : std_logic := '0';
  signal Rd_En_d             : std_logic := '0';
  signal Rd_En_q             : std_logic := '0';
  signal Rd_En_q             : std_logic := '0';
 
 
  constant BAUD_RATE_DIV     : integer := integer(Clock_Frequency / Bit_Rate);
  constant BAUD_RATE_DIV     : integer := integer(Clock_Frequency / Bit_Rate);
 
 
Line 97... Line 101...
  constant FULL_PERIOD       : std_logic_vector(Baud_Bits - 1 downto 0) :=
  constant FULL_PERIOD       : std_logic_vector(Baud_Bits - 1 downto 0) :=
                                 conv_std_logic_vector(Full_Per_i, Baud_Bits);
                                 conv_std_logic_vector(Full_Per_i, Baud_Bits);
 
 
  signal Rx_Baud_Cntr        : std_logic_vector(Baud_Bits - 1 downto 0) :=
  signal Rx_Baud_Cntr        : std_logic_vector(Baud_Bits - 1 downto 0) :=
                                 (others => '0');
                                 (others => '0');
  signal Rx_Baud_Tick        : std_logic;
  signal Rx_Baud_Tick        : std_logic := '0';
 
 
  signal Vec_Rx_SR           : std_logic_vector(2 downto 0);
  signal Vec_Rx_SR           : std_logic_vector(2 downto 0) := "000";
  alias  Vec_Rx_MS            is Vec_Rx_SR(2);
  alias  Vec_Rx_MS            is Vec_Rx_SR(2);
  signal Rx_Idle_Cntr        : std_logic_vector(3 downto 0);
  signal Rx_Idle_Cntr        : std_logic_vector(3 downto 0) := "0000";
  signal RX_Idle             : std_logic;
  signal Rx_Idle             : std_logic := '0';
  signal Rx_Data             : DATA_TYPE := x"00";
  signal Rx_Data             : DATA_TYPE := x"00";
  signal Rx_Valid            : std_logic;
  signal Rx_Valid            : std_logic;
 
 
  type VECTOR_RX_STATES is ( CHECKSUM_INIT,
  type VECTOR_RX_STATES is ( CHECKSUM_INIT,
                             GET_VECTOR_CMD,
                             GET_VECTOR_CMD,
                             GET_VECTOR_ARG_LB,
                             GET_VECTOR_ARG_LB,
                             GET_VECTOR_ARG_UB,
                             GET_VECTOR_ARG_UB,
                             GET_VECTOR_SUM,
                             GET_VECTOR_SUM_LB,
 
                             GET_VECTOR_SUM_UB,
                             SEND_INTERRUPT );
                             SEND_INTERRUPT );
  signal Vector_State        : VECTOR_RX_STATES := GET_VECTOR_CMD;
  signal Vector_State        : VECTOR_RX_STATES := GET_VECTOR_CMD;
 
 
  signal Vec_Req_SR           : std_logic_vector(2 downto 0);
  signal Vec_Req_SR          : std_logic_vector(2 downto 0) := "000";
  alias  Vec_Req_MS           is Vec_Req_SR(2);
  alias  Vec_Req_MS           is Vec_Req_SR(2);
 
 
  signal Vector_Index        : DATA_TYPE := x"00";
  signal Vector_Index        : DATA_TYPE := x"00";
  signal Vector_Data         : ADDRESS_TYPE := x"0000";
  signal Vector_Data         : ADDRESS_TYPE := x"0000";
  alias  Vector_Data_LB      is Vector_Data(7 downto 0);
  alias  Vector_Data_LB      is Vector_Data(7 downto 0);
  alias  Vector_Data_UB      is Vector_Data(15 downto 8);
  alias  Vector_Data_UB      is Vector_Data(15 downto 8);
  signal Vector_RX_Sum       : DATA_TYPE := x"00";
  signal Vector_RX_Sum       : ADDRESS_TYPE := x"0000";
 
  alias  Vector_RX_Sum_LB    is Vector_RX_Sum(7 downto 0);
 
  alias  Vector_RX_Sum_UB    is Vector_RX_Sum(15 downto 8);
 
 
 
  signal Checksum            : ADDRESS_TYPE := x"0000";
 
 
  constant MAGIC_NUM         : DATA_TYPE := x"4D";
  signal Interrupt_Req       : std_logic := '0';
  signal Checksum            : DATA_TYPE := x"00";
  signal Interrupt_Pending   : std_logic := '0';
 
 
begin
begin
 
 
  Addr_Match                 <= '1' when Comp_Addr = User_Addr else '0';
  Addr_Match                 <= '1' when Comp_Addr = User_Addr else '0';
 
  Wr_En_d                    <= Addr_Match and Open8_Bus.Wr_En;
  Rd_En_d                    <= Addr_Match and Open8_Bus.Rd_En;
  Rd_En_d                    <= Addr_Match and Open8_Bus.Rd_En;
 
 
  io_reg: process( Clock, Reset )
  io_reg: process( Clock, Reset )
  begin
  begin
    if( Reset = Reset_Level )then
    if( Reset = Reset_Level )then
      Reg_Sel_q              <= (others => '0');
      Reg_Sel_q              <= (others => '0');
 
      Wr_En_q                <= '0';
      Rd_En_q                <= '0';
      Rd_En_q                <= '0';
      Rd_Data                <= OPEN8_NULLBUS;
      Rd_Data                <= OPEN8_NULLBUS;
 
      Interrupt              <= '0';
 
                Interrupt_Pending      <= '0';
    elsif( rising_edge( Clock ) )then
    elsif( rising_edge( Clock ) )then
      Reg_Sel_q              <= Reg_Sel_d;
      Reg_Sel_q              <= Reg_Sel_d;
 
      Wr_En_q                <= Wr_En_d;
      Rd_Data                <= OPEN8_NULLBUS;
      Rd_Data                <= OPEN8_NULLBUS;
      Rd_En_q                <= Rd_En_d;
      Rd_En_q                <= Rd_En_d;
      if( Rd_En_q = '1'  )then
      if( Rd_En_q = '1'  )then
        case( Reg_Sel_q )is
        case( Reg_Sel_q )is
          when "00" =>
          when "00" =>
            Rd_Data          <= Vector_Index;
            Rd_Data          <= Vector_Index;
          when "01" =>
          when "01" =>
            Rd_Data          <= Vector_Data_LB;
            Rd_Data          <= Vector_Data_LB;
          when "10" =>
          when "10" =>
            Rd_Data          <= Vector_Data_UB;
            Rd_Data          <= Vector_Data_UB;
 
          when "11" =>
 
            Rd_Data          <= Interrupt_Pending & "0000000";
          when others =>
          when others =>
            null;
            null;
      end case;
      end case;
      end if;
      end if;
 
 
 
      Interrupt              <= Interrupt_Req;
 
      if( Interrupt_Req = '1' )then
 
        Interrupt_Pending    <= '1';
 
      elsif( Wr_En_q = '1' )then
 
        Interrupt_Pending    <= '0';
 
      end if;
 
 
 
      RX_FC                  <= not Interrupt_Pending;
 
 
    end if;
    end if;
  end process;
  end process;
 
 
  RX_Idle_proc: process( Clock, Reset )
  RX_Idle_proc: process( Clock, Reset )
  begin
  begin
Line 173... Line 198...
      if( Rx_Baud_Cntr = 0 )then
      if( Rx_Baud_Cntr = 0 )then
        Rx_Baud_Cntr         <= FULL_PERIOD;
        Rx_Baud_Cntr         <= FULL_PERIOD;
        Rx_Baud_Tick         <= '1';
        Rx_Baud_Tick         <= '1';
      end if;
      end if;
 
 
      Vec_Rx_SR              <= Vec_Rx_SR(1 downto 0) & Vec_Rx;
      Vec_Rx_SR              <= Vec_Rx_SR(1 downto 0) & Rx_In;
      Rx_Idle_Cntr           <= Rx_Idle_Cntr - Rx_Baud_Tick;
      Rx_Idle_Cntr           <= Rx_Idle_Cntr - Rx_Baud_Tick;
      if( Vec_Rx_MS = '0' )then
      if( Vec_Rx_MS = '0' )then
        Rx_Idle_Cntr         <= (others => '1');
        Rx_Idle_Cntr         <= (others => '1');
      elsif( Rx_Idle_Cntr = 0 )then
      elsif( Rx_Idle_Cntr = 0 )then
        Rx_Idle_Cntr         <= (others => '0');
        Rx_Idle_Cntr         <= (others => '0');
      end if;
      end if;
 
 
      Rx_Idle                <= nor_reduce(Rx_Idle_Cntr);
      Rx_Idle                <= nor_reduce(Rx_Idle_Cntr);
    end if;
    end if;
  end process;
  end process;
 
 
  U_RX : entity work.async_ser_rx
  U_RX : entity work.async_ser_rx
Line 196... Line 220...
  )
  )
  port map(
  port map(
    Clock                    => Clock,
    Clock                    => Clock,
    Reset                    => Reset,
    Reset                    => Reset,
    --
    --
    RX_In                    => Vec_Rx,
    RX_In                    => Rx_In,
    --
    --
    Rx_Data                  => RX_Data,
    Rx_Data                  => RX_Data,
    Rx_Valid                 => RX_Valid,
    Rx_Valid                 => RX_Valid,
    Rx_PErr                  => open
    Rx_PErr                  => open
  );
  );
Line 210... Line 234...
    if( Reset = Reset_Level )then
    if( Reset = Reset_Level )then
      Vec_Req_SR             <= (others => '0');
      Vec_Req_SR             <= (others => '0');
      Vector_State           <= CHECKSUM_INIT;
      Vector_State           <= CHECKSUM_INIT;
      Vector_Index           <= x"00";
      Vector_Index           <= x"00";
      Vector_Data            <= x"0000";
      Vector_Data            <= x"0000";
      Interrupt              <= '0';
      Checksum               <= x"0000";
 
      Interrupt_Req          <= '0';
    elsif( rising_edge(Clock) )then
    elsif( rising_edge(Clock) )then
      Vec_Req_SR             <= Vec_Req_SR(1 downto 0) & Vec_Req;
      Interrupt_Req          <= '0';
 
 
      Interrupt              <= '0';
 
 
 
      if( Vec_Req_MS = '1' )then
 
        Vector_Index         <= "00" & Vec_Index;
 
        Vector_Data          <= Vec_Data;
 
        Interrupt            <= '1';
 
      end if;
 
 
 
      case( Vector_State )is
      case( Vector_State )is
        when CHECKSUM_INIT =>
        when CHECKSUM_INIT =>
          Checksum           <= MAGIC_NUM;
          Checksum           <= x"00" & Magic_Num;
          Vector_State       <= GET_VECTOR_CMD;
          Vector_State       <= GET_VECTOR_CMD;
 
 
        when GET_VECTOR_CMD =>
        when GET_VECTOR_CMD =>
          if( Rx_Valid = '1' )then
          if( Rx_Valid = '1' )then
            Checksum         <= Checksum + Rx_Data;
            Checksum         <= Checksum + (x"00" & Rx_Data);
            Vector_Index     <= "00" & Rx_Data(5 downto 0);
            Vector_Index     <= Rx_Data;
            Vector_State     <= GET_VECTOR_ARG_LB;
            Vector_State     <= GET_VECTOR_ARG_LB;
          end if;
          end if;
 
 
        when GET_VECTOR_ARG_LB =>
        when GET_VECTOR_ARG_LB =>
          if( Rx_Valid = '1' )then
          if( Rx_Valid = '1' )then
            Checksum         <= Checksum + Rx_Data;
            Checksum         <= Checksum + (x"00" & Rx_Data);
            Vector_Data_LB   <= Rx_Data;
            Vector_Data_LB   <= Rx_Data;
            Vector_State     <= GET_VECTOR_ARG_UB;
            Vector_State     <= GET_VECTOR_ARG_UB;
          end if;
          end if;
 
 
        when GET_VECTOR_ARG_UB =>
        when GET_VECTOR_ARG_UB =>
          if( Rx_Valid = '1' )then
          if( Rx_Valid = '1' )then
            Checksum         <= Checksum + Rx_Data;
            Checksum         <= Checksum + (x"00" & Rx_Data);
            Vector_Data_UB   <= Rx_Data;
            Vector_Data_UB   <= Rx_Data;
            Vector_State     <= GET_VECTOR_SUM;
            Vector_State     <= GET_VECTOR_SUM_LB;
 
          end if;
 
 
 
        when GET_VECTOR_SUM_LB =>
 
          if( Rx_Valid = '1' )then
 
            Vector_RX_Sum_LB <= Rx_Data;
 
            Vector_State     <= GET_VECTOR_SUM_UB;
          end if;
          end if;
 
 
        when GET_VECTOR_SUM =>
        when GET_VECTOR_SUM_UB =>
          if( Rx_Valid = '1' )then
          if( Rx_Valid = '1' )then
            Vector_RX_Sum    <= Rx_Data;
            Vector_RX_Sum_UB <= Rx_Data;
            Vector_State     <= SEND_INTERRUPT;
            Vector_State     <= SEND_INTERRUPT;
          end if;
          end if;
 
 
        when SEND_INTERRUPT =>
        when SEND_INTERRUPT =>
          if( Checksum = Vector_RX_Sum )then
          if( Checksum = Vector_RX_Sum )then
            Interrupt        <= '1';
            Interrupt_Req    <= '1';
          end if;
          end if;
          Vector_State       <= CHECKSUM_INIT;
          Vector_State       <= CHECKSUM_INIT;
        when others => null;
        when others => null;
      end case;
      end case;
 
 
      if( Rx_Idle = '1' )then
      if( Rx_Idle = '1' or Interrupt_Pending = '1' )then
        Vector_State         <= CHECKSUM_INIT;
        Vector_State         <= CHECKSUM_INIT;
      end if;
      end if;
 
 
    end if;
    end if;
  end process;
  end process;

powered by: WebSVN 2.1.0

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