SPI_Test/rtl/modem/freqmod.v

337 lines
11 KiB
Verilog

// Relese History
// Version Date Author Description
// 1.1 2024-04-08 ZYZ
//-----------------------------------------------------------------------------------------------------------------
// Keywords : 1.add Env_vld
// 2.add Mod_vld
// 3.change the use of Mod_enable
// 4.divide modem into FM and AM
//
//
//
//
//-----------------------------------------------------------------------------------------------------------------
// Parameter
//
//-----------------------------------------------------------------------------------------------------------------
// Purpose :
//
//-----------------------------------------------------------------------------------------------------------------
// Target Device:
// Tool versions:
//-----------------------------------------------------------------------------------------------------------------
// Reuse Issues
// Reset Strategy:
// Clock Domains:
// Critical Timing:
// Asynchronous I/F:
// Synthesizable (y/n):
// Other:
//-FHDR--------------------------------------------------------------------------------------------------------
module freqmod (
//System Signal
input Dig_Clk //Module Clock
,input Dig_Resetn //Module Reset Signal
//Envelope Data
,input signed [15:0] Env_Idata //env_i is signed (two's complement)
,input signed [15:0] Env_Qdata //env_q is signed (two's complement)
,input Env_Vld //env data is vld
//Nco data
,input signed [15:0] Nco_Sin //nco_sin is signed (two's complement)
,input signed [15:0] Nco_Cos //nco_cos is signed (two's complement)
//Config Signal
,input Mod_Sideband_Sel //1'b0: Mod_data_i = Icoswd+Qsinwd, Mod_data_q = -Isinwd+Qcoswd
//1'b1: Mod_data_i = Icoswd-Qsinwd, Mod_data_q = Isinwd+Qcoswd
,input Mod_Enable //1'b0: disable Modem,1'b1:enable modem
//Output modem data
,output signed [15:0] Mod_Data_I //Modem output data for I
,output signed [15:0] Mod_Data_Q //Modem output data for Q
,output Mod_Vld //Modem output data vld
);
//////////////////////////////////////////////////////////////
// Wire & reg
//////////////////////////////////////////////////////////////
//The temporary result Regs of a multiplication operation.
wire signed [31:0] mult_isin_tmp;
wire signed [31:0] mult_icos_tmp;
wire signed [31:0] mult_qsin_tmp;
wire signed [31:0] mult_qcos_tmp;
//The processing of a multiplication result.
wire signed [15:0] mult_isin_w;
wire signed [15:0] mult_icos_w;
wire signed [15:0] mult_qsin_w;
wire signed [15:0] mult_qcos_w;
//The multiplier processing result register.
reg signed [15:0] mult_isin_r;
reg signed [15:0] mult_icos_r;
reg signed [15:0] mult_qsin_r;
reg signed [15:0] mult_qcos_r;
//Temporary storage of IQ data.
wire signed [16:0] adder0_icosqsin_tmp;
wire signed [16:0] adder1_isinqcos_tmp;
//Output of IQ data stored in registers.
reg signed [15:0] adder0_icosqsin_r;
reg signed [15:0] adder1_isinqcos_r;
//Modulation data valid flag Regs.
reg [7 :0] freqmod_data_vld_dly;
//shifting register,Env_Idata
reg signed [15:0] Env_Idata_r1;
reg signed [15:0] Env_Idata_r2;
reg signed [15:0] Env_Idata_r3;
reg signed [15:0] Env_Idata_r4;
always @(posedge Dig_Clk or negedge Dig_Resetn) begin
if(!Dig_Resetn)
begin
Env_Idata_r1 <= 16'b0;
Env_Idata_r2 <= 16'b0;
Env_Idata_r3 <= 16'b0;
Env_Idata_r4 <= 16'b0;
end
else if(~Mod_Enable)
begin
Env_Idata_r1 <= 16'b0;
Env_Idata_r2 <= Env_Idata_r1;
Env_Idata_r3 <= Env_Idata_r2;
Env_Idata_r4 <= Env_Idata_r3;
end
else begin
Env_Idata_r1 <= Env_Idata;
Env_Idata_r2 <= Env_Idata_r1;
Env_Idata_r3 <= Env_Idata_r2;
Env_Idata_r4 <= Env_Idata_r3;
end
end
//shifting register,Env_Qdata
reg signed [15:0] Env_Qdata_r1;
reg signed [15:0] Env_Qdata_r2;
reg signed [15:0] Env_Qdata_r3;
reg signed [15:0] Env_Qdata_r4;
always @(posedge Dig_Clk or negedge Dig_Resetn) begin
if(!Dig_Resetn)
begin
Env_Qdata_r1 <= 16'b0;
Env_Qdata_r2 <= 16'b0;
Env_Qdata_r3 <= 16'b0;
Env_Qdata_r4 <= 16'b0;
end
else if(~Mod_Enable)
begin
Env_Qdata_r1 <= 16'b0;
Env_Qdata_r2 <= Env_Qdata_r1;
Env_Qdata_r3 <= Env_Qdata_r2;
Env_Qdata_r4 <= Env_Qdata_r3;
end
else begin
Env_Qdata_r1 <= Env_Qdata;
Env_Qdata_r2 <= Env_Qdata_r1;
Env_Qdata_r3 <= Env_Qdata_r2;
Env_Qdata_r4 <= Env_Qdata_r3;
end
end
//////////////////////////////////////////////////////////////
// Orthogonal modulation
//////////////////////////////////////////////////////////////
//DW_mult_pipe Instantiation -> Env_Idata * Nco_Sin
DW_mult_pipe #(
.a_width ( 16 )
,.b_width ( 16 )
,.num_stages ( 3 )
,.stall_mode ( 0 )
,.rst_mode ( 1 )
,.op_iso_mode ( 0 )
) inst_isin_mult (
.clk ( Dig_Clk )
,.rst_n ( Dig_Resetn )
,.en ( 1'b1 )
,.a ( Env_Idata_r4 )
,.b ( Nco_Sin )
,.tc ( 1'b1 )
,.product ( mult_isin_tmp )
);
//DW_mult_pipe Instantiation -> Env_Idata * Nco_Cos
DW_mult_pipe #(
.a_width ( 16 )
,.b_width ( 16 )
,.num_stages ( 3 )
,.stall_mode ( 0 )
,.rst_mode ( 1 )
,.op_iso_mode ( 0 )
) inst_icos_mult (
.clk ( Dig_Clk )
,.rst_n ( Dig_Resetn )
,.en ( 1'b1 )
,.a ( Env_Idata_r4 )
,.b ( Nco_Cos )
,.tc ( 1'b1 )
,.product ( mult_icos_tmp )
);
//DW_mult_pipe Instantiation -> Env_Qdata * Nco_Sin
DW_mult_pipe #(
.a_width ( 16 )
,.b_width ( 16 )
,.num_stages ( 3 )
,.stall_mode ( 0 )
,.rst_mode ( 1 )
,.op_iso_mode ( 0 )
) inst_qsin_mult (
.clk ( Dig_Clk )
,.rst_n ( Dig_Resetn )
,.en ( 1'b1 )
,.a ( Env_Qdata_r4 )
,.b ( Nco_Sin )
,.tc ( 1'b1 )
,.product ( mult_qsin_tmp )
);
//DW_mult_pipe Instantiation -> Env_Qdata * Nco_Cos
DW_mult_pipe #(
.a_width ( 16 )
,.b_width ( 16 )
,.num_stages ( 3 )
,.stall_mode ( 0 )
,.rst_mode ( 1 )
,.op_iso_mode ( 0 )
) inst_qcos_mult (
.clk ( Dig_Clk )
,.rst_n ( Dig_Resetn )
,.en ( 1'b1 )
,.a ( Env_Qdata_r4 )
,.b ( Nco_Cos )
,.tc ( 1'b1 )
,.product ( mult_qcos_tmp )
);
//////////////////////////////////////////////////////////////
// The processing of a multiplication result.
//////////////////////////////////////////////////////////////
assign mult_isin_w = {mult_isin_tmp[31],mult_isin_tmp[29:15]} +mult_isin_tmp[14];
assign mult_icos_w = {mult_icos_tmp[31],mult_icos_tmp[29:15]} +mult_icos_tmp[14];
assign mult_qsin_w = {mult_qsin_tmp[31],mult_qsin_tmp[29:15]} +mult_qsin_tmp[14];
assign mult_qcos_w = {mult_qcos_tmp[31],mult_qcos_tmp[29:15]} +mult_qcos_tmp[14];
//////////////////////////////////////////////////////////////
// The multiplier processing result register.
//////////////////////////////////////////////////////////////
//mult_isin_r
always @(posedge Dig_Clk or negedge Dig_Resetn) begin
if(Dig_Resetn == 1'b0) begin
mult_isin_r <= 16'd0;
end
else begin
mult_isin_r <= mult_isin_w;
end
end
//mult_icos_r
always @(posedge Dig_Clk or negedge Dig_Resetn) begin
if(Dig_Resetn == 1'b0) begin
mult_icos_r <= 16'd0;
end
else begin
mult_icos_r <= mult_icos_w;
end
end
//mult_qsin_r
always @(posedge Dig_Clk or negedge Dig_Resetn) begin
if(Dig_Resetn == 1'b0) begin
mult_qsin_r <= 16'd0;
end
else begin
mult_qsin_r <= mult_qsin_w;
end
end
//mult_qcos_r
always @(posedge Dig_Clk or negedge Dig_Resetn) begin
if(Dig_Resetn == 1'b0) begin
mult_qcos_r <= 16'd0;
end
else begin
mult_qcos_r <= mult_qcos_w;
end
end
//////////////////////////////////////////////////////////////
// Orthogonal modulation
//////////////////////////////////////////////////////////////
assign adder0_icosqsin_tmp = ~Mod_Sideband_Sel ? (mult_icos_r + mult_qsin_r):(mult_icos_r - mult_qsin_r);
//1'b0: adder0_icosqsin_tmp = Icoswd+Qsinwd, 1'b1:adder0_icosqsin_tmp = Icoswd-Qsinwd
assign adder1_isinqcos_tmp = Mod_Sideband_Sel ? (mult_isin_r + mult_qcos_r):(-mult_isin_r + mult_qcos_r);
//1'b0: adder1_isinqcos_tmp = Isinwd+Qcoswd, 1'b1:adder1_isinqcos_tmp = -Isinwd+Qcoswd
//////////////////////////////////////////////////////////////
// Output of IQ data stored in registers.
//////////////////////////////////////////////////////////////
always @(posedge Dig_Clk or negedge Dig_Resetn) begin
if(Dig_Resetn == 1'b0) begin
adder0_icosqsin_r <= 16'd0;
end
else if(adder0_icosqsin_tmp[16:15] == 2'b01)begin
adder0_icosqsin_r <= 32767;
end
else if (adder0_icosqsin_tmp[16:15] == 2'b10)begin
adder0_icosqsin_r <= -32768;
end
else begin
adder0_icosqsin_r <= {adder0_icosqsin_tmp[16],adder0_icosqsin_tmp[14:0]};
end
end
always @(posedge Dig_Clk or negedge Dig_Resetn) begin
if(Dig_Resetn == 1'b0) begin
adder1_isinqcos_r <= 16'd0;
end
else if (adder1_isinqcos_tmp[16:15] == 2'b01)begin
adder1_isinqcos_r <= 32767;
end
else if (adder1_isinqcos_tmp[16:15] == 2'b10)begin
adder1_isinqcos_r <= -32768;
end
else begin
adder1_isinqcos_r <= {adder1_isinqcos_tmp[16],adder1_isinqcos_tmp[14:0]};
end
end
assign Mod_Data_I = adder0_icosqsin_r;
assign Mod_Data_Q = adder1_isinqcos_r;
//////////////////////////////////////////////////////////////
// Generation of Mod_Vld signal.
//////////////////////////////////////////////////////////////
//mod_data_vld_dly
always @(posedge Dig_Clk or negedge Dig_Resetn) begin
if(Dig_Resetn == 1'b0) begin
freqmod_data_vld_dly <= 8'b0;
end
else begin
freqmod_data_vld_dly <= {freqmod_data_vld_dly[6:0], Mod_Enable & Env_Vld};
end
end
assign Mod_Vld = freqmod_data_vld_dly[7];
endmodule