Merged r6329:6428 of features/inband-usb + distcheck fixes into trunk.
[debian/gnuradio] / usrp / fpga / inband_lib / channel_ram.v
1 module channel_ram 
2         ( // System
3         input txclk,
4         input reset,
5         
6         // USB side
7         input [31:0] datain, 
8         input WR, 
9         input WR_done,
10         output have_space,
11
12         // Reader side
13         output [31:0] dataout,
14         input RD,
15         input RD_done,
16         output packet_waiting);
17         
18         reg [6:0] wr_addr, rd_addr;
19         reg [1:0] which_ram_wr, which_ram_rd;
20         reg [2:0] nb_packets;
21         
22         reg [31:0] ram0 [0:127];
23         reg [31:0] ram1 [0:127];
24         reg [31:0] ram2 [0:127];
25         reg [31:0] ram3 [0:127];
26         
27         reg [31:0] dataout0;
28         reg [31:0] dataout1;
29         reg [31:0] dataout2;
30         reg [31:0] dataout3;
31         
32         wire wr_done_int;
33         wire rd_done_int;
34         wire [6:0] rd_addr_final;
35         wire [1:0] which_ram_rd_final;
36         
37         // USB side
38         always @(posedge txclk)
39                 if(WR & (which_ram_wr == 2'd0)) ram0[wr_addr] <= datain;
40                         
41         always @(posedge txclk)
42                 if(WR & (which_ram_wr == 2'd1)) ram1[wr_addr] <= datain;
43
44         always @(posedge txclk)
45                 if(WR & (which_ram_wr == 2'd2)) ram2[wr_addr] <= datain;
46
47         always @(posedge txclk)
48                 if(WR & (which_ram_wr == 2'd3)) ram3[wr_addr] <= datain;
49
50    assign wr_done_int = ((WR && (wr_addr == 7'd127)) || WR_done);
51    
52         always @(posedge txclk)
53                 if(reset)
54                         wr_addr <= 0;
55                 else if (WR_done)
56                         wr_addr <= 0;
57                 else if (WR) 
58                         wr_addr <= wr_addr + 7'd1;
59                 
60         always @(posedge txclk)
61                 if(reset)
62                         which_ram_wr <= 0;
63                 else if (wr_done_int) 
64                         which_ram_wr <= which_ram_wr + 2'd1;
65         
66         assign have_space = (nb_packets < 3'd3);
67                 
68         // Reader side
69         // short hand fifo
70         // rd_addr_final is what rd_addr is going to be next clock cycle
71         // which_ram_rd_final is what which_ram_rd is going to be next clock cycle
72         always @(posedge txclk)  dataout0 <= ram0[rd_addr_final];
73         always @(posedge txclk)  dataout1 <= ram1[rd_addr_final];
74         always @(posedge txclk)  dataout2 <= ram2[rd_addr_final];
75         always @(posedge txclk)  dataout3 <= ram3[rd_addr_final];
76         
77         assign dataout = (which_ram_rd_final[1]) ? 
78                                                 (which_ram_rd_final[0] ? dataout3 : dataout2) :
79                                                 (which_ram_rd_final[0] ? dataout1 : dataout0);
80
81         //RD_done is the only way to signal the end of one packet
82         assign rd_done_int = RD_done;   
83
84         always @(posedge txclk)
85                 if (reset)
86                         rd_addr <= 0;
87                 else if (RD_done)
88                         rd_addr <= 0;
89                 else if (RD) rd_addr <= rd_addr + 7'd1;
90                         
91         assign rd_addr_final = (reset|RD_done) ? (6'd0) : 
92                                 ((RD)?(rd_addr+7'd1):rd_addr); 
93         always @(posedge txclk)
94            if (reset)
95                         which_ram_rd <= 0;
96                 else if (rd_done_int)
97                         which_ram_rd <= which_ram_rd + 2'd1;
98
99         assign which_ram_rd_final = (reset) ? (2'd0):
100                                ((rd_done_int) ? (which_ram_rd + 2'd1) : which_ram_rd);
101                                 
102         //packet_waiting is set to zero if rd_done_int is high
103         //because there is no guarantee that nb_packets will be pos.
104         //assign packet_waiting = (nb_packets != 0) & (~rd_done_int);
105         assign packet_waiting = (nb_packets > 1) | ((nb_packets == 1)&(~rd_done_int));
106         always @(posedge txclk)
107                 if (reset)
108                         nb_packets <= 0;
109                 else if (wr_done_int & ~rd_done_int)
110                         nb_packets <= nb_packets + 3'd1;
111                 else if (rd_done_int & ~wr_done_int)
112                         nb_packets <= nb_packets - 3'd1;
113                         
114 endmodule