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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [VHDL/] [o8_vector_rx.vhd] - Blame information for rev 309

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 296 jshamlet
-- Copyright (c)2021 Jeremy Seth Henry
2 240 jshamlet
-- All rights reserved.
3
--
4
-- Redistribution and use in source and binary forms, with or without
5
-- modification, are permitted provided that the following conditions are met:
6
--     * Redistributions of source code must retain the above copyright
7
--       notice, this list of conditions and the following disclaimer.
8
--     * Redistributions in binary form must reproduce the above copyright
9
--       notice, this list of conditions and the following disclaimer in the
10
--       documentation and/or other materials provided with the distribution,
11
--       where applicable (as part of a user interface, debugging port, etc.)
12
--
13
-- THIS SOFTWARE IS PROVIDED BY JEREMY SETH HENRY ``AS IS'' AND ANY
14
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15
-- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16
-- DISCLAIMED. IN NO EVENT SHALL JEREMY SETH HENRY BE LIABLE FOR ANY
17
-- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
-- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
-- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22
-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
--
24
-- VHDL Entity: o8_vector_rx
25
-- Description: Receives a 6-bit vector command and 16-bit argument from the
26
--               vector_tx entity. Issues interrupt to the CPU on receipt of
27
--               three bytes.
28
--
29
-- Register Map:
30
-- Offset  Bitfield Description                        Read/Write
31
--   0x0   --AAAAAA Vector Select
32
--   0x1   AAAAAAAA Vector Argument LB
33
--   0x2   AAAAAAAA Vector Argument UB
34
--
35
-- Revision History
36
-- Author          Date     Change
37
------------------ -------- ---------------------------------------------------
38
-- Seth Henry      04/15/20 Created from o8_epoch_timer due to requirement
39
--                           change.
40
-- Seth Henry      04/16/20 Modified to make use of Open8 bus record
41
-- Seth Henry      05/06/20 Modified to eliminate request line and detect idle
42
--                           conditions instead
43 246 jshamlet
-- Seth Henry      05/23/20 Added the parallel interface
44 285 jshamlet
-- Seth Henry      04/07/21 Added checksum to prevent glitching on serial noise
45 296 jshamlet
-- Seth Henry      09/15/21 Removed parallel interface and increased checksum
46
--                           to 16-bits. Also made the magic number a generic.
47 240 jshamlet
 
48
library ieee;
49
  use ieee.std_logic_1164.all;
50
  use ieee.std_logic_unsigned.all;
51
  use ieee.std_logic_arith.all;
52
  use ieee.std_logic_misc.all;
53
 
54
library work;
55
  use work.Open8_pkg.all;
56
 
57
entity o8_vector_rx is
58
generic(
59 296 jshamlet
  Magic_Num                  : DATA_TYPE;
60 240 jshamlet
  Bit_Rate                   : real;
61
  Enable_Parity              : boolean;
62
  Parity_Odd_Even_n          : std_logic;
63
  Clock_Frequency            : real;
64
  Address                    : ADDRESS_TYPE
65
);
66
port(
67
  Open8_Bus                  : in  OPEN8_BUS_TYPE;
68
  Rd_Data                    : out DATA_TYPE;
69
  Interrupt                  : out std_logic;
70 246 jshamlet
  -- Serial Interface
71 296 jshamlet
  Rx_In                      : in  std_logic;
72
  RX_FC                      : out std_logic
73 240 jshamlet
);
74
end entity;
75
 
76
architecture behave of o8_vector_rx is
77
 
78
  alias Clock                is Open8_Bus.Clock;
79
  alias Reset                is Open8_Bus.Reset;
80
 
81
  constant User_Addr         : std_logic_vector(15 downto 2) :=
82
                                Address(15 downto 2);
83
  alias  Comp_Addr           is Open8_Bus.Address(15 downto 2);
84
  signal Addr_Match          : std_logic := '0';
85
 
86 244 jshamlet
  alias  Reg_Sel_d           is Open8_Bus.Address(1 downto 0);
