From 9c70c28f2848e580e6edf9cacc94e121e4eb60e3 Mon Sep 17 00:00:00 2001 From: denis Date: Fri, 13 Jan 2023 03:35:13 +0700 Subject: [PATCH] add LLR testbench & add more info about LLR cores --- do/do_llr.do | 17 ++ rtl/llr/README.md | 17 +- rtl/llr/llr_bpsk_8psk_demapper.sv | 13 +- rtl/llr/llr_even_qam_demapper_core.sv | 18 +- rtl/llr/llr_odd_qam_demapper.sv | 11 +- rtl/llr/llr_qam128_demapper.sv | 6 +- rtl/llr/llr_qam2048_demapper.sv | 205 ++++++++++------ rtl/llr/llr_qam32_demapper.sv | 12 +- rtl/llr/llr_qam512_demapper.sv | 54 +++-- testbench/llr/tb_qam_demapper.sv | 324 ++++++++++++++++++++++++++ 10 files changed, 565 insertions(+), 112 deletions(-) create mode 100644 do/do_llr.do create mode 100644 testbench/llr/tb_qam_demapper.sv diff --git a/do/do_llr.do b/do/do_llr.do new file mode 100644 index 0000000..9744122 --- /dev/null +++ b/do/do_llr.do @@ -0,0 +1,17 @@ +onerror {resume} + +set incdir ../include +set rtldir ../rtl +set tbdir ../testbench +set workdir ../work +# +vlib $workdir +# +vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/llr $rtldir/llr/*.sv + +vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/bch $tbdir/llr/tb_qam_demapper.sv + +set seed [clock seconds] + +vsim -sv_seed $seed tb_qam_demapper -lib $workdir +nowarn+8233 +run -all diff --git a/rtl/llr/README.md b/rtl/llr/README.md index 34f375b..0014be0 100644 --- a/rtl/llr/README.md +++ b/rtl/llr/README.md @@ -1,3 +1,18 @@ Static configurated Gray bit canstellation mapper for BSPK..QAM4096 modulation and corresponding LLR demapper. -Even QAMs and BPSK/8PSK LLR bitwidth can be any, others odd QAMs only LLR = 4bit \ No newline at end of file +Even QAMs and BPSK/8PSK LLR bitwidth can be any, others odd QAMs only LLR = 4bit + +vivado 2019.1 Artix 7 - 2 + +Gray bit mapper up to QAM4096 : LUT/REG 74/181 >350MHz + +Even QAM LLR demapper up to 4096 : LUT/REG 500/545 >250MHz + +Odd QAM LLR demapper up to QAM2048 : LUT/REG/RAMB 600/760/12.0 >250MHz + +Odd QAM LLR demapper up to QAM512 : LUT/REG/RAMB 331/483/7.5 >250MHz + +Odd QAM LLR demapper up to QAM128 : LUT/REG/RAMB 151/275/3.0 >250MHz + : LUT/REG 645/548 >250MHz + +Attnetion: the used map bits to quadrature value converter rules see in tb_qam_mapper.sv file (!!!) diff --git a/rtl/llr/llr_bpsk_8psk_demapper.sv b/rtl/llr/llr_bpsk_8psk_demapper.sv index f913845..69eb866 100644 --- a/rtl/llr/llr_bpsk_8psk_demapper.sv +++ b/rtl/llr/llr_bpsk_8psk_demapper.sv @@ -131,9 +131,9 @@ module llr_bpsk_8psk_demapper this_t adat_re; this_t adat_im; - this_t bit0_llr [1 : 3] /*synthesis keep*/; - this_t bit1_llr [1 : 3] /*synthesis keep*/; - this_t bit2_llr [1 : 3] /*synthesis keep*/; + this_t bit0_llr [1 : 3] ; + this_t bit1_llr [1 : 3] ; + this_t bit2_llr [1 : 3] ; //------------------------------------------------------------------------------------------------------ // @@ -200,12 +200,13 @@ module llr_bpsk_8psk_demapper poverflow = (dat > cMAX_POS); noverflow = (dat < cMIN_NEG); // - if (poverflow | noverflow) + if (poverflow | noverflow) begin saturate_llr = poverflow ? cMAX_POS[pLLR_W-1 : 0] : cMIN_NEG[pLLR_W-1 : 0]; - else + end + else begin saturate_llr = dat[pLLR_W-1 : 0]; + end end endfunction - endmodule diff --git a/rtl/llr/llr_even_qam_demapper_core.sv b/rtl/llr/llr_even_qam_demapper_core.sv index d3ad695..eaf1f6d 100644 --- a/rtl/llr/llr_even_qam_demapper_core.sv +++ b/rtl/llr/llr_even_qam_demapper_core.sv @@ -223,14 +223,18 @@ module llr_even_qam_demapper_core oqam <= qam[4]; oLLR[0] <= saturate_llr(bit0_llr[4] + bit0_lsb_llr[4]); oLLR[1] <= saturate_llr(bit1_llr[4] + bit1_lsb_llr[4]); - if (pBMAX > 4) + if (pBMAX > 4) begin oLLR[2] <= saturate_llr(bit2_llr[4] + bit2_lsb_llr[4]); - if (pBMAX > 6) + end + if (pBMAX > 6) begin oLLR[3] <= saturate_llr(bit3_llr[4] + bit3_lsb_llr[4]); - if (pBMAX > 8) + end + if (pBMAX > 8) begin oLLR[4] <= saturate_llr(bit4_llr[4] + bit4_lsb_llr[4]); - if (pBMAX > 10) + end + if (pBMAX > 10) begin oLLR[5] <= saturate_llr(bit5_llr[4] + bit5_lsb_llr[4]); + end end end end @@ -260,10 +264,12 @@ module llr_even_qam_demapper_core poverflow = (dat > cMAX_POS); noverflow = (dat < cMIN_NEG); // - if (poverflow | noverflow) + if (poverflow | noverflow) begin saturate_llr = poverflow ? cMAX_POS[pLLR_W-1 : 0] : cMIN_NEG[pLLR_W-1 : 0]; - else + end + else begin saturate_llr = dat[pLLR_W-1 : 0]; + end end endfunction diff --git a/rtl/llr/llr_odd_qam_demapper.sv b/rtl/llr/llr_odd_qam_demapper.sv index afacdf1..67402f8 100644 --- a/rtl/llr/llr_odd_qam_demapper.sv +++ b/rtl/llr/llr_odd_qam_demapper.sv @@ -81,7 +81,7 @@ module llr_odd_qam_demapper parameter int pBMAX = 12 , parameter int pDAT_W = 9 , // fixed, don't change parameter int pLLR_W = 4 , // fixed, don't change - parameter bit pUSE_RAMB = 0 + parameter bit pUSE_RAMB = 1 ) ( iclk , @@ -387,16 +387,19 @@ module llr_odd_qam_demapper 4'd1 : oLLR[0] <= bpsk_8psk_demapper__oLLR[0]; 4'd3 : oLLR[0 : 2] <= bpsk_8psk_demapper__oLLR; 4'd5 : begin - if (pBMAX > 4) + if (pBMAX > 4) begin oLLR[0 : 4] <= qam32_demapper__oLLR; + end end 4'd7 : begin - if (pBMAX > 6) + if (pBMAX > 6) begin oLLR[0 : 6] <= qam128_demapper__oLLR; + end end 4'd9 : begin - if (pBMAX > 8) + if (pBMAX > 8) begin oLLR[0 : 8] <= qam512_demapper__oLLR; + end end endcase end diff --git a/rtl/llr/llr_qam128_demapper.sv b/rtl/llr/llr_qam128_demapper.sv index f6cec89..e040096 100644 --- a/rtl/llr/llr_qam128_demapper.sv +++ b/rtl/llr/llr_qam128_demapper.sv @@ -924,10 +924,12 @@ module llr_qam128_demapper poverflow = (dat > cMAX_POS); noverflow = (dat < cMIN_NEG); // - if (poverflow | noverflow) + if (poverflow | noverflow) begin saturate_llr = poverflow ? cMAX_POS[pLLR_W-1 : 0] : cMIN_NEG[pLLR_W-1 : 0]; - else + end + else begin saturate_llr = dat[pLLR_W-1 : 0]; + end end endfunction diff --git a/rtl/llr/llr_qam2048_demapper.sv b/rtl/llr/llr_qam2048_demapper.sv index 7d9927c..168d7fc 100644 --- a/rtl/llr/llr_qam2048_demapper.sv +++ b/rtl/llr/llr_qam2048_demapper.sv @@ -361,140 +361,199 @@ module llr_qam2048_demapper bit_tab_sel[0] <= !adat_im_less32 & !adat_re_less24 & !adat_re_more40; // bit 9 - if (adat_im_less30) + if (adat_im_less30) begin bit_math_dat[9] <= cLEVEL_32 - adat_re; - else if (adat_re_less24) + end + else if (adat_re_less24) begin bit_math_dat[9] <= cLEVEL_32 - adat_im; - else + end + else begin bit_math_dat[9] <= -7; + end // bit 8 - if (adat_im_less30) + if (adat_im_less30) begin bit_math_dat[8] <= adat_re - cLEVEL_16; - else + end + else begin bit_math_dat[8] <= -7; + end // bit 7 - if (adat_re_less16) + if (adat_re_less16) begin bit_math_dat[7] <= adat_re - cLEVEL_8; - else if (adat_re_less32) + end + else if (adat_re_less32) begin bit_math_dat[7] <= cLEVEL_24 - adat_re; - else if (adat_im_less24) + end + else if (adat_im_less24) begin bit_math_dat[7] <= adat_re - cLEVEL_40; - else + end + else begin bit_math_dat[7] <= -7; + end // bit 6 - if (adat_re_less8) + if (adat_re_less8) begin bit_math_dat[6] <= adat_re - cLEVEL_4; - else if (adat_re_less16) + end + else if (adat_re_less16) begin bit_math_dat[6] <= cLEVEL_12 - adat_re; - else if (adat_re_less24) + end + else if (adat_re_less24) begin bit_math_dat[6] <= adat_re - cLEVEL_20; - else if (adat_re_less32) + end + else if (adat_re_less32) begin bit_math_dat[6] <= cLEVEL_28 - adat_re; + end else if (adat_im_less24) begin - if (adat_re_less40) + if (adat_re_less40) begin bit_math_dat[6] <= adat_re - cLEVEL_36; - else + end + else begin bit_math_dat[6] <= cLEVEL_44 - adat_re; + end end - else + else begin bit_math_dat[6] <= -7; + end // bit 5 - if (adat_re_less4) + if (adat_re_less4) begin bit_math_dat[5] <= adat_re - cLEVEL_2; - else if (adat_re_less8) + end + else if (adat_re_less8) begin bit_math_dat[5] <= cLEVEL_6 - adat_re; - else if (adat_re_less12) + end + else if (adat_re_less12) begin bit_math_dat[5] <= adat_re - cLEVEL_10; - else if (adat_re_less16) + end + else if (adat_re_less16) begin bit_math_dat[5] <= cLEVEL_14 - adat_re; - else if (adat_re_less20) + end + else if (adat_re_less20) begin bit_math_dat[5] <= adat_re - cLEVEL_18; - else if (adat_re_less24) + end + else if (adat_re_less24) begin bit_math_dat[5] <= cLEVEL_22 - adat_re; - else if (adat_re_less28) + end + else if (adat_re_less28) begin bit_math_dat[5] <= adat_re - cLEVEL_26; - else if (adat_re_less32) + end + else if (adat_re_less32) begin bit_math_dat[5] <= cLEVEL_30 - adat_re; + end else if (adat_im_less24) begin - if (adat_re_less36) + if (adat_re_less36) begin bit_math_dat[5] <= adat_re - cLEVEL_34; - else if (adat_re_less40) + end + else if (adat_re_less40) begin bit_math_dat[5] <= cLEVEL_38 - adat_re; - else if (adat_re_less44) + end + else if (adat_re_less44) begin bit_math_dat[5] <= adat_re - cLEVEL_42; - else + end + else begin bit_math_dat[5] <= cLEVEL_46 - adat_re; + end end - else + else begin bit_math_dat[5] <= -7; + end // bit 3 - if (adat_im_less24) + if (adat_im_less24) begin bit_math_dat[3] <= cLEVEL_16 - adat_im; - else if (adat_im_more40) + end + else if (adat_im_more40) begin bit_math_dat[3] <= cLEVEL_16 - adat_re; - else if (adat_re_less8) + end + else if (adat_re_less8) begin bit_math_dat[3] <= adat_im - cLEVEL_32; - else + end + else begin bit_math_dat[3] <= -7; + end // bit 2 - if (adat_im_less16) + if (adat_im_less16) begin bit_math_dat[2] <= adat_im - cLEVEL_8; - else if (adat_im_less32) + end + else if (adat_im_less32) begin bit_math_dat[2] <= cLEVEL_24 - adat_im; - else if (adat_re_less24) + end + else if (adat_re_less24) begin bit_math_dat[2] <= adat_im - cLEVEL_40; - else + end + else begin bit_math_dat[2] <= -7; + end + // bit 1 - if (adat_im_less8) + if (adat_im_less8) begin bit_math_dat[1] <= adat_im - cLEVEL_4; - else if (adat_im_less16) + end + else if (adat_im_less16) begin bit_math_dat[1] <= cLEVEL_12 - adat_im; - else if (adat_im_less24) + end + else if (adat_im_less24) begin bit_math_dat[1] <= adat_im - cLEVEL_20; - else if (adat_im_less32) + end + else if (adat_im_less32) begin bit_math_dat[1] <= cLEVEL_28 - adat_im; + end else if (adat_re_less24) begin - if (adat_im_less40) + if (adat_im_less40) begin bit_math_dat[1] <= adat_im - cLEVEL_36; - else + end + else begin bit_math_dat[1] <= cLEVEL_44 - adat_im; + end end - else + else begin bit_math_dat[1] <= -7; + end + // bit 0 - if (adat_im_less4) + if (adat_im_less4) begin bit_math_dat[0] <= adat_im - cLEVEL_2; - else if (adat_im_less8) + end + else if (adat_im_less8) begin bit_math_dat[0] <= cLEVEL_6 - adat_im; - else if (adat_im_less12) + end + else if (adat_im_less12) begin bit_math_dat[0] <= adat_im - cLEVEL_10; - else if (adat_im_less16) + end + else if (adat_im_less16) begin bit_math_dat[0] <= cLEVEL_14 - adat_im; - else if (adat_im_less20) + end + else if (adat_im_less20) begin bit_math_dat[0] <= adat_im - cLEVEL_18; - else if (adat_im_less24) + end + else if (adat_im_less24) begin bit_math_dat[0] <= cLEVEL_22 - adat_im; - else if (adat_im_less28) + end + else if (adat_im_less28) begin bit_math_dat[0] <= adat_im - cLEVEL_26; - else if (adat_im_less32) + end + else if (adat_im_less32) begin bit_math_dat[0] <= cLEVEL_30 - adat_im; + end else if (adat_re_less24) begin - if (adat_im_less36) + if (adat_im_less36) begin bit_math_dat[0] <= adat_im - cLEVEL_34; - else if (adat_im_less40) + end + else if (adat_im_less40) begin bit_math_dat[0] <= cLEVEL_38 - adat_im; - else if (adat_im_less44) + end + else if (adat_im_less44) begin bit_math_dat[0] <= adat_im - cLEVEL_42; - else + end + else begin bit_math_dat[0] <= cLEVEL_46 - adat_im; + end end - else + else begin bit_math_dat[0] <= -7; + end end end @@ -532,22 +591,22 @@ module llr_qam2048_demapper if (iclkena) begin // // val[0] - dat4sat_re <= saturate(dat_re, cEDGE_NEG, cEDGE_POS); - dat4sat_im <= saturate(dat_im, cEDGE_NEG, cEDGE_POS); + dat4sat_re <= saturate(dat_re, cEDGE_NEG, cEDGE_POS); + dat4sat_im <= saturate(dat_im, cEDGE_NEG, cEDGE_POS); // // val[1] - bit4_llr [2] <= saturate_llr(-dat4sat_im); - bit10_llr[2] <= saturate_llr( dat4sat_re); + bit4_llr [2] <= saturate_llr(-dat4sat_im); + bit10_llr[2] <= saturate_llr( dat4sat_re); - adat_re <= (dat4sat_re < 0) ? -dat4sat_re : dat4sat_re; - adat_im <= (dat4sat_im < 0) ? -dat4sat_im : dat4sat_im; + adat_re <= (dat4sat_re < 0) ? -dat4sat_re : dat4sat_re; + adat_im <= (dat4sat_im < 0) ? -dat4sat_im : dat4sat_im; // // val[2] - bit4_llr [3] <= bit4_llr [2]; - bit10_llr[3] <= bit10_llr[2]; + bit4_llr [3] <= bit4_llr [2]; + bit10_llr[3] <= bit10_llr[2]; - are <= adat_re; - aim <= adat_im; + are <= adat_re; + aim <= adat_im; end end @@ -619,10 +678,12 @@ module llr_qam2048_demapper poverflow = (dat > max); noverflow = (dat < min); // - if (poverflow | noverflow) + if (poverflow | noverflow) begin saturate = poverflow ? max : min; - else + end + else begin saturate = dat; + end end endfunction @@ -633,10 +694,12 @@ module llr_qam2048_demapper poverflow = (dat > cMAX_POS); noverflow = (dat < cMIN_NEG); // - if (poverflow | noverflow) + if (poverflow | noverflow) begin saturate_llr = poverflow ? cMAX_POS[pLLR_W-1 : 0] : cMIN_NEG[pLLR_W-1 : 0]; - else + end + else begin saturate_llr = dat[pLLR_W-1 : 0]; + end end endfunction diff --git a/rtl/llr/llr_qam32_demapper.sv b/rtl/llr/llr_qam32_demapper.sv index 27a92f5..20b09ea 100644 --- a/rtl/llr/llr_qam32_demapper.sv +++ b/rtl/llr/llr_qam32_demapper.sv @@ -488,10 +488,12 @@ module llr_qam32_demapper poverflow = (dat > max); noverflow = (dat < min); // - if (poverflow | noverflow) + if (poverflow | noverflow) begin saturate = poverflow ? max : min; - else + end + else begin saturate = dat; + end end endfunction @@ -502,10 +504,12 @@ module llr_qam32_demapper poverflow = (dat > cMAX_POS); noverflow = (dat < cMIN_NEG); // - if (poverflow | noverflow) + if (poverflow | noverflow) begin saturate_llr = poverflow ? cMAX_POS[pLLR_W-1 : 0] : cMIN_NEG[pLLR_W-1 : 0]; - else + end + else begin saturate_llr = dat[pLLR_W-1 : 0]; + end end endfunction diff --git a/rtl/llr/llr_qam512_demapper.sv b/rtl/llr/llr_qam512_demapper.sv index 561eb95..fadd436 100644 --- a/rtl/llr/llr_qam512_demapper.sv +++ b/rtl/llr/llr_qam512_demapper.sv @@ -1048,42 +1048,56 @@ module llr_qam512_demapper bit_tab_sel[0] <= !adat_im_less16; // bit 7 - if (adat_im_less8) + if (adat_im_less8) begin bit_math_dat[7] <= cLEVEL_16 - adat_re; - else + end + else begin bit_math_dat[7] <= cLEVEL_16 - adat_im; + end // bit 6 bit_math_dat[6] <= adat_re - cLEVEL_8; // bit 5 - if (adat_re_less8) + if (adat_re_less8) begin bit_math_dat[5] <= adat_re - cLEVEL_4; - else + end + else begin bit_math_dat[5] <= cLEVEL_12 - adat_re; + end // bit 4 - if (adat_re_less4) + if (adat_re_less4) begin bit_math_dat[4] <= adat_re - cLEVEL_2; - else if (adat_re_less8) + end + else if (adat_re_less8) begin bit_math_dat[4] <= cLEVEL_6 - adat_re; - else if (adat_re_less12) + end + else if (adat_re_less12) begin bit_math_dat[4] <= adat_re - cLEVEL_10; - else + end + else begin bit_math_dat[4] <= cLEVEL_14 - adat_re; + end // bit 2 bit_math_dat[2] <= cLEVEL_8 - adat_im; // bit 1 - if (adat_im_less8) + if (adat_im_less8) begin bit_math_dat[1] <= adat_im - cLEVEL_4; - else + end + else begin bit_math_dat[1] <= cLEVEL_12 - adat_im; + end // bit 0 - if (adat_im_less4) + if (adat_im_less4) begin bit_math_dat[0] <= adat_im - cLEVEL_2; - else if (adat_im_less8) + end + else if (adat_im_less8) begin bit_math_dat[0] <= cLEVEL_6 - adat_im; - else if (adat_im_less12) + end + else if (adat_im_less12) begin bit_math_dat[0] <= adat_im - cLEVEL_10; - else + end + else begin bit_math_dat[0] <= cLEVEL_14 - adat_im; + end end end @@ -1195,10 +1209,12 @@ module llr_qam512_demapper poverflow = (dat > max); noverflow = (dat < min); // - if (poverflow | noverflow) + if (poverflow | noverflow) begin saturate = poverflow ? max : min; - else + end + else begin saturate = dat; + end end endfunction @@ -1209,10 +1225,12 @@ module llr_qam512_demapper poverflow = (dat > cMAX_POS); noverflow = (dat < cMIN_NEG); // - if (poverflow | noverflow) + if (poverflow | noverflow) begin saturate_llr = poverflow ? cMAX_POS[pLLR_W-1 : 0] : cMIN_NEG[pLLR_W-1 : 0]; - else + end + else begin saturate_llr = dat[pLLR_W-1 : 0]; + end end endfunction diff --git a/testbench/llr/tb_qam_demapper.sv b/testbench/llr/tb_qam_demapper.sv new file mode 100644 index 0000000..fa0bec9 --- /dev/null +++ b/testbench/llr/tb_qam_demapper.sv @@ -0,0 +1,324 @@ +// +// Project : FEC library +// Author : Shekhalev Denis (des00) +// Workfile : tb_qam_demapper.sv +// Description : testbench for qams mapper/demapper +// + +module tb_qam_demapper ; + + parameter int pBMAX = 12 ; + parameter int pDAT_W = 9 ; + parameter int pLLR_W = 4 ; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + bit iclk ; + bit ireset ; + bit iclkena ; + // + logic isop ; + logic ival ; + logic ieop ; + logic [3 : 0] iqam ; + logic [pBMAX-1 : 0] idat ; + // + logic mapper__osop ; + logic mapper__oval ; + logic mapper__oeop ; + logic [3 : 0] mapper__oqam ; + logic [pBMAX/2-1 : 0] mapper__odat_re ; + logic [pBMAX/2-1 : 0] mapper__odat_im ; + // + logic demapper__ival ; + logic demapper__isop ; + logic [3 : 0] demapper__iqam ; + logic signed [pDAT_W-1 : 0] demapper__idat_re ; + logic signed [pDAT_W-1 : 0] demapper__idat_im ; + // + logic even_qam__oval ; + logic even_qam__osop ; + logic [3 : 0] even_qam__oqam ; + logic signed [pLLR_W-1 : 0] even_qam__oLLR [0 : 11] ; + // + logic odd_qam__oval ; + logic odd_qam__osop ; + logic [3 : 0] odd_qam__oqam ; + logic signed [pLLR_W-1 : 0] odd_qam__oLLR [0 : 11] ; + + //------------------------------------------------------------------------------------------------------ + // bit mapper + //------------------------------------------------------------------------------------------------------ + + gray_bit_mapper + #( + .pBMAX ( pBMAX ) + ) + mapper + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .isop ( isop ) , + .ival ( ival ) , + .ieop ( ieop ) , + .iqam ( iqam ) , + .idat ( idat ) , + // + .osop ( mapper__osop ) , + .oval ( mapper__oval ) , + .oeop ( mapper__oeop ) , + .oqam ( mapper__oqam ) , + .odat_re ( mapper__odat_re ) , + .odat_im ( mapper__odat_im ) + ); + + //------------------------------------------------------------------------------------------------------ + // modulator + //------------------------------------------------------------------------------------------------------ + + localparam int cQPSK_POINT = 2**(pDAT_W-2); + + assign demapper__ival = mapper__oval; + assign demapper__isop = mapper__osop; + assign demapper__iqam = mapper__oqam; + + always_comb begin + demapper__idat_re = '0; + demapper__idat_im = '0; + case (mapper__oqam) + 1 : begin + demapper__idat_re = do_qpsk_modulation(mapper__odat_re[0]); + demapper__idat_im = do_qpsk_modulation(mapper__odat_im[0]); + end + 2 : begin + demapper__idat_re = do_qpsk_modulation(mapper__odat_re[0]); + demapper__idat_im = do_qpsk_modulation(mapper__odat_im[0]); + end + 3 : begin + demapper__idat_re = do_8psk_modulation(mapper__odat_re[1 : 0]); + demapper__idat_im = do_8psk_modulation(mapper__odat_im[1 : 0]); + end + 4 : begin + demapper__idat_re = do_qam16_modulation(mapper__odat_re[1 : 0]); + demapper__idat_im = do_qam16_modulation(mapper__odat_im[1 : 0]); + end + 5 : begin + demapper__idat_re = do_qam32_modulation(mapper__odat_re[2 : 0]); + demapper__idat_im = do_qam32_modulation(mapper__odat_im[2 : 0]); + end + 6 : begin + demapper__idat_re = do_qam64_modulation(mapper__odat_re[2 : 0]); + demapper__idat_im = do_qam64_modulation(mapper__odat_im[2 : 0]); + end + 7 : begin + demapper__idat_re = do_qam128_modulation(mapper__odat_re[3 : 0]); + demapper__idat_im = do_qam128_modulation(mapper__odat_im[3 : 0]); + end + 8 : begin + demapper__idat_re = do_qam256_modulation(mapper__odat_re[3 : 0]); + demapper__idat_im = do_qam256_modulation(mapper__odat_im[3 : 0]); + end + 9 : begin + demapper__idat_re = do_qam512_modulation(mapper__odat_re[4 : 0]); + demapper__idat_im = do_qam512_modulation(mapper__odat_im[4 : 0]); + end + 10 : begin + demapper__idat_re = do_qam1024_modulation(mapper__odat_re[4 : 0]); + demapper__idat_im = do_qam1024_modulation(mapper__odat_im[4 : 0]); + end + 11 : begin + demapper__idat_re = do_qam2048_modulation(mapper__odat_re[5 : 0]); + demapper__idat_im = do_qam2048_modulation(mapper__odat_im[5 : 0]); + end + 12 : begin + demapper__idat_re = do_qam4096_modulation(mapper__odat_re[5 : 0]); + demapper__idat_im = do_qam4096_modulation(mapper__odat_im[5 : 0]); + end + endcase + end + + function automatic int do_qpsk_modulation (bit data); + do_qpsk_modulation = data ? cQPSK_POINT : -cQPSK_POINT; + endfunction + + function automatic int do_8psk_modulation (bit [1 : 0] data); + int coe [4] = '{-167, -69, 69, 167}; // cQPSK_POINT/2 * sqrt(2) * cos([1:3]*pi/8) + begin + do_8psk_modulation = coe[data]; + end + endfunction + + function automatic int do_qam16_modulation (bit [1 : 0] data); + do_qam16_modulation = (-3 + 2*data)*cQPSK_POINT/2; + endfunction + + function automatic int do_qam32_modulation (bit [2 : 0] data); + do_qam32_modulation = (-5 + 2*data)*cQPSK_POINT/4; + endfunction + + function automatic int do_qam64_modulation (bit [2 : 0] data); + do_qam64_modulation = (-7 + 2*data)*cQPSK_POINT/4; + endfunction + + function automatic int do_qam128_modulation (bit [3 : 0] data); + do_qam128_modulation = (-11 + 2*data)*cQPSK_POINT/8; + endfunction + + function automatic int do_qam256_modulation (bit [3 : 0] data); + do_qam256_modulation = (-15 + 2*data)*cQPSK_POINT/8; + endfunction + + function automatic int do_qam512_modulation (bit [4 : 0] data); + do_qam512_modulation = (-23 + 2*data)*cQPSK_POINT/16; + endfunction + + function automatic int do_qam1024_modulation (bit [4 : 0] data); + do_qam1024_modulation = (-31 + 2*data)*cQPSK_POINT/16; + endfunction + + function automatic int do_qam2048_modulation (bit [5 : 0] data); + do_qam2048_modulation = (-47 + 2*data)*cQPSK_POINT/32; + endfunction + + function automatic int do_qam4096_modulation (bit [5 : 0] data); + do_qam4096_modulation = (-63 + 2*data)*cQPSK_POINT/32; + endfunction + + //------------------------------------------------------------------------------------------------------ + // LLR demapper + //------------------------------------------------------------------------------------------------------ + + llr_even_qam_demapper + #( + .pBMAX ( pBMAX ) , + .pDAT_W ( pDAT_W ) , + .pLLR_W ( pLLR_W ) + ) + even_qam + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .ival ( demapper__ival ) , + .isop ( demapper__isop ) , + .iqam ( demapper__iqam ) , + .idat_re ( demapper__idat_re ) , + .idat_im ( demapper__idat_im ) , + // + .oval ( even_qam__oval ) , + .osop ( even_qam__osop ) , + .oqam ( even_qam__oqam ) , + .oLLR ( even_qam__oLLR ) + ); + + llr_odd_qam_demapper + #( + .pBMAX ( pBMAX ) , + .pDAT_W ( pDAT_W ) , + .pLLR_W ( pLLR_W ) , + .pUSE_RAMB ( 1 ) + ) + odd_qam + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .ival ( demapper__ival ) , + .isop ( demapper__isop ) , + .iqam ( demapper__iqam ) , + .idat_re ( demapper__idat_re ) , + .idat_im ( demapper__idat_im ) , + // + .oval ( odd_qam__oval ) , + .osop ( odd_qam__osop ) , + .oqam ( odd_qam__oqam ) , + .oLLR ( odd_qam__oLLR ) + ); + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + initial begin + iclk <= 1'b0; + #5ns forever #5ns iclk = ~iclk; + end + + assign ireset = 1'b0; + assign iclkena = 1'b1; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + bit [pBMAX-1 : 0] dat; + + always_comb begin + dat = '0; + for (int i = 0; i < pBMAX; i++) begin + if (i < odd_qam__oqam) begin + dat[i] = odd_qam__oqam[0] ? (odd_qam__oLLR[i] >= 0) : (even_qam__oLLR[i] >= 0); + end + end + end + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + int TEST_BPS_QAM [] = '{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + + int err; + + initial begin : main + ival <= '0; + isop <= '0; + ieop <= '0; + idat <= '0; + iqam <= '0; + + repeat (20) @(posedge iclk); + + err = 0; + + fork + // generator + begin + foreach (TEST_BPS_QAM[i]) begin + iqam <= TEST_BPS_QAM[i]; + for (int b = 0; b < 2**TEST_BPS_QAM[i]; b++) begin + ival <= 1'b1; + idat <= b; + @(posedge iclk); + ival <= 1'b0; + end + end + end + // checker + begin + foreach (TEST_BPS_QAM[i]) begin + for (int b = 0; b < 2**TEST_BPS_QAM[i]; b++) begin + @(posedge iclk iff odd_qam__oval); + if (b != dat) begin + err++; + end + end + end + end + join + + + repeat (20) @(posedge iclk); + + $display("test_done = %0d errors", err); + + $stop; + end + +endmodule