| /* ASTECAS projet | |
| * CINVESTAV-GLD | |
| * ITESM-GDL | |
| * RHALL-TECH | |
| *-------------------------------------------------- | |
| * | |
| * Programer: MSc Abisai Ramirez Perez (abramirez@gdl.cinvestav.mx) | |
| * Filename : OQPSK_PS_RCOSINE.v | |
| * Type : Verilog Module | |
| * | |
| * Description: | |
| * This module is the transmitter of OQPSK, which uses a fix bitrate and raised cosine pulse shaping filter | |
| * Version : 1.0 | |
| * Data : march 2018 | |
| * Revision : - | |
| * Reviser : - | |
| * | |
| *-------------------------------------------------- | |
| * Modification Log "please register all the modifications in this area" | |
| * Update: Module edited for RCOSINE pulse shaping | |
| * Programmer: Luis Adolfo Luna RodrÃguez - September 2017 | |
| * Update V1.0: Module edited for OpenLane process - LALR Oct 2022 | |
| * | |
| */ | |
| module OQPSK_PS_RCOSINE2 | |
| #(parameter | |
| DW_IN = 13, // Output bits | |
| I_SEL = 01, // Integer bits | |
| SAMPLES = 02, // Samples per symbol | |
| PS_SAMPLES = 50 // Samples of the pulse shaping | |
| ) | |
| ( | |
| `ifdef USE_POWER_PINS | |
| inout vccd1, // User area 1 1.8V supply | |
| inout vssd1, // User area 1 digital ground | |
| `endif | |
| input CLK , // Clock | |
| input RST , // Reset low active | |
| input EN , // Enable | |
| input BitIn , // Incoming Bitstream | |
| output signed [(DW_IN-I_SEL):I_SEL-1] I, // In-phase component | |
| output signed [(DW_IN-I_SEL):I_SEL-1] Q, // Quadrature component | |
| output [5:0] addI, | |
| output [5:0] addQ | |
| ); | |
| wire En_1M; | |
| wire En_1M_dly; | |
| wire En_2M; | |
| wire wi_b2r; | |
| wire [SAMPLES-1:0] wi_Reg2Rom; | |
| wire wi_Reg2Rom_delay; | |
| wire [I_SEL-2:-(DW_IN-I_SEL)] I_ROM; | |
| wire [I_SEL-1:-(DW_IN-I_SEL)] I_Cmplted; | |
| wire [I_SEL-2:-(DW_IN-I_SEL)] Q_ROM; | |
| wire [I_SEL-1:-(DW_IN-I_SEL)] Q_Cmplted; | |
| wire [$clog2(PS_SAMPLES)-1:0] addressI; | |
| wire [$clog2(PS_SAMPLES)-1:0] addressQ; | |
| // This module converts from bitstream to symbosl for OQPSK | |
| buffer_TX #(SAMPLES-1'b1) bit2symb | |
| ( | |
| .CLK50M ( CLK ), // clock 50MHz | |
| .RST ( RST ), // Reset, low active | |
| .EN ( En_2M ), // Enable 2 MHz | |
| .BitIn ( BitIn ), // Incoming bitstream | |
| .regi ( wi_b2r ) // buffer of 2 bits. | |
| ); | |
| // Register updatated each 1MHz | |
| REG_TX #(SAMPLES, SAMPLES) Register | |
| ( | |
| .CLK ( CLK ), // Clock 50MHz | |
| .RST ( RST ), // Reset, low active | |
| .EN ( En_1M ), // Enable 1 MHz | |
| .In ( {BitIn,wi_b2r}), | |
| .Out ( wi_Reg2Rom ) | |
| ); | |
| assign Sym = wi_Reg2Rom; | |
| // Register updatated each 1MHz and it's delayed 1/2 symbol time | |
| REG_TX #(1, 1) Reg_Delay_Q | |
| ( | |
| .CLK ( CLK ), // Clock 50MHz | |
| .RST ( RST ), // Reset, low active | |
| .EN ( En_1M_dly ), // Enable 1 MHz delayed | |
| .In ( wi_Reg2Rom[1] ), | |
| .Out ( wi_Reg2Rom_delay ) | |
| ); | |
| // **** CONTROL OF THE ROM MEMORY **** | |
| ctrl_2ROMS // ROM memory module | |
| #( | |
| .SAMPLES ( PS_SAMPLES ) | |
| ) | |
| ROM_ctrl_mdl | |
| ( | |
| .CLK_50M ( CLK ), // Clock input at 50MHz | |
| .rst ( RST ), // Reset low active | |
| .EN1 ( EN ), // Enable of the first counter. | |
| .addr1 ( addressI ), // Address of the rom memory | |
| .addr2 ( addressQ ), // Address of the rom memory | |
| .F50 ( En_1M ), // Enable of 2MHz | |
| .F25 ( En_1M_dly ), // | |
| .F2M ( En_2M ) | |
| ); | |
| assign C_F50 = En_1M; | |
| assign C_F25 = En_1M_dly; | |
| assign C_F2M = En_2M; | |
| assign addI = addressI; | |
| assign addQ = addressQ; | |
| // **** RCOSINE PULSE SHAPING **** | |
| pulse_shaping_v1 #(.SAMPLES(PS_SAMPLES), .DW(DW_IN), .I(I_SEL-1)) p_shaping_I( | |
| .reset(RST), | |
| .counter_addr(addressI), | |
| .bit_in(wi_Reg2Rom[0]), | |
| .out_filtered_s(I) | |
| ); | |
| pulse_shaping_v1 #(.SAMPLES(PS_SAMPLES), .DW(DW_IN), .I(I_SEL-1)) p_shaping_Q( | |
| .reset(RST), | |
| .counter_addr(addressQ), | |
| .bit_in(wi_Reg2Rom_delay), | |
| // .bit_in(wi_Reg2Rom[1]), | |
| .out_filtered_s(Q) | |
| ); | |
| // `include "MathFun.vh" | |
| endmodule | |
| module buffer_TX | |
| #(parameter SAMPLES=1) | |
| ( | |
| input CLK50M , | |
| input RST , | |
| input EN , | |
| input BitIn , | |
| output reg [SAMPLES-1:0] regi | |
| ); | |
| //integer ii; | |
| always@(posedge CLK50M or negedge RST) | |
| begin | |
| if (!RST) | |
| begin | |
| regi<={SAMPLES{1'b0}}; | |
| end | |
| else | |
| if(EN) | |
| begin | |
| regi <= BitIn; | |
| end | |
| end | |
| endmodule | |
| module ctrl_2ROMS // ROM memory module | |
| #(parameter SAMPLES=50) | |
| ( | |
| input CLK_50M , // Clock input at 50MHz | |
| input rst , // Reset low active | |
| input EN1 , // Enable of the first counter. | |
| output [$clog2(SAMPLES)-1:0] addr1 , // Address of the rom memory I component | |
| output [$clog2(SAMPLES)-1:0] addr2 , // Address of the rom memory Q component | |
| output F50 , // 1M enable each 50 clocks | |
| output F25 , // 1M enable each 25 clocks | |
| output F2M // Signal at 2 Megahertz | |
| ); | |
| reg [$clog2(SAMPLES)-1:0] Counter1; | |
| reg [$clog2(SAMPLES)-1:0] Counter2; | |
| always@(posedge CLK_50M or negedge rst) | |
| if(!rst) | |
| Counter1 <=0; | |
| else | |
| if(EN1) | |
| begin | |
| if (F50) | |
| Counter1 <= 0; | |
| else | |
| Counter1 <= Counter1 + 1'b1; | |
| end | |
| always@(posedge CLK_50M or negedge rst) | |
| if(!rst) | |
| Counter2 <=0; | |
| else | |
| if(EN1) | |
| begin | |
| if (F25) | |
| Counter2 <= 0; | |
| else | |
| Counter2 <= Counter2 + 1'b1; | |
| end | |
| assign F50 = (Counter1==6'd49)? 1'b1:1'b0; | |
| assign F25 = (Counter1==6'd24)? 1'b1:1'b0; | |
| assign F2M = (F50|F25); | |
| // assign addr1 = Counter1[log2(SAMPLES):1]; | |
| //assign addr2 = Counter2[log2(SAMPLES):1]; | |
| assign addr1 = Counter1; | |
| assign addr2 = Counter2; | |
| // `include "MathFun.vh" | |
| endmodule | |
| module pulse_shaping_v1 #(parameter SAMPLES=50, DW=13, I=0) | |
| ( input reset, | |
| input [$clog2(SAMPLES)-1:0] counter_addr, | |
| input bit_in, | |
| output signed [I-1:-(DW-I)] out_filtered_s | |
| ); | |
| // `include "MathFun.vh" | |
| wire signed[I-1:-(DW-I)] o_rom_1, o_rom_2, o_rom_3; | |
| reg signed[I-1:-(DW-I)] o_rom_1_1, o_rom_2_1, o_rom_3_1; | |
| reg bit_in_0; | |
| reg bit_in_1; | |
| reg bit_in_2; | |
| reg ctl; | |
| reg ctl_1; | |
| reg [1:0] counter = 2'b00; | |
| always @(*) begin | |
| if (!reset) begin | |
| ctl = 1'b0; | |
| ctl_1 = bit_in; | |
| bit_in_0 = 1'b0; | |
| end | |
| else | |
| bit_in_0 = bit_in; | |
| if (counter_addr == 6'd49) begin | |
| ctl = 1'b1; | |
| if (bit_in_0 == ctl_1) begin | |
| o_rom_2_1 = (bit_in_1 == 1'b1)?o_rom_2:-o_rom_2; | |
| ctl_1 = bit_in_1; | |
| end | |
| else begin | |
| o_rom_2_1 = (bit_in_1 == 1'b1)?-o_rom_2:o_rom_2; | |
| ctl_1 = bit_in_1; | |
| end | |
| end | |
| else begin | |
| ctl = 1'b0; | |
| o_rom_2_1 = (bit_in_1 == 1'b1)?o_rom_2:-o_rom_2; | |
| end | |
| o_rom_1_1 = (bit_in == 1'b1)?o_rom_1:-o_rom_1; | |
| o_rom_3_1 = (bit_in_2 == 1'b1)?o_rom_3:-o_rom_3; | |
| end | |
| always @ (posedge ctl or negedge reset) begin | |
| if(!reset) begin | |
| bit_in_1 <= 1'b0; | |
| bit_in_2 <= 1'b0; | |
| counter <= 2'b00; | |
| end | |
| else begin | |
| counter <= (counter <= 2'b01)?counter + 1'b1:counter; | |
| bit_in_1 <= bit_in; | |
| bit_in_2 <= bit_in_1; | |
| end | |
| end | |
| rcosine_1 #(SAMPLES,DW,I) rcos_1 | |
| ( | |
| .addr(counter_addr), | |
| .out(o_rom_1) | |
| ); | |
| rcosine_2 #(SAMPLES,DW,I) rcos_2 | |
| ( | |
| .addr(counter_addr), | |
| .out(o_rom_2) | |
| ); | |
| rcosine_3 #(SAMPLES,DW,I) rcos_3 | |
| ( | |
| .addr(counter_addr), | |
| .out(o_rom_3) | |
| ); | |
| assign out_filtered_s = o_rom_1_1 + ((counter > 2'b00)?o_rom_2_1:0) + ((counter > 2'b01)?o_rom_3_1:0); | |
| endmodule | |
| module rcosine_1 #(parameter SAMPLES=50, DW=13, I=0) | |
| ( | |
| input [$clog2(SAMPLES)-1:0] addr, | |
| output reg signed[I-1:-(DW-I)] out | |
| ); | |
| always@* | |
| case(addr) | |
| 00:out = 13'b0000000000000; | |
| 01:out = 13'b0000000000000; | |
| 02:out = 13'b0000000000010; | |
| 03:out = 13'b0000000000100; | |
| 04:out = 13'b0000000001000; | |
| 05:out = 13'b0000000001100; | |
| 06:out = 13'b0000000010010; | |
| 07:out = 13'b0000000011000; | |
| 08:out = 13'b0000000100000; | |
| 09:out = 13'b0000000101000; | |
| 10:out = 13'b0000000110000; | |
| 11:out = 13'b0000000111001; | |
| 12:out = 13'b0000001000001; | |
| 13:out = 13'b0000001001001; | |
| 14:out = 13'b0000001010000; | |
| 15:out = 13'b0000001010111; | |
| 16:out = 13'b0000001011011; | |
| 17:out = 13'b0000001011101; | |
| 18:out = 13'b0000001011110; | |
| 19:out = 13'b0000001011011; | |
| 20:out = 13'b0000001010101; | |
| 21:out = 13'b0000001001100; | |
| 22:out = 13'b0000000111111; | |
| 23:out = 13'b0000000101110; | |
| 24:out = 13'b0000000011001; | |
| 25:out = 13'b0000000000000; | |
| 26:out = -13'b0000000011101; | |
| 27:out = -13'b0000000111101; | |
| 28:out = -13'b0000001100001; | |
| 29:out = -13'b0000010001001; | |
| 30:out = -13'b0000010110010; | |
| 31:out = -13'b0000011011101; | |
| 32:out = -13'b0000100001010; | |
| 33:out = -13'b0000100110110; | |
| 34:out = -13'b0000101100010; | |
| 35:out = -13'b0000110001100; | |
| 36:out = -13'b0000110110011; | |
| 37:out = -13'b0000111010101; | |
| 38:out = -13'b0000111110010; | |
| 39:out = -13'b0001000001000; | |
| 40:out = -13'b0001000010110; | |
| 41:out = -13'b0001000011011; | |
| 42:out = -13'b0001000010101; | |
| 43:out = -13'b0001000000100; | |
| 44:out = -13'b0000111100110; | |
| 45:out = -13'b0000110111010; | |
| 46:out = -13'b0000110000000; | |
| 47:out = -13'b0000100110111; | |
| 48:out = -13'b0000011011111; | |
| 49:out = -13'b0000001110111; | |
| default: out = 13'b0000000000000; | |
| endcase | |
| // `include "MathFun.vh" | |
| endmodule | |
| module rcosine_2 #(parameter SAMPLES=50, DW=13, I=0) | |
| ( | |
| input [$clog2(SAMPLES)-1:0] addr, | |
| output reg signed[I-1:-(DW-I)] out | |
| ); | |
| always@* | |
| case(addr) | |
| 00:out = 13'b0000000000000; | |
| 01:out = 13'b0000010000110; | |
| 02:out = 13'b0000100011011; | |
| 03:out = 13'b0000110111110; | |
| 04:out = 13'b0001001101110; | |
| 05:out = 13'b0001100101010; | |
| 06:out = 13'b0001111110000; | |
| 07:out = 13'b0010010111111; | |
| 08:out = 13'b0010110010101; | |
| 09:out = 13'b0011001110000; | |
| 10:out = 13'b0011101001110; | |
| 11:out = 13'b0100000101101; | |
| 12:out = 13'b0100100001001; | |
| 13:out = 13'b0100111100010; | |
| 14:out = 13'b0101010110100; | |
| 15:out = 13'b0101101111110; | |
| 16:out = 13'b0110000111100; | |
| 17:out = 13'b0110011101101; | |
| 18:out = 13'b0110110001111; | |
| 19:out = 13'b0111000011111; | |
| 20:out = 13'b0111010011100; | |
| 21:out = 13'b0111100000101; | |
| 22:out = 13'b0111101011000; | |
| 23:out = 13'b0111110010100; | |
| 24:out = 13'b0111110111000; | |
| 25:out = 13'b0111111000100; | |
| 26:out = 13'b0111110111000; | |
| 27:out = 13'b0111110010100; | |
| 28:out = 13'b0111101011000; | |
| 29:out = 13'b0111100000101; | |
| 30:out = 13'b0111010011100; | |
| 31:out = 13'b0111000011111; | |
| 32:out = 13'b0110110001111; | |
| 33:out = 13'b0110011101101; | |
| 34:out = 13'b0110000111100; | |
| 35:out = 13'b0101101111110; | |
| 36:out = 13'b0101010110100; | |
| 37:out = 13'b0100111100010; | |
| 38:out = 13'b0100100001001; | |
| 39:out = 13'b0100000101101; | |
| 40:out = 13'b0011101001110; | |
| 41:out = 13'b0011001110000; | |
| 42:out = 13'b0010110010101; | |
| 43:out = 13'b0010010111111; | |
| 44:out = 13'b0001111110000; | |
| 45:out = 13'b0001100101010; | |
| 46:out = 13'b0001001101110; | |
| 47:out = 13'b0000110111110; | |
| 48:out = 13'b0000100011011; | |
| 49:out = 13'b0000010000110; | |
| default: out = 13'b0000000000000; | |
| endcase | |
| // `include "MathFun.vh" | |
| endmodule | |
| module rcosine_3 #(parameter SAMPLES=50, DW=13, I=0) | |
| ( | |
| input [$clog2(SAMPLES)-1:0] addr, | |
| output reg signed[I-1:-(DW-I)] out | |
| ); | |
| always@* | |
| case(addr) | |
| 00:out = -13'b0000000000000; | |
| 01:out = -13'b0000001110111; | |
| 02:out = -13'b0000011011111; | |
| 03:out = -13'b0000100110111; | |
| 04:out = -13'b0000110000000; | |
| 05:out = -13'b0000110111010; | |
| 06:out = -13'b0000111100110; | |
| 07:out = -13'b0001000000100; | |
| 08:out = -13'b0001000010101; | |
| 09:out = -13'b0001000011011; | |
| 10:out = -13'b0001000010110; | |
| 11:out = -13'b0001000001000; | |
| 12:out = -13'b0000111110010; | |
| 13:out = -13'b0000111010101; | |
| 14:out = -13'b0000110110011; | |
| 15:out = -13'b0000110001100; | |
| 16:out = -13'b0000101100010; | |
| 17:out = -13'b0000100110110; | |
| 18:out = -13'b0000100001010; | |
| 19:out = -13'b0000011011101; | |
| 20:out = -13'b0000010110010; | |
| 21:out = -13'b0000010001001; | |
| 22:out = -13'b0000001100001; | |
| 23:out = -13'b0000000111101; | |
| 24:out = -13'b0000000011101; | |
| 25:out = 13'b0000000000000; | |
| 26:out = 13'b0000000011001; | |
| 27:out = 13'b0000000101110; | |
| 28:out = 13'b0000000111111; | |
| 29:out = 13'b0000001001100; | |
| 30:out = 13'b0000001010101; | |
| 31:out = 13'b0000001011011; | |
| 32:out = 13'b0000001011110; | |
| 33:out = 13'b0000001011101; | |
| 34:out = 13'b0000001011011; | |
| 35:out = 13'b0000001010111; | |
| 36:out = 13'b0000001010000; | |
| 37:out = 13'b0000001001001; | |
| 38:out = 13'b0000001000001; | |
| 39:out = 13'b0000000111001; | |
| 40:out = 13'b0000000110000; | |
| 41:out = 13'b0000000101000; | |
| 42:out = 13'b0000000100000; | |
| 43:out = 13'b0000000011000; | |
| 44:out = 13'b0000000010010; | |
| 45:out = 13'b0000000001100; | |
| 46:out = 13'b0000000001000; | |
| 47:out = 13'b0000000000100; | |
| 48:out = 13'b0000000000010; | |
| 49:out = 13'b0000000000000; | |
| default: out = 13'b0000000000000; | |
| endcase | |
| // `include "MathFun.vh" | |
| endmodule | |
| module REG_TX | |
| #(parameter DW_IN=2, I_SEL=2) | |
| ( | |
| input CLK, | |
| input RST, | |
| input EN, | |
| input signed [I_SEL-1:-(DW_IN-I_SEL)] In, | |
| output reg signed [I_SEL-1:-(DW_IN-I_SEL)] Out | |
| ); | |
| always@(posedge CLK or negedge RST) | |
| if (!RST) | |
| begin | |
| Out <= {DW_IN{1'b0}}; | |
| end | |
| else | |
| begin | |
| if(EN==1'b1) | |
| begin | |
| Out <= In; | |
| end | |
| end | |
| endmodule | |