aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/vivado_ipi/axi_bitq/bitq_fsm.vhd
blob: a952c4b356f111f7a390372f92709400c3c00d9a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
--
-- Copyright 2018 Ettus Research, A National Instruments Company
--
-- SPDX-License-Identifier: LGPL-3.0
--
-- Module: bitq_fsm
-- Description: Simple IP to shift bits in/out (primarily for JTAG)
-- bitq_fsm implements the state machine underlying the IP

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity bitq_fsm is
generic (
  IDLE_VALUE : std_logic := 'Z'
);
port (
  clk  : in std_logic;
  rstn : in std_logic;
  prescalar : in std_logic_vector(7 downto 0);

  bit_clk  : inout std_logic;
  bit_in   : in    std_logic;
  bit_out  : inout std_logic;
  bit_stb  : inout std_logic;
  start    : in std_logic;
  ready    : out std_logic;
  len      : in std_logic_vector(4 downto 0);
  wr_data  : in std_logic_vector(31 downto 0);
  stb_data : in std_logic_vector(31 downto 0);
  rd_data  : out std_logic_vector(31 downto 0)
);

end bitq_fsm;

architecture arch of bitq_fsm is
  type bitq_state_t is (IDLE, LOW, HIGH);
  signal bitq_state : bitq_state_t;

  signal bit_clk_count  : unsigned(7 downto 0);
  signal bit_count  : unsigned(5 downto 0);

  signal bit_out_r  : std_logic;
  signal bit_stb_r  : std_logic;

  signal rd_data_r  : std_logic_vector(31 downto 0);

begin
  rd_data <= rd_data_r;

  gen_io : process (bitq_state, bit_count, bit_out_r, bit_stb_r)
  begin
    case (bitq_state) is
    when IDLE =>
      bit_clk <= IDLE_VALUE;
      bit_out <= IDLE_VALUE;
      bit_stb <= IDLE_VALUE;
      ready   <= '1';
    when LOW =>
      bit_clk <= '0';
      bit_out <= bit_out_r;
      bit_stb <= bit_stb_r;
      ready <= '0';
    when HIGH =>
      bit_clk <= '1';
      bit_out <= bit_out_r;
      bit_stb <= bit_stb_r;
      ready <= '0';
    when others =>
      bit_clk <= IDLE_VALUE;
      bit_out <= IDLE_VALUE;
      bit_stb <= IDLE_VALUE;
      ready   <= '1';
    end case;
  end process;

  bit_clk_gen : process (clk)
  begin
  if rising_edge(clk) then
    if (rstn = '0') or (bitq_state = IDLE) or
       (bit_clk_count = 0) then
      bit_clk_count <= unsigned(prescalar);
    elsif (bit_clk_count /= 0) then
      bit_clk_count <= bit_clk_count - 1;
    end if;
  end if;
  end process bit_clk_gen;

  fsm : process (clk)
  begin
  if rising_edge(clk) then
    if (rstn = '0') then
      bitq_state <= IDLE;
      bit_count <= to_unsigned(0, bit_count'length);
      rd_data_r <= (others => '0');
    else
      case bitq_state is
      when IDLE =>
        bit_count <= to_unsigned(0, bit_count'length);

        if (start = '1') then
          bitq_state <= LOW;
          rd_data_r <= (others => '0');
          bit_out_r <= wr_data(0);
          bit_stb_r <= stb_data(0);
        end if;
      when LOW =>
        if (bit_clk_count = 0) then
          rd_data_r(to_integer(bit_count)) <= bit_in;
          bit_count <= bit_count + 1;
          bitq_state <= HIGH; --Rising edge
        end if;
      when HIGH =>
        if (bit_clk_count = 0) then
          if (bit_count > unsigned('0' & len)) then
            bitq_state <= IDLE;
          else
            bit_out_r <= wr_data(to_integer(bit_count));
            bit_stb_r <= stb_data(to_integer(bit_count));
            bitq_state <= LOW; --Falling edge
          end if;
        end if;
      end case;
    end if;
  end if;
  end process fsm;

end arch;