AMC13
Firmwares for the different applications of the AMC13 uTCA board made at Boston University
 All Classes Variables
transactor_sm.vhd
1 -- The state machine which controls the ipbus itself
2 --
3 -- This version for ipbus 2.0
4 --
5 -- All details of the ipbus transaction protocol itself are in here.
6 -- However, the module knows nothing about the transport layer, and
7 -- just processes the transactions it's handed.
8 --
9 -- Dave Newbold, October 2012
10 
11 library ieee;
12 use ieee.std_logic_1164.all;
13 use ieee.numeric_std.all;
14 
15 library work;
16 use work.ipbus.all;
17 
18 entity transactor_sm is
19  port(
20  clk: in std_logic;
21  rst: in std_logic;
22  rx_data: in std_logic_vector(31 downto 0); -- Input packet data
23  rx_ready: in std_logic; -- Asserted when valid input packet data is available
24  rx_next: out std_logic; -- New input packet data please
25  tx_data: out std_logic_vector(31 downto 0); -- Output packet data
26  tx_we: out std_logic; -- Valid output word
27  tx_hdr: out std_logic; -- Marks a transaction header
28  tx_err: out std_logic; -- Asserted if we end the packet early due to error
29  ipb_out: out ipb_wbus;
30  ipb_in: in ipb_rbus;
31  cfg_we: out std_logic; -- local bus write enable
32  cfg_addr: out std_logic_vector(1 downto 0); -- local bus addr
33  cfg_din: in std_logic_vector(31 downto 0); -- local bus data
34  cfg_dout: out std_logic_vector(31 downto 0)
35  );
36 
37 end transactor_sm;
38 
39 architecture rtl of transactor_sm is
40 
41  constant TIMEOUT: integer := 255;
42 
43  constant TRANS_RD: std_logic_vector(3 downto 0) := X"0";
44  constant TRANS_WR: std_logic_vector(3 downto 0) := X"1";
45  constant TRANS_RDN: std_logic_vector(3 downto 0) := X"2";
46  constant TRANS_WRN: std_logic_vector(3 downto 0) := X"3";
47  constant TRANS_RMWB: std_logic_vector(3 downto 0) := X"4";
48  constant TRANS_RMWS: std_logic_vector(3 downto 0) := X"5";
49  constant TRANS_RD_CFG: std_logic_vector(3 downto 0) := X"6";
50  constant TRANS_WR_CFG: std_logic_vector(3 downto 0) := X"7";
51 
52  type state_type is (ST_IDLE, ST_HDR, ST_ADDR, ST_BUS_CYCLE, ST_RMW_1, ST_RMW_2);
53  signal state: state_type;
54 
55  signal rx_ready_d, start, rmw_cyc, cfg_cyc, rmw_write, write, strobe, ack, last_wd: std_logic;
56  signal trans_type: std_logic_vector(3 downto 0);
57  signal addr: unsigned(31 downto 0);
58  signal words_todo, words_done: unsigned(7 downto 0);
59  signal timer: unsigned(7 downto 0);
60  signal rmw_coeff, rmw_input, rmw_result, data_out: std_logic_vector(31 downto 0);
61  signal err, err_d: std_logic_vector(3 downto 0);
62  signal hdr: std_logic_vector(31 downto 0);
63 
64 begin
65 
66  process(clk)
67  begin
68  if rising_edge(clk) then
69  if rst = '1' then
70  state <= ST_IDLE;
71  else
72  case state is
73 -- Starting state
74  when ST_IDLE =>
75  if start = '1' then
76  state <= ST_HDR;
77  end if;
78 -- Decode header word
79  when ST_HDR =>
80  if rx_ready = '0' or err /= X"0" or err_d /= X"0" then
81  state <= ST_IDLE;
82  else
83  state <= ST_ADDR;
84  end if;
85 -- Load address counter
86  when ST_ADDR =>
87  if words_todo /= X"00" then
88  state <= ST_BUS_CYCLE;
89  else
90  state <= ST_HDR;
91  end if;
92 -- The bus transaction
93  when ST_BUS_CYCLE =>
94  if err /= X"0" then
95  state <= ST_HDR;
96  elsif ack = '1' and last_wd = '1' then
97  if rmw_cyc = '1' and rmw_write = '0' then
98  state <= ST_RMW_1;
99  else
100  state <= ST_HDR;
101  end if;
102  elsif timer = TIMEOUT then
103  state <= ST_HDR;
104  end if;
105 -- RMW operations
106  when ST_RMW_1 =>
107  if trans_type = TRANS_RMWB then
108  state <= ST_RMW_2;
109  else
110  state <= ST_BUS_CYCLE;
111  end if;
112 
113  when ST_RMW_2 =>
114  state <= ST_BUS_CYCLE;
115 
116  end case;
117  end if;
118 
119  end if;
120  end process;
121 
122  process(clk)
123  begin
124  if rising_edge(clk) then
125 
126  rx_ready_d <= rx_ready;
127 
128  if state = ST_HDR then
129  hdr <= rx_data;
130  end if;
131 
132  if state = ST_ADDR then
133  addr <= unsigned(rx_data);
134  elsif ack = '1' and (trans_type = TRANS_RD or trans_type = TRANS_WR) then
135  addr <= addr + 1;
136  end if;
137 
138  if state = ST_HDR then
139  words_todo <= unsigned(rx_data(15 downto 8));
140  elsif state = ST_RMW_1 then
141  words_todo <= (others => '0');
142  elsif state <= ST_ADDR or ack = '1' then
143  words_todo <= words_todo - 1;
144  end if;
145 
146  if state = ST_HDR then
147  words_done <= (others => '0');
148  elsif ack = '1' and (rmw_cyc = '0' or rmw_write = '1') then
149  words_done <= words_done + 1;
150  end if;
151 
152  if state = ST_ADDR or state = ST_RMW_1 or ack = '1' then
153  timer <= (others => '0');
154  elsif strobe = '1' then
155  timer <= timer + 1;
156  end if;
157 
158  if state = ST_HDR then
159  rmw_write <= '0';
160  elsif state = ST_RMW_1 then
161  rmw_write <= '1';
162  end if;
163 
164  if state = ST_RMW_1 then
165  rmw_coeff <= rx_data;
166  rmw_result <= std_logic_vector(unsigned(rmw_input) + unsigned(rx_data));
167  elsif state = ST_RMW_2 then
168  rmw_result <= (rmw_input and rmw_coeff) or rx_data;
169  end if;
170 
171  if ack = '1' then
172  rmw_input <= ipb_in.ipb_rdata;
173  end if;
174 
175  if state = ST_IDLE then
176  err_d <= X"0";
177  else
178  err_d <= err;
179  end if;
180 
181  end if;
182  end process;
183 
184  start <= rx_ready and not rx_ready_d;
185  last_wd <= '1' when words_todo = 0 else '0';
186  trans_type <= hdr(7 downto 4);
187 
188  strobe <= '1' when state = ST_BUS_CYCLE and cfg_cyc = '0' else '0';
189  write <= '1' when trans_type = TRANS_WR or trans_type = TRANS_WRN or trans_type = TRANS_WR_CFG
190  or rmw_write = '1' else '0';
191  rx_next <= '1' when state = ST_HDR or state = ST_RMW_1 or state = ST_RMW_2 or
192  (state = ST_ADDR and (write='1' or words_todo = X"00")) or
193  (state = ST_BUS_CYCLE and (ack and (strobe or cfg_cyc) and (write or last_wd) and not rmw_write) = '1')
194  else '0';
195  rmw_cyc <= '1' when trans_type = TRANS_RMWB or trans_type = TRANS_RMWS else '0';
196  cfg_cyc <= '1' when trans_type = TRANS_RD_CFG or trans_type = TRANS_WR_CFG else '0';
197 
198  process(state, rx_data, ipb_in.ipb_err, timer, write)
199  begin
200  err <= X"0";
201  if state = ST_HDR then
202  if rx_data(31 downto 28) /= X"2" or rx_data(3 downto 0) /= X"f" then
203  err <= "0001";
204  end if;
205  elsif state = ST_BUS_CYCLE then
206  if ipb_in.ipb_err = '1' then
207  err <= "010" & write;
208  elsif timer = TIMEOUT then
209  err <= "011" & write;
210  end if;
211  end if;
212  end process;
213 
214  ack <= ipb_in.ipb_ack or ipb_in.ipb_err or cfg_cyc;
215 
216  ipb_out.ipb_addr <= std_logic_vector(addr);
217  ipb_out.ipb_write <= write;
218  ipb_out.ipb_strobe <= strobe;
219  ipb_out.ipb_wdata <= rx_data when rmw_cyc = '0' else rmw_result;
220 
221  data_out <= ipb_in.ipb_rdata when cfg_cyc = '0' else cfg_din;
222 
223  tx_data <= (hdr(31 downto 16) & std_logic_vector(words_done) & hdr(7 downto 4) & err_d) when state = ST_HDR else data_out;
224  tx_we <= '1' when state = ST_HDR or (state = ST_BUS_CYCLE and (ack and not write) = '1') else '0';
225  tx_hdr <= '1' when state = ST_HDR else '0';
226  tx_err <= '1' when err_d /= X"0" else '0';
227 
228  cfg_addr <= std_logic_vector(addr(1 downto 0));
229  cfg_we <= '1' when state = ST_BUS_CYCLE and trans_type = TRANS_WR_CFG else '0';
230  cfg_dout <= rx_data;
231 
232 end rtl;