87
  signal Reg_Sel_q           : std_logic_vector(1 downto 0) := "00";
88 296 jshamlet
 
89
  signal Wr_En_d             : std_logic := '0';
90
  signal Wr_En_q             : std_logic := '0';
91
 
92 244 jshamlet
  signal Rd_En_d             : std_logic := '0';
93
  signal Rd_En_q             : std_logic := '0';
94 240 jshamlet
 
95
  constant BAUD_RATE_DIV     : integer := integer(Clock_Frequency / Bit_Rate);
96
 
97
  -- Period of each bit in sub-clocks (subtract one to account for zero)
98
  constant Full_Per_i        : integer := BAUD_RATE_DIV - 1;
99
  constant Baud_Bits         : integer := ceil_log2(Full_Per_i);
100
 
101
  constant FULL_PERIOD       : std_logic_vector(Baud_Bits - 1 downto 0) :=
102
                                 conv_std_logic_vector(Full_Per_i, Baud_Bits);
103
 
104
  signal Rx_Baud_Cntr        : std_logic_vector(Baud_Bits - 1 downto 0) :=
105
                                 (others => '0');
106 296 jshamlet
  signal Rx_Baud_Tick        : std_logic := '0';
107 240 jshamlet
 
108 296 jshamlet
  signal Vec_Rx_SR           : std_logic_vector(2 downto 0) := "000";
109 246 jshamlet
  alias  Vec_Rx_MS            is Vec_Rx_SR(2);
110 296 jshamlet
  signal Rx_Idle_Cntr        : std_logic_vector(3 downto 0) := "0000";
111
  signal Rx_Idle             : std_logic := '0';
112 246 jshamlet
  signal Rx_Data             : DATA_TYPE := x"00";
113
  signal Rx_Valid            : std_logic;
114 240 jshamlet
 
115 285 jshamlet
  type VECTOR_RX_STATES is ( CHECKSUM_INIT,
116
                             GET_VECTOR_CMD,
117
                             GET_VECTOR_ARG_LB,
118
                             GET_VECTOR_ARG_UB,
119 296 jshamlet
                             GET_VECTOR_SUM_LB,
120
                             GET_VECTOR_SUM_UB,
121 240 jshamlet
                             SEND_INTERRUPT );
122
  signal Vector_State        : VECTOR_RX_STATES := GET_VECTOR_CMD;
123
 
124 296 jshamlet
  signal Vec_Req_SR          : std_logic_vector(2 downto 0) := "000";
125
  alias  Vec_Req_MS          is Vec_Req_SR(2);
126 240 jshamlet
 
127 296 jshamlet
  signal Vector_Index        : DATA_TYPE    := x"00";
128 246 jshamlet
  signal Vector_Data         : ADDRESS_TYPE := x"0000";
129
  alias  Vector_Data_LB      is Vector_Data(7 downto 0);
130
  alias  Vector_Data_UB      is Vector_Data(15 downto 8);
131 296 jshamlet
  signal Vector_RX_Sum       : ADDRESS_TYPE := x"0000";
132
  alias  Vector_RX_Sum_LB    is Vector_RX_Sum(7 downto 0);
133
  alias  Vector_RX_Sum_UB    is Vector_RX_Sum(15 downto 8);
134 240 jshamlet
 
135 296 jshamlet
  signal Checksum            : ADDRESS_TYPE := x"0000";
136 285 jshamlet
 
137 296 jshamlet
  signal Interrupt_Req       : std_logic := '0';
138
  signal Interrupt_Pending   : std_logic := '0';
139
 
140 240 jshamlet
begin
141
 
142
  Addr_Match                 <= '1' when Comp_Addr = User_Addr else '0';
143 296 jshamlet
  Wr_En_d                    <= Addr_Match and Open8_Bus.Wr_En;
144 244 jshamlet
  Rd_En_d                    <= Addr_Match and Open8_Bus.Rd_En;
