aboutsummaryrefslogtreecommitdiffstats
path: root/inband_lib/usb_fifo_reader.v
blob: 170c70fd497ee304f73e2b03b60e6209099ba7b5 (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
131
132
133
134
135
module usb_fifo_reader (tx_clock, fifodata, pkt_waiting, reset,
      rdreq, skip, done_chan, WR_chan, tx_data_bus);
      
    /* Module parameters */
    parameter                       NUM_CHAN      =   2 ;
    parameter                       WIDTH         =   32 ;
    
    input   wire                    tx_clock ;
    input   wire                    reset ;
    input   wire       [WIDTH-1:0]  fifodata ;
    input   wire                    pkt_waiting ;
    output  reg                     rdreq ;
    output  reg                     skip ;
    output  reg        [NUM_CHAN:0] done_chan ;
    output  reg        [NUM_CHAN:0] WR_chan ;
    output  reg        [WIDTH-1:0]  tx_data_bus ;
     
   
   
    /* States definition */
    `define IDLE                      3'd0
    `define WAIT                      3'd1
    `define READ_HEADER               3'd2
    `define FORWARD_DATA              3'd3
    `define SKIP_REST                 3'd4
   
    /* Channel Ids */
    `define TXCHAN0                   5'h0
    `define TXCHAN1                   5'h1
    `define TXCMD                     5'h1F
   
    /* Local registers */
    reg                      [2:0]    reader_state ;
    reg                      [2:0]    reader_next_state ;
    reg                      [4:0]    channel ;
    reg                      [8:0]    pkt_length ;
    reg                      [8:0]    read_length ;
    
    /* State Machine */
    always @(posedge tx_clock)
    begin
        if (reset) 
		  begin
		      reader_state <= `IDLE ;
            reader_next_state <= `IDLE ;
            rdreq <= 0 ;
            skip <= 0 ;
            WR_chan <= {NUM_CHAN+1{1'b0}} ;
            done_chan <= {NUM_CHAN+1{1'b0}} ;
          end
        else 
		  begin
            reader_state = reader_next_state ;
            
            case(reader_state)
            `IDLE: 
				begin
				    reader_next_state <= pkt_waiting ? `WAIT : `IDLE ;
                rdreq <= pkt_waiting ;
            end
     
            /* Wait for the fifo's data to show up */
            `WAIT:
            begin
			       reader_next_state <= `READ_HEADER ;
            end
               
            `READ_HEADER: 
			   begin
                reader_next_state <= `FORWARD_DATA ;
                  
                /* Read header fields */
                channel <= (fifodata & 32'h1F0000) ;
                pkt_length <= (fifodata & 16'h1FF) + 4 ;
                read_length <= 9'd0 ;
                  
                /* Forward data */
                case (channel)
                    `TXCHAN0: WR_chan[0] <= 1 ;
                    `TXCHAN1: WR_chan[1] <= 1 ;
                    `TXCMD:   WR_chan[2] <= 1 ;
                    default:  WR_chan <= 1 ;
                endcase
                tx_data_bus <= fifodata ;
            end
               
            `FORWARD_DATA:
			   begin
                read_length <= read_length + 4 ;
                  
                // If end of payload...
                if (read_length == pkt_length)
				    begin
                    reader_next_state <= `SKIP_REST ;
                    /* If the packet is 512 bytes, don't skip */
                    skip <= pkt_length < 506 ;
                     
                    /* Data pushing done */
                    WR_chan <= {NUM_CHAN+1{1'b0}} ;
                    
                    /* Notify next block */
                    case (channel)
                       `TXCHAN0: done_chan[0] <= 1 ;
                       `TXCHAN1: done_chan[1] <= 1 ;
                       `TXCMD:   done_chan[2] <= 1 ;
                       default:  done_chan[0] <= 1 ;
                    endcase
                end
                else if (read_length == pkt_length - 4)
                    rdreq <= 0 ;
                    
                /* Forward data */
                tx_data_bus <= fifodata ;
            end
               
            `SKIP_REST: 
			   begin
			       reader_next_state <= pkt_waiting ? `READ_HEADER : `IDLE ;
                done_chan <= {NUM_CHAN+1{1'b0}} ;
                rdreq <= pkt_waiting ;
                skip <= 0 ;
            end
                
            default: 
			   begin
                reader_state <= `IDLE;
                reader_next_state <= `IDLE;
            end
            endcase
        end
    end  
endmodule