summaryrefslogtreecommitdiff
path: root/usrp/fpga/inband_lib/usb_fifo_writer.v
blob: abe1dd5678d1f35603ae3111df1e9fcafce5fc49 (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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183

module usb_fifo_writer
   #(parameter BUS_WIDTH = 16,
     parameter NUM_CHAN = 2,
     parameter FIFO_WIDTH = 32)
   (     //FX2 Side
			input bus_reset, 
			input usbclk, 
			input WR_fx2, 
			input [15:0]usbdata,
			
			// TX Side
			input reset,
			input txclk,
			output reg [NUM_CHAN:0] WR_channel,
			output reg [FIFO_WIDTH-1:0] ram_data,
			output reg [NUM_CHAN:0] WR_done_channel );
   

	reg [8:0] write_count;

	/* Fix FX2 bug */
	always @(posedge usbclk)
    	if(bus_reset)        // Use bus reset because this is on usbclk
       		write_count <= #1 0;
    	else if(WR_fx2 & ~write_count[8])
    		write_count <= #1 write_count + 9'd1;
    	else
    		write_count <= #1 WR_fx2 ? write_count : 9'b0;

	reg WR_fx2_fixed;
	reg [15:0]usbdata_fixed;
	
	always @(posedge usbclk) 
	begin
	   WR_fx2_fixed <= WR_fx2 & ~write_count[8];
	   usbdata_fixed <= usbdata;
	end

	/* Used to convert 16 bits bus_data to the 32 bits wide fifo */
    reg                             word_complete ;
    reg     [BUS_WIDTH-1:0]         usbdata_delayed ;
    reg                             writing ;
	wire	[FIFO_WIDTH-1:0]		usbdata_packed ;    
	wire							WR_packed ;
   
    always @(posedge usbclk)
    begin
        if (bus_reset)
          begin
            word_complete <= 0 ;
            writing <= 0 ;
          end
        else if (WR_fx2_fixed)
          begin
            writing <= 1 ;
            if (word_complete)
                word_complete <= 0 ;
            else
              begin
                usbdata_delayed <= usbdata_fixed ;
                word_complete <= 1 ;
              end
          end
        else
            writing <= 0 ;
	end
    
	assign usbdata_packed = {usbdata_fixed, usbdata_delayed} ;
    assign WR_packed = word_complete & writing ;

	/* Make sure data are sync with usbclk */
 	reg [31:0]usbdata_usbclk;
	reg WR_usbclk; 
    
    always @(posedge usbclk)
    begin
    	if (WR_packed)
    		usbdata_usbclk <= usbdata_packed;
        WR_usbclk <= WR_packed;
    end

	/* Cross clock boundaries */
	reg [FIFO_WIDTH-1:0] usbdata_tx ;
	reg WR_tx;
    reg WR_1;
    reg WR_2;
	reg [31:0] usbdata_final;
	reg WR_final;
   
	always @(posedge txclk) usbdata_tx <= usbdata_usbclk;

    always @(posedge txclk) 
    	if (reset)
    		WR_1 <= 0;
    	else
       		WR_1 <= WR_usbclk;

    always @(posedge txclk) 
    	if (reset)
       		WR_2 <= 0;
    	else
      		WR_2 <= WR_1;

	always @(posedge txclk)
	begin
		if (reset)
			WR_tx <= 0;
		else
		   WR_tx <= WR_1 & ~WR_2;
	end
	
	always @(posedge txclk)
	begin
	   if (reset)
	      WR_final <= 0;
	   else
	   begin
	      WR_final <= WR_tx; 
	      if (WR_tx)
	         usbdata_final <= usbdata_tx;
	   end
	end
	     
	/* Parse header and forward to ram */
	reg [3:0]reader_state;
	reg [4:0]channel ;
	reg [9:0]read_length ;
	
	parameter IDLE = 4'd0;
	parameter HEADER = 4'd1;
	parameter WAIT = 4'd2;
	parameter FORWARD = 4'd3;
	
	`define CHANNEL 20:16
	`define PKT_SIZE 512
	
	always @(posedge txclk)
	begin
	    if (reset)
	      begin
	       reader_state <= 0;
	       WR_channel <= 0;
	       WR_done_channel <= 0;
	      end
	      else
	        case (reader_state)
	        IDLE: begin
	            if (WR_final)
	                reader_state <= HEADER; 
	            end
	       
            // Store channel and forware header
	        HEADER: begin
	            channel <= (usbdata_final[`CHANNEL] == 5'h1f ? NUM_CHAN : usbdata_final[`CHANNEL]) ;
	            WR_channel[(usbdata_final[`CHANNEL] == 5'h1f ? NUM_CHAN : usbdata_final[`CHANNEL])] <= 1;
				//channel <= usbdata_final[`CHANNEL] ;
	            //WR_channel[usbdata_final[`CHANNEL]] <= 1;
	            ram_data <= usbdata_final;
				read_length <= 10'd4 ;
				
                reader_state <= WAIT;
	        end
	       
	        WAIT: begin
	           WR_channel[channel] <= 0;
	
			   if (read_length == `PKT_SIZE)
	               reader_state <= IDLE;
	           else if (WR_final)
	               reader_state <= FORWARD;
	        end
	       
	        FORWARD: begin
	           WR_channel[channel] <= 1;
	           ram_data <= usbdata_final;
	           read_length <= read_length + 10'd4;
	           
	           reader_state <= WAIT;
	        end
	       endcase
	end
endmodule