// Jeff Mock // 2030 Gough St. // San Francisco, CA 94109 // jeff@mock.com // // Copyright 2005,2006 // // \$URL: https://www.mock.com/svn/pdev/trunk/gx/sp/src/stokes.v \$ // \$Id: stokes.v 913 2007-02-24 01:09:40Z jeff \$ // Take output of PFB, and upshift 0..7 bits with saturation // and calculate the four stokes parameters. // // This is from a conversation with Aaron Parsons about // calculating stokes parameters. I think I will blame this // all on Aaron if the calculation is not correct... I've // rearranged the terms for s3 from the original emails // with Aaron to save a subtract and it looks a little // cleaner. // // The four Stokes parameters are as follows. A and B are // complex signals from the two polarities of the antenna: // I = AA* + BB* Total power // Q = AA* - BB* // U = AB* + BA* // V = j(AB* - BA*) // // I'll use the following definitions for scalar fixed point // calculations: // A = a0 + a1j // B = b0 + b1j // // AA* = (a0 + a1j) ( a0 - a1j) = a0a0 + a1a1 // BB* = (b0 + b1j) ( b0 - b1j) = b0b0 + b1b1 // AB* = (a0 + a1j) ( b0 - b1j) = (a0b0 + a1b1) + j (a1b0 - a0b1) // BA* = (b0 + b1j) ( a0 - a1j) = (a0b0 + a1b1) + j (a0b1 - a1b0) // // Integrate the following scalars: // s0 = AA* = a0a0 + a1a1 (unsigned) // s1 = BB* = b0b0 + b1b1 (unsigned) // s2 = Re(AB*) = Re(BA*) = a0b0 + a1b1 // s3 = -Im(AB*) = Im(BA*) = a0b1 - a1b0 // // These correspond to: // AA* = s0 // BB* = s1 // AB* = s2 - j s3 // BA* = s2 + j s3 // // After integration compute the four stokes parameters: // I = AA* + BB* // Q = AA* - BB* // U = AB* + BA* // V = j(AB* - BA*) // // I = s0 + s1 // Q = s0 - s1 // U = (s2 - s3j) + (s2 + s3j) = 2*s2 // V = j((s2 - s3j) - (s2 + s3j)) = 2*s3 // // I scale the whole thing by 0.5 so it looks a little cleaner: // I = (s0 + s1)/2 // Q = (s0 - s1)/2 // U = s2 // V = s3 // // So, this module computes s0,s1,s2,s3 prior to integration, these // can be used after integration to calculation the four stokes // parameters. // // In the code I use different names to match the rest of the datapath, // something like: // a0 = r_pola // a1 = i_pola // b0 = r_polb // b1 = i_polb // `define STOKES_DEL 7 module stokes ( ck, shift, r_pola, i_pola, r_polb, i_polb, sync_del, s0, s1, s2, s3, sync_stokes, vshift_sat ); input ck; input [2:0] shift; input [`N_PFB-1:0] r_pola; input [`N_PFB-1:0] i_pola; input [`N_PFB-1:0] r_polb; input [`N_PFB-1:0] i_polb; input sync_del; output [`N_MUL-1:0] s0; output [`N_MUL-1:0] s1; output [`N_MUL-1:0] s2; output [`N_MUL-1:0] s3; output sync_stokes; output vshift_sat; reg vshift_sat; reg [2:0] shift_d1; always @(posedge ck) shift_d1 <= shift; reg [`STOKES_DEL-1:0] sdel; always @(posedge ck) sdel <= { sdel[`STOKES_DEL-2:0], sync_del }; assign sync_stokes = sdel[`STOKES_DEL-1]; // Upshift pola signals 0..7 bits wire [`N_PFB-1:0] r_pola_sft; wire [`N_PFB-1:0] i_pola_sft; wire r_pola_sat; wire i_pola_sat; vshift sft_r_pola ( .ck ( ck ), .shift ( shift_d1 ), .a ( r_pola ), .sat ( r_pola_sat ), .x ( r_pola_sft ) ); vshift sft_i_pola ( .ck ( ck ), .shift ( shift_d1 ), .a ( i_pola ), .sat ( i_pola_sat ), .x ( i_pola_sft ) ); // Upshift polb signals 0..7 bits wire [`N_PFB-1:0] r_polb_sft; wire [`N_PFB-1:0] i_polb_sft; wire r_polb_sat; wire i_polb_sat; vshift sft_r_polb ( .ck ( ck ), .shift ( shift_d1 ), .a ( r_polb ), .sat ( r_polb_sat ), .x ( r_polb_sft ) ); vshift sft_i_polb ( .ck ( ck ), .shift ( shift_d1 ), .a ( i_polb ), .sat ( i_polb_sat ), .x ( i_polb_sft ) ); always @(posedge ck) vshift_sat <= r_pola_sat | i_pola_sat | r_polb_sat | i_polb_sat; // The four products for s0 and s1, these results are all positive // since it's n^2. // wire [`N_MUL-1:0] raxra; wire [`N_MUL-1:0] iaxia; wire [`N_MUL-1:0] rbxrb; wire [`N_MUL-1:0] ibxib; smult m_raxra ( .ck ( ck ), .a ( r_pola_sft ), .b ( r_pola_sft ), .y ( raxra ) ); smult m_iaxia ( .ck ( ck ), .a ( i_pola_sft ), .b ( i_pola_sft ), .y ( iaxia ) ); smult m_rbxrb ( .ck ( ck ), .a ( r_polb_sft ), .b ( r_polb_sft ), .y ( rbxrb ) ); smult m_ibxib ( .ck ( ck ), .a ( i_polb_sft ), .b ( i_polb_sft ), .y ( ibxib ) ); `ifdef N_FULL_STOKES // The four cross products for s2 and s3, These are // signed results. // wire [`N_MUL-2:0] raxrb; wire [`N_MUL-2:0] iaxib; wire [`N_MUL-2:0] raxib; wire [`N_MUL-2:0] iaxrb; smult1 m_raxrb ( .ck ( ck ), .a ( r_pola_sft ), .b ( r_polb_sft ), .y ( raxrb ) ); smult1 m_iaxib ( .ck ( ck ), .a ( i_pola_sft ), .b ( i_polb_sft ), .y ( iaxib ) ); smult1 m_raxib ( .ck ( ck ), .a ( r_pola_sft ), .b ( i_polb_sft ), .y ( raxib ) ); smult1 m_iaxrb ( .ck ( ck ), .a ( i_pola_sft ), .b ( r_polb_sft ), .y ( iaxrb ) ); `endif reg [`N_MUL-1:0] s0; reg [`N_MUL-1:0] s1; always @(posedge ck) begin // The partial products are positive and we are going to // store s0,s1 as unsigned integers to gain an extra bit // of precision. So, this add takes place without an // extra bit, the sign bits of the partials is zero and // serves as the high bit of the unsigned value after the // add. s0 <= raxra + iaxia; s1 <= rbxrb + ibxib; end `ifdef N_FULL_STOKES reg [`N_MUL-1:0] s2; reg [`N_MUL-1:0] s3; always @(posedge ck) begin // These are signed, sign extend one bit longer to prevent // overflow. s2 <= {raxrb[`N_MUL-2], raxrb} + {iaxib[`N_MUL-2], iaxib}; s3 <= {raxib[`N_MUL-2], raxib} - {iaxrb[`N_MUL-2], iaxrb}; end `else wire [`N_MUL-1:0] s2; wire [`N_MUL-1:0] s3; assign s2 = `N_MUL'b0; assign s3 = `N_MUL'b0; `endif endmodule