vt52-fpga  1.0.0 Initial
vt52-fpga is a serial terminal implemented on a FPGA
usb_uart_bridge_ep.v
Go to the documentation of this file.
1 /*
2  usb_uart_bridge_ep
3 
4  This is the endpoint to uart translator. Two things to highlight: the directions
5  IN and OUT are set with respect to the HOST, and also in USB, the HOST runs all
6  endpoint interactions.
7 
8  The out endpoint interface. This is the out w.r.t. the host, hence in to
9  us. There are request grant, data available and data get signals, stall and
10  acked signals. And the data itself.
11 
12  The in endpoint interface. This is the in w.r.t. the host, hence out to us.
13  This interface also has a req and grant. There's a put signal and a free
14  signal. Stall and acked. And the data.
15 
16  To get data in and out there are two pipeline interfaces - one in and one out.
17 
18  OUT (or into this device)
19 
20  Roughly, the USB innards signal that a packet has arrived by raising out_ep_data_available.
21  The data multiplexor has to be switched, so the interface is requested. This is
22  combinatorial logic so clever req and grant stuff can happen in the same line.
23 
24  assign out_ep_req = ( out_ep_req_reg || out_ep_data_avail );
25 
26  With the interface granted, the data is free to get. Every cycle that the out_ep_data_get
27  signal is high, the input address is advanced. Inside the USB innards, when the
28  read address pointer equals the address of the write pointer (when all the data is
29  retreived, the out_ep_data_available flag is lowered and we withdraw our request for
30  the interface and go back to idle.
31 
32  Interestingly, if you stop taking data... you lose your buffer. So don't.
33 
34  IN (or out of this device back to the host)
35 
36  The IN EP works by providing a buffer and waiting for the local logic to fill it,
37  or to say that it's done. When this happens the interface switches to a new state where
38  it waits for a token from the host. When it get the token, it sends the data. When that
39  is acknoledged, the buffer is released and returned ready to be filled again.
40 
41  in_ep_data_free signals that there's a buffer waiting. And that signal goes low when
42  the buffer is full and not available.
43 
44  In the case where a buffer is not full - just sitting around with some data in it, a decision
45  has to be made at some point just to send. This is handled by a timeout mechanism, which
46  asserts in_ep_data_done and lets the buffer be sent.
47 
48  In the case where the buffer fills to the top, in_ep_data_free goes low by itself.
49 
50 */
51 
53  input clk,
54  input reset,
55 
56  ////////////////////
57  // out endpoint interface
58  ////////////////////
59  output out_ep_req, // request the data interface for the out endpoint
60  input out_ep_grant, // data interface granted
61  input out_ep_data_avail, // flagging data available to get from the host - stays up until the cycle upon which it is empty
62  input out_ep_setup, // [setup packet sent? - not used here]
63  output out_ep_data_get, // request to get the data
64  input [7:0] out_ep_data, // data from the host
65  output out_ep_stall, // an output enabling the device to stop inputs (not used)
66  input out_ep_acked, // indicating that the outgoing data was acked
67 
68  ////////////////////
69  // in endpoint interface
70  ////////////////////
71  output in_ep_req, // request the data interface for the in endpoint
72  input in_ep_grant, // data interface granted
73  input in_ep_data_free, // end point is ready for data - (specifically there is a buffer and it has space)
74  // after going low it takes a while to get another back, but it does this automatically
75  output in_ep_data_put, // forces end point to read our data
76  output [7:0] in_ep_data, // data back to the host
77  output in_ep_data_done, // signalling that we're done sending data
78  output in_ep_stall, // an output enabling the device to stop outputs (not used)
79  input in_ep_acked, // indicating that the outgoing data was acked
80 
81  // uart pipeline in
82  input [7:0] uart_in_data,
83  input uart_in_valid,
84  output uart_in_ready,
85 
86  // uart pipeline out
87  output [7:0] uart_out_data,
88  output uart_out_valid,
89  input uart_out_ready,
90 
91  output [3:0] debug
92 );
93 
94  // Timeout counter width.
95  localparam TimeoutWidth = 3;
96 
97  // We don't stall
98  assign out_ep_stall = 1'b0;
99  assign in_ep_stall = 1'b0;
100 
101  // Registers for the out pipeline (out of the module)
102  reg [7:0] uart_out_data_reg;
103  reg [7:0] uart_out_data_overflow_reg;
104  reg uart_out_valid_reg;
105 
106  // registers for the out end point (out of the host)
107  reg out_ep_req_reg;
108  reg out_ep_data_get_reg;
109 
110  // out pipeline / out endpoint state machine state (6 states -> 3 bits)
111  reg [1:0] pipeline_out_state;
112 
113  localparam PipelineOutState_Idle = 0;
114  localparam PipelineOutState_WaitData = 1;
115  localparam PipelineOutState_PushData = 2;
116  localparam PipelineOutState_WaitPipeline = 3;
117 
118  // connect the pipeline registers to the outgoing ports
119  assign uart_out_data = uart_out_data_reg;
120  assign uart_out_valid = uart_out_valid_reg;
121 
122  // automatically make the bus request from the data_available
123  // latch it with out_ep_req_reg
124  assign out_ep_req = ( out_ep_req_reg || out_ep_data_avail );
125 
126  wire out_granted_data_available;
127 
128  assign out_granted_data_available = out_ep_req && out_ep_grant;
129 
130  assign out_ep_data_get = ( uart_out_ready || ~uart_out_valid_reg ) && out_ep_data_get_reg;
131 
132  reg [7:0] out_stall_data;
133  reg out_stall_valid;
134 
135  // do HOST OUT, DEVICE IN, PIPELINE OUT (!)
136  always @(posedge clk) begin
137  if ( reset ) begin
138  pipeline_out_state <= PipelineOutState_Idle;
139  uart_out_data_reg <= 0;
140  uart_out_valid_reg <= 0;
141  out_ep_req_reg <= 0;
142  out_ep_data_get_reg <= 0;
143  out_stall_data <= 0;
144  out_stall_valid <= 0;
145  end else begin
146  case( pipeline_out_state )
147  PipelineOutState_Idle: begin
148  // Waiting for the data_available signal indicating that a data packet has arrived
149  if ( out_granted_data_available ) begin
150  // indicate that we want the data
151  out_ep_data_get_reg <= 1;
152  // although the bus has been requested automatically, we latch the request so we control it
153  out_ep_req_reg <= 1;
154  // now wait for the data to set up
155  pipeline_out_state <= PipelineOutState_WaitData;
156  uart_out_valid_reg <= 0;
157  out_stall_data <= 0;
158  out_stall_valid <= 0;
159  end
160  end
161  PipelineOutState_WaitData: begin
162  // it takes one cycle for the juices to start flowing
163  // we got here when we were starting or if the outgoing pipe stalled
164  if ( uart_out_ready || ~uart_out_valid_reg ) begin
165  //if we were stalled, we can send the byte we caught while we were stalled
166  // the actual stalled byte now having been VALID & READY'ed
167  if ( out_stall_valid ) begin
168  uart_out_data_reg <= out_stall_data;
169  uart_out_valid_reg <= 1;
170  out_stall_data <= 0;
171  out_stall_valid <= 0;
172  if ( out_ep_data_avail )
173  pipeline_out_state <= PipelineOutState_PushData;
174  else begin
175  pipeline_out_state <= PipelineOutState_WaitPipeline;
176  end
177  end else begin
178  pipeline_out_state <= PipelineOutState_PushData;
179  end
180  end
181  end
182  PipelineOutState_PushData: begin
183  // can grab a character if either the out was accepted or the out reg is empty
184  if ( uart_out_ready || ~uart_out_valid_reg ) begin
185  // now we really have got some data and a place to shove it
186  uart_out_data_reg <= out_ep_data;
187  uart_out_valid_reg <= 1;
188  if ( ~out_ep_data_avail ) begin
189  // stop streaming, now just going to wait until the character is accepted
190  out_ep_data_get_reg <= 0;
191  pipeline_out_state <= PipelineOutState_WaitPipeline;
192  end
193  end else begin
194  // We're in push data so there is a character, but our pipeline has stalled
195  // need to save the character and wait.
196  out_stall_data <= out_ep_data;
197  out_stall_valid <= 1;
198  pipeline_out_state <= PipelineOutState_WaitData;
199  if ( ~out_ep_data_avail )
200  out_ep_data_get_reg <= 0;
201  end
202  end
203  PipelineOutState_WaitPipeline: begin
204  // unhand the bus (don't want to block potential incoming) - be careful, this works instantly!
205  out_ep_req_reg <= 0;
206  if ( uart_out_ready ) begin
207  uart_out_valid_reg <= 0;
208  uart_out_data_reg <= 0;
209  pipeline_out_state <= PipelineOutState_Idle;
210  end
211 
212  end
213 
214  endcase
215  end
216  end
217 
218  // in endpoint control registers
219  reg in_ep_req_reg;
220  reg in_ep_data_done_reg;
221 
222  // in pipeline / in endpoint state machine state (4 states -> 2 bits)
223  reg [1:0] pipeline_in_state;
224 
225  localparam PipelineInState_Idle = 0;
226  localparam PipelineInState_WaitData = 1;
227  localparam PipelineInState_CycleData = 2;
228  localparam PipelineInState_WaitEP = 3;
229 
230  // connect the pipeline register to the outgoing port
231  assign uart_in_ready = ( pipeline_in_state == PipelineInState_CycleData ) && in_ep_data_free;
232 
233  // uart_in_valid and a buffer being ready is the request for the bus.
234  // It is granted automatically if available, and latched on by the SM.
235  // Note once requested, uart_in_valid may go on and off as data is available.
236  // When requested, connect the end point registers to the outgoing ports
237  assign in_ep_req = ( uart_in_valid && in_ep_data_free) || in_ep_req_reg;
238 
239  // Confirmation that the bus was granted
240  wire in_granted_in_valid = in_ep_grant && uart_in_valid;
241 
242  // Here are the things we use to get data sent
243  // ... put this word
244  assign in_ep_data_put = ( pipeline_in_state == PipelineInState_CycleData ) && uart_in_valid && in_ep_data_free;
245  // ... we're done putting - send the buffer
246  assign in_ep_data_done = in_ep_data_done_reg;
247  // ... the actual data, direct from the pipeline to the usb in buffer
248  assign in_ep_data = uart_in_data;
249 
250  // If we have a half filled buffer, send it after a while by using a timer
251  // 4 bits of counter, we'll just count up until bit 3 is high... 8 clock cycles seems more than enough to wait
252  // to send the packet
253  reg [TimeoutWidth:0] in_ep_timeout;
254 
255  // do PIPELINE IN, FPGA/Device OUT, Host IN
256  always @(posedge clk) begin
257  if ( reset ) begin
258  pipeline_in_state <= PipelineInState_Idle;
259  in_ep_req_reg <= 0;
260  in_ep_data_done_reg <= 0;
261  end else begin
262  case( pipeline_in_state )
263  PipelineInState_Idle: begin
264  in_ep_data_done_reg <= 0;
265  if ( in_granted_in_valid && in_ep_data_free ) begin
266  // got the bus, there is free space, now do the data
267  // confirm request bus - this will hold the request up until we're done with it
268  in_ep_req_reg <= 1;
269  pipeline_in_state <= PipelineInState_CycleData;
270  end
271  end
272  PipelineInState_CycleData: begin
273  if (uart_in_valid ) begin
274  if ( ~in_ep_data_free ) begin
275  // back to idle
276  pipeline_in_state <= PipelineInState_Idle;
277  // release the bus
278  in_ep_req_reg <= 0;
279  end
280  end else begin
281  // No valid character. Let's just pause for a second to see if any more are forthcoming.
282  // clear the timeout counter
283  in_ep_timeout <= 0;
284  pipeline_in_state <= PipelineInState_WaitData;
285  end
286  end
287  PipelineInState_WaitData: begin
288  in_ep_timeout <= in_ep_timeout + 1;
289  if ( uart_in_valid ) begin
290  pipeline_in_state <= PipelineInState_CycleData;
291  end else begin
292  // check for a timeout
293  if ( in_ep_timeout[ TimeoutWidth ] ) begin
294  in_ep_data_done_reg <= 1;
295  pipeline_in_state <= PipelineInState_WaitEP;
296  end
297  end
298  end
299 
300  PipelineInState_WaitEP: begin
301  // maybe done is ignored if putting?
302  in_ep_data_done_reg <= 0;
303 
304  // back to idle
305  pipeline_in_state <= PipelineInState_Idle;
306  // release the bus
307  in_ep_req_reg <= 0;
308  end
309  endcase
310  end
311  end
312 
313  assign debug = { in_ep_data_free, in_ep_data_done, pipeline_in_state[ 1 ], pipeline_in_state[ 0 ] };
314 
315 endmodule
module usb_uart_bridge_ep(input clk, input reset, output out_ep_req, input out_ep_grant, input out_ep_data_avail, input out_ep_setup, output out_ep_data_get, input[8] out_ep_data, output out_ep_stall, input out_ep_acked, output in_ep_req, input in_ep_grant, input in_ep_data_free, output in_ep_data_put, output[8] in_ep_data, output in_ep_data_done, output in_ep_stall, input in_ep_acked, input[8] uart_in_data, input uart_in_valid, output uart_in_ready, output[8] uart_out_data, output uart_out_valid, input uart_out_ready, output[4] debug)
always(posedge clk)
Definition: uart_rx.v:86