Merged r5033:5116 from developer branch jcorgan/snd, with minor edits. Trunk passes...
[debian/gnuradio] / gr-sounder / src / fpga / lib / sounder_rx.v
1 // -*- verilog -*-
2 //
3 //  USRP - Universal Software Radio Peripheral
4 //
5 //  Copyright (C) 2007 Corgan Enterprises LLC
6 //
7 //  This program is free software; you can redistribute it and/or modify
8 //  it under the terms of the GNU General Public License as published by
9 //  the Free Software Foundation; either version 2 of the License, or
10 //  (at your option) any later version.
11 //
12 //  This program is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //  GNU General Public License for more details.
16 //
17 //  You should have received a copy of the GNU General Public License
18 //  along with this program; if not, write to the Free Software
19 //  Foundation, Inc., 51 Franklin Street, Boston, MA  02110-1301  USA
20 //
21
22 module sounder_rx(clk_i,rst_i,ena_i,rx_strobe_i,tx_strobe_i,mask_i,len_i,
23                   rx_in_i_i,rx_in_q_i,rx_i_o,rx_q_o,rx_strobe_o);
24    
25    input         clk_i;         // Master clock
26    input         rst_i;         // Subsystem reset
27    input         ena_i;         // Subsystem enable
28    input         rx_strobe_i;   // Strobe every received sample
29    input         tx_strobe_i;   // Strobe every transmitted sample
30     
31    input  [15:0] mask_i;        // PN code LFSR mask
32    input  [15:0] len_i;         // PN code LFSR sequence length
33    input  [15:0] rx_in_i_i;     // I channel on receive
34    input  [15:0] rx_in_q_i;     // Q channel on receive
35
36    output [15:0] rx_i_o;        // I channel of impulse response
37    output [15:0] rx_q_o;        // Q channel of impulse response
38    output        rx_strobe_o;   // Impulse response value ready
39
40    // LFSR phase counter
41    reg [15:0] count;
42    wire cycle = (count == (len_i - 1));
43
44    always @(posedge clk_i)
45      if (rst_i | ~ena_i)
46        count <= 16'b0;
47      else
48        if (cycle)
49          count <= 16'b0;
50        else
51          count <= count + 16'b1;
52            
53    // Retard LFSR phase once per cycle
54    wire lfsr_strobe = (tx_strobe_i & ~cycle);
55
56    // Recreate local reference of transmitted PN code
57    wire pn;
58    lfsr reference
59      ( .clk_i(clk_i),.rst_i(rst_i),.ena_i(ena_i),.strobe_i(lfsr_strobe),.mask_i(mask_i),.pn_o(pn) );
60
61    wire [31:0] rx_i_ext, rx_q_ext;
62    sign_extend #(16,32) i_extend(rx_in_i_i, rx_i_ext);
63    sign_extend #(16,32) q_extend(rx_in_q_i, rx_q_ext);
64
65    reg [31:0] accum;
66    always @(posedge clk_i)
67      if (rst_i | ~ena_i)
68        accum <= 32'b0;
69      else
70        if (rx_strobe_i)
71          if (cycle)
72            accum <= 32'b0;
73          else
74            if (pn)
75              accum <= accum + rx_i_ext;
76            else
77              accum <= accum - rx_i_ext;
78    
79    assign rx_i_o = accum[31:16];
80    assign rx_q_o = accum[15:0];
81    assign rx_strobe_o = rx_strobe_i & cycle;
82
83 endmodule // sounder_rx
84