145 240 jshamlet
 
146
  io_reg: process( Clock, Reset )
147
  begin
148
    if( Reset = Reset_Level )then
149 246 jshamlet
      Reg_Sel_q              <= (others => '0');
150 296 jshamlet
      Wr_En_q                <= '0';
151 246 jshamlet
      Rd_En_q                <= '0';
152
      Rd_Data                <= OPEN8_NULLBUS;
153 296 jshamlet
      Interrupt              <= '0';
154
                Interrupt_Pending      <= '0';
155 240 jshamlet
    elsif( rising_edge( Clock ) )then
156 246 jshamlet
      Reg_Sel_q              <= Reg_Sel_d;
157 296 jshamlet
      Wr_En_q                <= Wr_En_d;
158 246 jshamlet
      Rd_Data                <= OPEN8_NULLBUS;
159
      Rd_En_q                <= Rd_En_d;
160 244 jshamlet
      if( Rd_En_q = '1'  )then
161
        case( Reg_Sel_q )is
162 240 jshamlet
          when "00" =>
163 246 jshamlet
            Rd_Data          <= Vector_Index;
164 240 jshamlet
          when "01" =>
165 246 jshamlet
            Rd_Data          <= Vector_Data_LB;
166 240 jshamlet
          when "10" =>
167 246 jshamlet
            Rd_Data          <= Vector_Data_UB;
168 296 jshamlet
          when "11" =>
169
            Rd_Data          <= Interrupt_Pending & "0000000";
170 240 jshamlet
          when others =>
171
            null;
172 296 jshamlet
        end case;
173 240 jshamlet
      end if;
174 296 jshamlet
 
175
      Interrupt              <= Interrupt_Req;
176
      if( Interrupt_Req = '1' )then
177
        Interrupt_Pending    <= '1';
178
      elsif( Wr_En_q = '1' )then
179
        Interrupt_Pending    <= '0';
180
      end if;
181
 
182
      RX_FC                  <= not Interrupt_Pending;
183
 
184 240 jshamlet
    end if;
185
  end process;
186
 
187
  RX_Idle_proc: process( Clock, Reset )
188
  begin
189
    if( Reset = Reset_Level )then
190 246 jshamlet
      Rx_Baud_Cntr           <= (others => '0');
191
      Rx_Baud_Tick           <= '0';
192
      Vec_Rx_SR              <= (others => '1');
193
      Rx_Idle_Cntr           <= (others => '0');
194
      Rx_Idle                <= '0';
195 240 jshamlet
    elsif( rising_edge(Clock) )then
196 246 jshamlet
      Rx_Baud_Cntr           <= Rx_Baud_Cntr - 1;
197
      Rx_Baud_Tick           <= '0';
198 240 jshamlet
      if( Rx_Baud_Cntr = 0 )then
199 246 jshamlet
        Rx_Baud_Cntr         <= FULL_PERIOD;
200
        Rx_Baud_Tick         <= '1';
201 240 jshamlet
      end if;
202
 
203 296 jshamlet
      Vec_Rx_SR              <= Vec_Rx_SR(1 downto 0) & Rx_In;
204 246 jshamlet
      Rx_Idle_Cntr           <= Rx_Idle_Cntr - Rx_Baud_Tick;
205
      if( Vec_Rx_MS = '0' )then
206
        Rx_Idle_Cntr         <= (others => '1');
207 240 jshamlet
      elsif( Rx_Idle_Cntr = 0 )then
208 246 jshamlet
        Rx_Idle_Cntr         <= (others => '0');
209 240 jshamlet
      end if;
210 246 jshamlet
      Rx_Idle                <= nor_reduce(Rx_Idle_Cntr);
211 240 jshamlet
    end if;
212
  end process;
213
 
214
  U_RX : entity work.async_ser_rx
