summaryrefslogtreecommitdiffstats
path: root/fpga/usrp2/custom/power_trig.v
blob: b3805903020b44e5939fa41a7f70cf85073c51ae (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
//
// Copyright 2012 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

// This a power trigger module implemented on top of the custom dsp template.
// Power triggering is implemented after the existing DDC chain.
// Triggering is controlled via user settings registers.

// Register 0:
//  threshold for power trigger
//  32 bit unsigned fixed-point number of some arbitrary scaling

module power_trig
#(
    //frontend bus width
    parameter WIDTH = 24,
    parameter BASE = 0
)
(
    //control signals
    input clock, //dsp clock
    input reset, //active high synchronous reset
    input clear, //active high on packet control init
    input enable, //active high when streaming enabled

    //user settings bus, controlled through user setting regs API
    input set_stb, input [7:0] set_addr, input [31:0] set_data,

    //full rate inputs directly from the RX frontend
    input [WIDTH-1:0] frontend_i,
    input [WIDTH-1:0] frontend_q,

    //full rate outputs directly to the DDC chain
    output [WIDTH-1:0] ddc_in_i,
    output [WIDTH-1:0] ddc_in_q,

    //strobed samples {I16,Q16} from the RX DDC chain
    input [31:0] ddc_out_sample,
    input ddc_out_strobe, //high on valid sample
    output ddc_out_enable, //enables DDC module

    //strobbed baseband samples {I16,Q16} from this module
    output [31:0] bb_sample,
    output bb_strobe //high on valid sample
);

    //leave frontend tied to existing ddc chain
    assign ddc_in_i = frontend_i;
    assign ddc_in_q = frontend_q;

    //ddc enable remains tied to global enable
    assign ddc_out_enable = enable;

    //below we implement a power trigger between baseband samples and ddc output...

   reg [8:0] 	  wr_addr;
   wire [8:0] 	  rd_addr;
   reg 		  triggered, triggerable;
   wire 	  trigger;
   
   wire [31:0] 	  delayed_sample;
   wire [31:0] 	  thresh;
   
   setting_reg #(.my_addr(BASE+0)) sr_0
     (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
      .in(set_data),.out(thresh),.changed());

   assign rd_addr = wr_addr + 1; // FIXME adjustable delay

   ram_2port  #(.DWIDTH(32),.AWIDTH(9)) delay_line
     (.clka(clk),.ena(1),.wea(ddc_out_strobe),.addra(wr_addr),.dia(ddc_out_sample),.doa(),
      .clkb(clk),.enb(ddc_out_strobe),.web(1'b0),.addrb(rd_addr),.dib(32'hFFFF),.dob(delayed_sample));

   always @(posedge clock)
     if(reset | ~enable)
       wr_addr <= 0;
     else
       if(ddc_out_strobe)
	 wr_addr <= wr_addr + 1;

   always @(posedge clock)
     if(reset | ~enable)
       triggerable <= 0;
     else if(wr_addr == 9'h1FF)  // Wait till we're nearly full
       triggerable <= 1;
   

   reg 			      stb_d1, stb_d2;
   always @(posedge clock) stb_d1 <= ddc_out_strobe;
   always @(posedge clock) stb_d2 <= stb_d1;
   
   assign bb_sample = delayed_sample;
   assign bb_strobe = stb_d1 & triggered;

   // Compute Mag
   wire [17:0] 		      mult_in = stb_d1 ? { ddc_out_sample[15],ddc_out_sample[15:0], 1'b0 } : 
			      { ddc_out_sample[31], ddc_out_sample[31:16], 1'b0 };
   wire [35:0] 		      prod;
   reg [31:0] 		      sum;
   
   MULT18X18S mult (.P(prod), .A(mult_in), .B(mult_in), .C(clock), .CE(ddc_out_strobe | stb_d1), .R(reset) );

   always @(posedge clock)
     if(stb_d1)
       sum <= prod[35:4];
     else if(stb_d2)
       sum <= sum + prod[35:4];

   always @(posedge clock)
     if(reset | ~enable | ~triggerable)
       triggered <= 0;
     else if(trigger)
       triggered <= 1;

   assign trigger = (sum > thresh);
   
endmodule // power_trig