215
  generic map(
216
    Reset_Level              => Reset_Level,
217
    Enable_Parity            => Enable_Parity,
218
    Parity_Odd_Even_n        => Parity_Odd_Even_n,
219
    Clock_Divider            => BAUD_RATE_DIV
220
  )
221
  port map(
222
    Clock                    => Clock,
223
    Reset                    => Reset,
224
    --
225 296 jshamlet
    RX_In                    => Rx_In,
226 240 jshamlet
    --
227
    Rx_Data                  => RX_Data,
228
    Rx_Valid                 => RX_Valid,
229
    Rx_PErr                  => open
230
  );
231
 
232
  Vector_RX_proc: process( Clock, Reset )
233
  begin
234
    if( Reset = Reset_Level )then
235 246 jshamlet
      Vec_Req_SR             <= (others => '0');
236 285 jshamlet
      Vector_State           <= CHECKSUM_INIT;
237 246 jshamlet
      Vector_Index           <= x"00";
238
      Vector_Data            <= x"0000";
239 296 jshamlet
      Checksum               <= x"0000";
240
      Interrupt_Req          <= '0';
241 240 jshamlet
    elsif( rising_edge(Clock) )then
242 296 jshamlet
      Interrupt_Req          <= '0';
243 246 jshamlet
 
244 240 jshamlet
      case( Vector_State )is
245 285 jshamlet
        when CHECKSUM_INIT =>
246 296 jshamlet
          Checksum           <= x"00" & Magic_Num;
247 285 jshamlet
          Vector_State       <= GET_VECTOR_CMD;
248
 
249 240 jshamlet
        when GET_VECTOR_CMD =>
250
          if( Rx_Valid = '1' )then
251 296 jshamlet
            Checksum         <= Checksum + (x"00" & Rx_Data);
252
            Vector_Index     <= Rx_Data;
253 240 jshamlet
            Vector_State     <= GET_VECTOR_ARG_LB;
254
          end if;
255
 
256
        when GET_VECTOR_ARG_LB =>
257
          if( Rx_Valid = '1' )then
258 296 jshamlet
            Checksum         <= Checksum + (x"00" & Rx_Data);
259 246 jshamlet
            Vector_Data_LB   <= Rx_Data;
260 240 jshamlet
            Vector_State     <= GET_VECTOR_ARG_UB;
261
          end if;
262
 
263
        when GET_VECTOR_ARG_UB =>
264
          if( Rx_Valid = '1' )then
265 296 jshamlet
            Checksum         <= Checksum + (x"00" & Rx_Data);
266 246 jshamlet
            Vector_Data_UB   <= Rx_Data;
267 296 jshamlet
            Vector_State     <= GET_VECTOR_SUM_LB;
268 285 jshamlet
          end if;
269
 
270 296 jshamlet
        when GET_VECTOR_SUM_LB =>
271 285 jshamlet
          if( Rx_Valid = '1' )then
272 296 jshamlet
            Vector_RX_Sum_LB <= Rx_Data;
273
            Vector_State     <= GET_VECTOR_SUM_UB;
274
          end if;
275
 
276
        when GET_VECTOR_SUM_UB =>
277
          if( Rx_Valid = '1' )then
278
            Vector_RX_Sum_UB <= Rx_Data;
279 240 jshamlet
            Vector_State     <= SEND_INTERRUPT;
280
          end if;
281
 
282
        when SEND_INTERRUPT =>
283 285 jshamlet
          if( Checksum = Vector_RX_Sum )then
284 296 jshamlet
            Interrupt_Req    <= '1';
285 285 jshamlet
          end if;
286
          Vector_State       <= CHECKSUM_INIT;
287 240 jshamlet
        when others => null;
288
      end case;
289
 
290 296 jshamlet
      if( Rx_Idle = '1' or Interrupt_Pending = '1' )then
291 285 jshamlet
        Vector_State         <= CHECKSUM_INIT;
292 240 jshamlet
      end if;
293
 
294
    end if;
295
  end process;
296
 
297
end architecture;

powered by: WebSVN 2.1.0

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