diff --git a/do/do_rsc2.do b/do/do_rsc2.do new file mode 100644 index 0000000..f159b93 --- /dev/null +++ b/do/do_rsc2.do @@ -0,0 +1,26 @@ +onerror {resume} + +set incdir ../include +set rtldir ../rtl +set tbdir ../testbench +set workdir ../work +# +vlib $workdir +# +vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/*.sv +vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/buffer/*.sv +# +vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/rsc $rtldir/rsc/*.sv +vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/rsc/enc $rtldir/rsc/enc/*.sv +vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/rsc/dec $rtldir/rsc/dec/*.sv +# +vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/rsc2 $rtldir/rsc2/*.sv +vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/rsc2/enc $rtldir/rsc2/enc/*.sv +vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/rsc2/dec $rtldir/rsc2/dec/*.sv + +vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/rsc $tbdir/rsc2/bertest.sv + +set seed [clock seconds] + +vsim -sv_seed $seed bertest -lib $workdir +nowarn+3015+3813+2241 +run -all diff --git a/rtl/rsc/README.md b/rtl/rsc/README.md index 913463e..4ac48ad 100644 --- a/rtl/rsc/README.md +++ b/rtl/rsc/README.md @@ -12,8 +12,8 @@ vivado 2019.1 Artix 7 - 2 Wimax OFDMA Nduobits = 1920(3840 bits), coderate = 2/3, 5bit metric, 10 iteration. Encoder use output buffer -Encoder : LUT/REG/RAMB 210/179/2.0 >200MHz (100Mbps -> 150Mbps) +Encoder : LUT/REG/RAMB 210/179/2.0 >200MHz (200Mbps -> 300Mbps) -Decoder simple : LUT/REG/RAMB 5.3k/4.7k/12.0 ~160MHz (12Mbps -> 8Mbps) +Decoder simple : LUT/REG/RAMB 5.3k/4.7k/12.0 ~160MHz (24Mbps -> 16Mbps) Attention: This is only CTC codecs. There is no bits permutation or interleaving. The coder and decoder correspond each other but can have different bit order with standard codes. diff --git a/rtl/rsc/dec/rsc_dec.sv b/rtl/rsc/dec/rsc_dec.sv index b17400e..deb11d5 100644 --- a/rtl/rsc/dec/rsc_dec.sv +++ b/rtl/rsc/dec/rsc_dec.sv @@ -240,7 +240,7 @@ module rsc_dec // // input buffer - logic [cIB_TAG_W-1 : 0] ibuffer__iwtag ; + logic [cIB_TAG_W-1 : 0] ibuffer__iwtag ; logic ibuffer__irempty ; logic [cADDR_W-1 : 0] ibuffer__ifsaddr ; diff --git a/rtl/rsc/dec/rsc_dec_engine.sv b/rtl/rsc/dec/rsc_dec_engine.sv index 122a1a5..1686537 100644 --- a/rtl/rsc/dec/rsc_dec_engine.sv +++ b/rtl/rsc/dec/rsc_dec_engine.sv @@ -467,63 +467,63 @@ module rsc_dec_engine // address generators //------------------------------------------------------------------------------------------------------ - rsc_dec_addr_gen - #( - .pB_nF ( 0 ) - ) - faddr_gen - ( - .iclk ( iclk ) , - .ireset ( ireset ) , - .iclkena ( iclkena ) , - // - .ipmode ( ctrl__oaddr_pmode ) , - .iclear ( ctrl__oaddr_clear ) , - .ienable ( ctrl__oaddr_enable ) , - // - .iN ( used_N ) , - .iNm1 ( used_Nm1 ) , - .iP ( used_P ) , - .iP0comp ( used_P0comp ) , - .iPincr ( used_Pincr ) , - .iPdvbinv ( used_Pdvbinv ) , - // - .osaddr ( faddr_gen__osaddr ) , - .opaddr ( faddr_gen__opaddr ) , - .obitinv ( addr_gen__obitinv ) - ); - - assign ofsaddr = faddr_gen__osaddr[pADDR_W-1 : 0]; - assign ofpaddr = faddr_gen__opaddr[pADDR_W-1 : 0]; - - rsc_dec_addr_gen - #( - .pB_nF ( 1 ) - ) - baddr_gen - ( - .iclk ( iclk ) , - .ireset ( ireset ) , - .iclkena ( iclkena ) , - // - .ipmode ( ctrl__oaddr_pmode ) , - .iclear ( ctrl__oaddr_clear ) , - .ienable ( ctrl__oaddr_enable ) , - // - .iN ( used_N ) , - .iNm1 ( used_Nm1 ) , - .iP ( used_P ) , - .iP0comp ( used_P0comp ) , - .iPincr ( used_Pincr ) , - .iPdvbinv ( used_Pdvbinv ) , - // - .osaddr ( baddr_gen__osaddr ) , - .opaddr ( baddr_gen__opaddr ) , - .obitinv ( ) // n.u. - ); - - assign obsaddr = baddr_gen__osaddr[pADDR_W-1 : 0]; - assign obpaddr = baddr_gen__opaddr[pADDR_W-1 : 0]; + rsc_dec_addr_gen + #( + .pB_nF ( 0 ) + ) + faddr_gen + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .ipmode ( ctrl__oaddr_pmode ) , + .iclear ( ctrl__oaddr_clear ) , + .ienable ( ctrl__oaddr_enable ) , + // + .iN ( used_N ) , + .iNm1 ( used_Nm1 ) , + .iP ( used_P ) , + .iP0comp ( used_P0comp ) , + .iPincr ( used_Pincr ) , + .iPdvbinv ( used_Pdvbinv ) , + // + .osaddr ( faddr_gen__osaddr ) , + .opaddr ( faddr_gen__opaddr ) , + .obitinv ( addr_gen__obitinv ) + ); + + assign ofsaddr = faddr_gen__osaddr[pADDR_W-1 : 0]; + assign ofpaddr = faddr_gen__opaddr[pADDR_W-1 : 0]; + + rsc_dec_addr_gen + #( + .pB_nF ( 1 ) + ) + baddr_gen + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .ipmode ( ctrl__oaddr_pmode ) , + .iclear ( ctrl__oaddr_clear ) , + .ienable ( ctrl__oaddr_enable ) , + // + .iN ( used_N ) , + .iNm1 ( used_Nm1 ) , + .iP ( used_P ) , + .iP0comp ( used_P0comp ) , + .iPincr ( used_Pincr ) , + .iPdvbinv ( used_Pdvbinv ) , + // + .osaddr ( baddr_gen__osaddr ) , + .opaddr ( baddr_gen__opaddr ) , + .obitinv ( ) // n.u. + ); + + assign obsaddr = baddr_gen__osaddr[pADDR_W-1 : 0]; + assign obpaddr = baddr_gen__opaddr[pADDR_W-1 : 0]; //------------------------------------------------------------------------------------------------------ // MAP engine diff --git a/rtl/rsc/dec/rsc_dec_map_engine.sv b/rtl/rsc/dec/rsc_dec_map_engine.sv index 65cdfb6..537d13a 100644 --- a/rtl/rsc/dec/rsc_dec_map_engine.sv +++ b/rtl/rsc/dec/rsc_dec_map_engine.sv @@ -140,11 +140,13 @@ assign rsc_dec_map_engine__ifyLLR = '0 ; assign rsc_dec_map_engine__ifwLLR = '0 ; assign rsc_dec_map_engine__ifLextr = '0 ; + assign rsc_dec_map_engine__ifsLLRtag = '0 ; assign rsc_dec_map_engine__ibaddr = '0 ; assign rsc_dec_map_engine__ibsLLR = '0 ; assign rsc_dec_map_engine__ibyLLR = '0 ; assign rsc_dec_map_engine__ibwLLR = '0 ; assign rsc_dec_map_engine__ibLextr = '0 ; + assign rsc_dec_map_engine__ibsLLRtag = '0 ; assign rsc_dec_map_engine__if_rp_state_even = '0 ; assign rsc_dec_map_engine__if_rp_state_odd = '0 ; assign rsc_dec_map_engine__ib_rp_state_even = '0 ; diff --git a/rtl/rsc2/README.md b/rtl/rsc2/README.md new file mode 100644 index 0000000..8b19663 --- /dev/null +++ b/rtl/rsc2/README.md @@ -0,0 +1,19 @@ +Dynamic configuration DVB-RSC2 (ETSI EN 301 545-2 V1.2.1) duo-binary convolution turbo code with MAX-Log-MAP decoding. + +Supported modes: all modes defined in Table A-1/2/4/5 + +Supports code rates: [1/3; 1/2; 2/3; 3/4; 4/5; 5/6; 6/7; 7/8] + +Encoder uses two pass coding with minimal delays. + +Decoder uses special MAP engine with 1 duo-bits per tick processing and simultaneous forward/backard recursion. + +vivado 2019.1 Artix 7 - 2 + +Wimax OFDMA Nduobits = 152(304 bits), coderate = 1/2, 5bit metric, 10 iteration. Encoder use output buffer + +Encoder : LUT/REG/RAMB 330/255/2.0 >200MHz (245Mbps -> 490Mbps) + +Decoder simple : LUT/REG/RAMB 9.5k/8k/10.0 ~160MHz (29Mbps -> 14.5Mbps) + +Attention: This is only CTC codec. There is no bits permutation or interleaving. The coder and decoder correspond each other but can have different bit order with standard codes. diff --git a/rtl/rsc2/dec/rsc2_dec.sv b/rtl/rsc2/dec/rsc2_dec.sv new file mode 100644 index 0000000..a0f28ef --- /dev/null +++ b/rtl/rsc2/dec/rsc2_dec.sv @@ -0,0 +1,650 @@ +/* + + + + parameter int pLLR_W = 4 ; + parameter int pLLR_FP = 4 ; + parameter int pODAT_W = 2 ; + parameter int pTAG_W = 8 ; + // + parameter int pN_MAX = 64 ; + // + parameter int pMMAX_TYPE = 0 ; + parameter bit pUSE_W_BIT = 0 ; + // + parameter bit pUSE_RP_P_COMP = 1 ; + parameter bit pUSE_RAM_PIPE = 1 ; + // + parameter bit pUSE_SRC_EOP_VAL_MASK = 1 ; + + logic rsc2_dec__iclk ; + logic rsc2_dec__ireset ; + logic rsc2_dec__iclkena ; + logic [3 : 0] rsc2_dec__icode ; + logic [5 : 0] rsc2_dec__iptype ; + logic [3 : 0] rsc2_dec__iNiter ; + logic [pTAG_W-1 : 0] rsc2_dec__itag ; + logic rsc2_dec__isop ; + logic rsc2_dec__ieop ; + logic rsc2_dec__ieof ; + logic rsc2_dec__ival ; + logic signed [pLLR_W-1 : 0] rsc2_dec__iLLR [0 : 1] ; + logic rsc2_dec__obusy ; + logic rsc2_dec__ordy ; + logic rsc2_dec__ireq ; + logic rsc2_dec__ofull ; + logic [pTAG_W-1 : 0] rsc2_dec__otag ; + logic rsc2_dec__osop ; + logic rsc2_dec__oeop ; + logic rsc2_dec__oval ; + logic [1 : 0] rsc2_dec__odat ; + logic [15 : 0] rsc2_dec__oerr ; + + + + rsc2_dec + #( + .pLLR_W ( pLLR_W ) , + .pLLR_FP ( pLLR_FP ) , + .pODAT_W ( pODAT_W ) , + .pTAG_W ( pTAG_W ) , + // + .pN_MAX ( pN_MAX ) , + // + .pMMAX_TYPE ( pMMAX_TYPE ) , + .pUSE_W_BIT ( pUSE_W_BIT ) , + // + .pUSE_RP_P_COMP ( pUSE_RP_P_COMP ) , + .pUSE_RAM_PIPE ( pUSE_RAM_PIPE ) , + // + .pUSE_SRC_EOP_VAL_MASK ( pUSE_SRC_EOP_VAL_MASK ) + ) + rsc2_dec + ( + .iclk ( rsc2_dec__iclk ) , + .ireset ( rsc2_dec__ireset ) , + .iclkena ( rsc2_dec__iclkena ) , + .icode ( rsc2_dec__icode ) , + .iptype ( rsc2_dec__iptype ) , + .iNiter ( rsc2_dec__iNiter ) , + .itag ( rsc2_dec__itag ) , + .isop ( rsc2_dec__isop ) , + .ieop ( rsc2_dec__ieop ) , + .ieof ( rsc2_dec__ieof ) , + .ival ( rsc2_dec__ival ) , + .iLLR ( rsc2_dec__iLLR ) , + .obusy ( rsc2_dec__obusy ) , + .ordy ( rsc2_dec__ordy ) , + .ireq ( rsc2_dec__ireq ) , + .ofull ( rsc2_dec__ofull ) , + .otag ( rsc2_dec__otag ) , + .osop ( rsc2_dec__osop ) , + .oeop ( rsc2_dec__oeop ) , + .oval ( rsc2_dec__oval ) , + .odat ( rsc2_dec__odat ) , + .oerr ( rsc2_dec__oerr ) + ); + + + assign rsc2_dec__iclk = '0 ; + assign rsc2_dec__ireset = '0 ; + assign rsc2_dec__iclkena = '0 ; + assign rsc2_dec__icode = '0 ; + assign rsc2_dec__iptype = '0 ; + assign rsc2_dec__iNiter = '0 ; + assign rsc2_dec__itag = '0 ; + assign rsc2_dec__isop = '0 ; + assign rsc2_dec__ieop = '0 ; + assign rsc2_dec__ieof = '0 ; + assign rsc2_dec__ival = '0 ; + assign rsc2_dec__iLLR = '0 ; + assign rsc2_dec__ireq = '0 ; + + + +*/ + +// +// Project : rsc2 +// Author : Shekhalev Denis (des00) +// Workfile : rsc2_dec.sv +// Description : top level for rsc2 decoder components with dynamic parameters change on fly +// Data process path is : +// source -> 2D input buffer -> decoder + extr_ram -> 2D buffer -> sink +// + +`include "define.vh" + +module rsc2_dec +#( + parameter int pLLR_W = 5 , // LLR width + parameter int pLLR_FP = pLLR_W-2 , // LLR fixed point + parameter int pODAT_W = 2 , // Output data width 2/4/8 + parameter int pTAG_W = 8 , // Tag port bitwidth + // + parameter int pN_MAX = 512 , // maximum number of data duobit's <= 4096 + // + parameter int pMMAX_TYPE = 0 , // 0 - max Log Map (only supported) + // 1 - const 1 max Log Map + parameter bit pUSE_W_BIT = 1 , // 0/1 - not use/use coderate with W bits (icode == 0 or icode == 10/11) + // + parameter bit pUSE_RP_P_COMP = 1 , // use parallel comparator for recursion processor + parameter bit pUSE_RAM_PIPE = 1 , // pipeline rams inside dec_engine + // + parameter bit pUSE_SRC_EOP_VAL_MASK = 1 // use ieop with ival ANDED, else use single ieop +) +( + iclk , + ireset , + iclkena , + // + icode , + iptype , + iNiter , + // + itag , + isop , + ieop , + ival , + iLLR , + // + obusy , + ordy , + // + ireq , + ofull , + // + otag , + osop , + oeop , + oval , + odat , + // + oerr +); + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + input logic iclk ; + input logic ireset ; + input logic iclkena ; + // + input logic [3 : 0] icode ; // coderate [0 : 7] - [1/3; 1/2; 2/3; 3/4; 4/5; 5/6; 6/7; 7/8] + input logic [5 : 0] iptype ; // permutation type [ 0: 33] - reordered Table A-1/2/4/5 + input logic [3 : 0] iNiter ; // number of iteration >= 2 + // + input logic [pTAG_W-1 : 0] itag ; + input logic isop ; + input logic ieop ; + input logic ival ; + input logic signed [pLLR_W-1 : 0] iLLR [0 : 1] ; + // input handshake interface + output logic obusy ; + output logic ordy ; + // output data ready/request interface + input logic ireq ; + output logic ofull ; + // + output logic [pTAG_W-1 : 0] otag ; + output logic osop ; + output logic oeop ; + output logic oval ; + output logic [pODAT_W-1 : 0] odat ; + // + output logic [15 : 0] oerr ; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + `include "../rsc2_constants.svh" + `include "rsc2_dec_types.svh" + + localparam int cADDR_W = clogb2(pN_MAX); + + localparam int cIB_TAG_W = $bits(code_ctx_t) + $bits(iNiter) + pTAG_W; // {used_code_ctx, Niter, tag} + localparam int cOB_TAG_W = 16 + $bits(dbits_num_t) + pTAG_W; // {decerr, iN, tag} + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + code_ctx_t used_code_ctx ; + + // source + logic source__ifulla ; + logic source__iemptya ; + + logic source__owrite ; + logic source__owfull ; + logic [1 : 0] source__owsel ; + logic [cADDR_W-1 : 0] source__owaddr ; + bit_llr_t source__osLLR [0 : 1] ; + bit_llr_t source__oyLLR [0 : 1] ; + bit_llr_t source__owLLR [0 : 1] ; + + // input buffer + logic [cIB_TAG_W-1 : 0] ibuffer__iwtag ; + + logic ibuffer__irempty ; + logic [cADDR_W-1 : 0] ibuffer__ifsaddr ; + bit_llr_t ibuffer__ofsLLR [0 : 1] ; + logic [cADDR_W-1 : 0] ibuffer__ifpaddr ; + bit_llr_t ibuffer__ofyLLR [0 : 1] ; + bit_llr_t ibuffer__ofwLLR [0 : 1] ; + + logic [cADDR_W-1 : 0] ibuffer__ibsaddr ; + bit_llr_t ibuffer__obsLLR [0 : 1] ; + logic [cADDR_W-1 : 0] ibuffer__ibpaddr ; + bit_llr_t ibuffer__obyLLR [0 : 1] ; + bit_llr_t ibuffer__obwLLR [0 : 1] ; + + logic [cIB_TAG_W-1 : 0] ibuffer__ortag ; + + logic ibuffer__oempty ; + logic ibuffer__oemptya ; + logic ibuffer__ofull ; + logic ibuffer__ofulla ; + // + // decoder engine + logic engine__irbuf_full ; + code_ctx_t engine__icode_ctx ; + logic [3 : 0] engine__iNiter ; + logic [pTAG_W-1 : 0] engine__irtag ; + logic engine__orempty ; + // + bit_llr_t engine__irfsLLR [2] ; + bit_llr_t engine__irfyLLR [2] ; + bit_llr_t engine__irfwLLR [2] ; + logic [cADDR_W-1 : 0] engine__ofsaddr ; + logic [cADDR_W-1 : 0] engine__ofpaddr ; + // + bit_llr_t engine__irbsLLR [2] ; + bit_llr_t engine__irbyLLR [2] ; + bit_llr_t engine__irbwLLR [2] ; + logic [cADDR_W-1 : 0] engine__obsaddr ; + logic [cADDR_W-1 : 0] engine__obpaddr ; + // + logic engine__iwbuf_empty ; + // + logic engine__owrite ; + logic engine__owfull ; + dbits_num_t engine__ownum ; + logic [pTAG_W-1 : 0] engine__owtag ; + logic [15 : 0] engine__owerr ; + // + logic [cADDR_W-1 : 0] engine__owfaddr ; + logic [1 : 0] engine__owfdat ; + // + logic [cADDR_W-1 : 0] engine__owbaddr ; + logic [1 : 0] engine__owbdat ; + // + // output buffer + logic obuffer__iwrite ; + logic obuffer__iwfull ; + + logic [cADDR_W-1 : 0] obuffer__ifwaddr ; + logic [1 : 0] obuffer__ifwdat ; + logic [cADDR_W-1 : 0] obuffer__ibwaddr ; + logic [1 : 0] obuffer__ibwdat ; + logic [cOB_TAG_W-1 : 0] obuffer__iwtag ; + + logic obuffer__irempty ; + logic [cADDR_W-1 : 0] obuffer__iraddr ; + logic [pODAT_W-1 : 0] obuffer__ordata ; + logic [cOB_TAG_W-1 : 0] obuffer__ortag ; + + logic obuffer__oempty ; + logic obuffer__oemptya ; + logic obuffer__ofull ; + logic obuffer__ofulla ; + // + // sink + dbits_num_t sink__iN ; + logic sink__ifull ; + logic [pODAT_W-1 : 0] sink__irdata ; + logic [15 : 0] sink__ierr ; + logic [pTAG_W-1 : 0] sink__itag ; + logic sink__orempty ; + logic [cADDR_W-1 : 0] sink__oraddr ; + + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + // synthesis translate_off + + logic [12 : 0] ntable__oN; + + rsc2_ntable + ntable + ( + .iptype ( iptype ) , + .oN ( ntable__oN ) , + .oNm1 ( ) + ); + + initial begin : info + @(posedge iclk iff iclkena & ival & isop); + $display("bw paramters used for decoding:"); + $display("block length %0d. code rate %0d", ntable__oN, icode); + case (pMMAX_TYPE) + 1 : $display("C=1.5 MaxLog Map"); + 2 : $display("C=2.0 MaxLog Map"); + 3 : $display("LUT MaxLog Map"); + default : $display("MaxLog Map"); + endcase + $display("iteration number : %0d", iNiter); + $display("fixed point_w : %0d", pLLR_FP); + $display("input bit LLR : %0d", $size(bit_llr_t)); + $display("duo bit LLR : %0d", $size(dbit_llr_t)); + $display("extrinsic (Lext) LLR : %0d", $size(extr_llr_t), 2**(cL_EXT_W-1)-1); + $display("trellis state (alpha/beta) LLR : %0d, max state : %0d", $size(trel_state_t), 2**(cSTATE_W-2)); + $display("trellis Lapo LLR : %0d", $size(trel_branch_t)); + end + // synthesis translate_on + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + assign used_code_ctx.code = icode ; + assign used_code_ctx.ptype = iptype ; + + //------------------------------------------------------------------------------------------------------ + // source module + //------------------------------------------------------------------------------------------------------ + + rsc2_dec_source + #( + .pLLR_W ( pLLR_W ) , + .pLLR_FP ( pLLR_FP ) , + .pADDR_W ( cADDR_W ) , + .pUSE_W_BIT ( pUSE_W_BIT ) , + .pUSE_EOP_VAL_MASK ( pUSE_SRC_EOP_VAL_MASK ) + ) + source + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .icode ( icode ) , // drive by input parameters + .iptype ( iptype ) , + // input interface + .isop ( isop ) , + .ieop ( ieop ) , + .ival ( ival ) , + .iLLR ( iLLR ) , + // + .ifulla ( source__ifulla ) , + .iemptya ( source__iemptya ) , + // + .obusy ( obusy ) , + .ordy ( ordy ) , + // ibuffer interface + .owrite ( source__owrite ) , + .owfull ( source__owfull ) , + .owsel ( source__owsel ) , + .owaddr ( source__owaddr ) , + .osLLR ( source__osLLR ) , + .oyLLR ( source__oyLLR ) , + .owLLR ( source__owLLR ) + ); + + assign source__ifulla = ibuffer__ofulla; + assign source__iemptya = ibuffer__oemptya; + + //------------------------------------------------------------------------------------------------------ + // input buffer + //------------------------------------------------------------------------------------------------------ + + rsc_dec_input_buffer + #( + .pLLR_W ( pLLR_W ) , + .pADDR_W ( cADDR_W ) , + // + .pTAG_W ( cIB_TAG_W ) , + // + .pBNUM_W ( 1 ) , // 2D + // + .pDPIPE ( pUSE_RAM_PIPE ) // no pipe + ) + ibuffer + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .iwrite ( source__owrite ) , + .iwfull ( source__owfull ) , + .iwsel ( source__owsel ) , + .iwaddr ( source__owaddr ) , + .isLLR ( source__osLLR ) , + .iyLLR ( source__oyLLR ) , + .iwLLR ( source__owLLR ) , + // + .iwtag ( ibuffer__iwtag ) , + // + .irempty ( ibuffer__irempty ) , + // + .ifsaddr ( ibuffer__ifsaddr ) , + .ofsLLR ( ibuffer__ofsLLR ) , + // + .ifpaddr ( ibuffer__ifpaddr ) , + .ofyLLR ( ibuffer__ofyLLR ) , + .ofwLLR ( ibuffer__ofwLLR ) , + // + .ibsaddr ( ibuffer__ibsaddr ) , + .obsLLR ( ibuffer__obsLLR ) , + // + .ibpaddr ( ibuffer__ibpaddr ) , + .obyLLR ( ibuffer__obyLLR ) , + .obwLLR ( ibuffer__obwLLR ) , + // + .ortag ( ibuffer__ortag ) , + // + .oempty ( ibuffer__oempty ) , + .oemptya ( ibuffer__oemptya ) , + .ofull ( ibuffer__ofull ) , + .ofulla ( ibuffer__ofulla ) + ); + + always_ff @(posedge iclk) begin + if (iclkena) begin + if (isop & ival) begin + ibuffer__iwtag <= {used_code_ctx, iNiter, itag}; // {used_code_ctx, Niter, tag} + end + end + end + + assign ibuffer__irempty = engine__orempty; + + assign ibuffer__ifsaddr = engine__ofsaddr; + assign ibuffer__ifpaddr = engine__ofpaddr; + + assign ibuffer__ibsaddr = engine__obsaddr; + assign ibuffer__ibpaddr = engine__obpaddr; + + //------------------------------------------------------------------------------------------------------ + // decoder engine + //------------------------------------------------------------------------------------------------------ + + rsc2_dec_engine + #( + .pLLR_W ( pLLR_W ) , + .pLLR_FP ( pLLR_FP ) , + .pADDR_W ( cADDR_W ) , + .pTAG_W ( pTAG_W ) , + // + .pMMAX_TYPE ( pMMAX_TYPE ) , + .pUSE_IBUF_PIPE ( pUSE_RAM_PIPE ) , + .pUSE_RP_P_COMP ( pUSE_RP_P_COMP ) + ) + engine + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .irbuf_full ( engine__irbuf_full ) , + .icode_ctx ( engine__icode_ctx ) , + .iNiter ( engine__iNiter ) , + .irtag ( engine__irtag ) , + .orempty ( engine__orempty ) , + // + .irfsLLR ( engine__irfsLLR ) , + .irfyLLR ( engine__irfyLLR ) , + .irfwLLR ( engine__irfwLLR ) , + .irfsLLRtag ( '0 ) , // n.u. + .ofsaddr ( engine__ofsaddr ) , + .ofpaddr ( engine__ofpaddr ) , + // + .irbsLLR ( engine__irbsLLR ) , + .irbyLLR ( engine__irbyLLR ) , + .irbwLLR ( engine__irbwLLR ) , + .irbsLLRtag ( '0 ) , // n.u + .obsaddr ( engine__obsaddr ) , + .obpaddr ( engine__obpaddr ) , + // + .iwbuf_empty ( engine__iwbuf_empty ) , + // + .owrite ( engine__owrite ) , + .owfull ( engine__owfull ) , + .ownum ( engine__ownum ) , + .owtag ( engine__owtag ) , + .owerr ( engine__owerr ) , + // + .owfaddr ( engine__owfaddr ) , + .owfdat ( engine__owfdat ) , + .owfderr ( ) , + .owfdtag ( ) , // n.u. + // + .owbaddr ( engine__owbaddr ) , + .owbdat ( engine__owbdat ) , + .owbderr ( ) , + .owbdtag ( ) // n.u + ); + + assign engine__irbuf_full = ibuffer__ofull; + + always_comb begin + {engine__icode_ctx, + engine__iNiter, + engine__irtag} = ibuffer__ortag; // {used_code_ctx, Niter, tag} + end + + assign engine__irfsLLR = ibuffer__ofsLLR ; + assign engine__irfyLLR = ibuffer__ofyLLR ; + assign engine__irfwLLR = pUSE_W_BIT ? ibuffer__ofwLLR : '{default : '0}; + + assign engine__irbsLLR = ibuffer__obsLLR ; + assign engine__irbyLLR = ibuffer__obyLLR ; + assign engine__irbwLLR = pUSE_W_BIT ? ibuffer__obwLLR : '{default : '0}; + + assign engine__iwbuf_empty = obuffer__oempty ; + + //------------------------------------------------------------------------------------------------------ + // output buffer + //------------------------------------------------------------------------------------------------------ + + rsc_dec_output_buffer + #( + .pADDR_W ( cADDR_W ) , + .pWDAT_W ( 2 ) , + .pRDAT_W ( pODAT_W ) , + // + .pTAG_W ( cOB_TAG_W ) , + // + .pBNUM_W ( 1 ) , // 2D + .pWPIPE ( pUSE_RAM_PIPE ) + ) + obuffer + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .iwrite ( obuffer__iwrite ) , + .iwfull ( obuffer__iwfull ) , + // + .ifwaddr ( obuffer__ifwaddr ) , + .ifwdat ( obuffer__ifwdat ) , + .ibwaddr ( obuffer__ibwaddr ) , + .ibwdat ( obuffer__ibwdat ) , + // + .iwtag ( obuffer__iwtag ) , + // + .irempty ( obuffer__irempty ) , + .iraddr ( obuffer__iraddr ) , + .ordata ( obuffer__ordata ) , + // + .ortag ( obuffer__ortag ) , + // + .oempty ( obuffer__oempty ) , + .oemptya ( obuffer__oemptya ) , + .ofull ( obuffer__ofull ) , + .ofulla ( obuffer__ofulla ) + ); + + assign obuffer__iwrite = engine__owrite ; + assign obuffer__iwfull = engine__owfull ; + + assign obuffer__ifwaddr = engine__owfaddr ; + assign obuffer__ifwdat = engine__owfdat ; + assign obuffer__ibwaddr = engine__owbaddr ; + assign obuffer__ibwdat = engine__owbdat ; + + assign obuffer__iwtag = {engine__owerr, engine__ownum, engine__owtag}; + + assign obuffer__irempty = sink__orempty; + assign obuffer__iraddr = sink__oraddr ; + + //------------------------------------------------------------------------------------------------------ + // sink module + //------------------------------------------------------------------------------------------------------ + + rsc_dec_sink + #( + .pADDR_W ( cADDR_W ) , + .pDAT_W ( pODAT_W ) , + .pTAG_W ( pTAG_W ) + ) + sink + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .iN ( sink__iN ) , + // + .ifull ( sink__ifull ) , + .irdata ( sink__irdata ) , + .irderr ( '0 ) , // n.u. + .irdtag ( '0 ) , // n.u. + .ierr ( sink__ierr ) , + .itag ( sink__itag ) , + .orempty ( sink__orempty ) , + .oraddr ( sink__oraddr ) , + // + .ireq ( ireq ) , + .ofull ( ofull ) , + // + .osop ( osop ) , + .oeop ( oeop ) , + .oval ( oval ) , + .odat ( odat ) , + .oderr ( ) , // n.u. + .odtag ( ) , // n.u. + .otag ( otag ) , + .oerr ( oerr ) + ); + + assign sink__ifull = obuffer__ofull; + assign sink__irdata = obuffer__ordata; + + assign {sink__ierr, sink__iN, sink__itag} = obuffer__ortag; + +endmodule + diff --git a/rtl/rsc2/dec/rsc2_dec_Lapo.sv b/rtl/rsc2/dec/rsc2_dec_Lapo.sv new file mode 100644 index 0000000..9a821cb --- /dev/null +++ b/rtl/rsc2/dec/rsc2_dec_Lapo.sv @@ -0,0 +1,249 @@ +/* + + + + parameter bit pB_nF = 0 ; + parameter int pLLR_W = 5 ; + parameter int pLLR_FP = 3 ; + parameter int pMMAX_TYPE = 0; + + + + logic rsc2_dec_Lapo__iclk ; + logic rsc2_dec_Lapo__ireset ; + logic rsc2_dec_Lapo__iclkena ; + logic rsc2_dec_Lapo__ival ; + gamma_t rsc2_dec_Lapo__igamma ; + state_t rsc2_dec_Lapo__istate ; + logic rsc2_dec_Lapo__oval ; + Lapo_t rsc2_dec_Lapo__oLapo ; + + + + rsc2_dec_Lapo + #( + .pB_nF ( pB_nF ) , + .pLLR_W ( pLLR_W ) , + .pLLR_FP ( pLLR_FP ) , + .pMMAX_TYPE ( pMMAX_TYPE ) + ) + rsc2_dec_Lapo + ( + .iclk ( rsc2_dec_Lapo__iclk ) , + .ireset ( rsc2_dec_Lapo__ireset ) , + .iclkena ( rsc2_dec_Lapo__iclkena ) , + .ival ( rsc2_dec_Lapo__ival ) , + .igamma ( rsc2_dec_Lapo__igamma ) , + .istate ( rsc2_dec_Lapo__istate ) , + .oval ( rsc2_dec_Lapo__oval ) , + .oLapo ( rsc2_dec_Lapo__oLapo ) + ); + + + assign rsc2_dec_Lapo__iclk = '0 ; + assign rsc2_dec_Lapo__ireset = '0 ; + assign rsc2_dec_Lapo__iclkena = '0 ; + assign rsc2_dec_Lapo__ival = '0 ; + assign rsc2_dec_Lapo__igamma = '0 ; + assign rsc2_dec_Lapo__istate = '0 ; + + + +*/ + +// +// Project : rsc2 +// Author : Shekhalev Denis (des00) +// Workfile : rsc2_dec_Lextr.sv +// Description : module to count aposteriory LLR : sum(bm(s, s')) = sum(alpha(s, k) * gamma_e(s, s') * beta(s',k+1)) +// Module latency us 5 tick. +// + +module rsc2_dec_Lapo +#( + parameter bit pB_nF = 0 , + parameter int pLLR_W = 5 , + parameter int pLLR_FP = 3 , + parameter int pMMAX_TYPE = 0 +) +( + iclk , + ireset , + iclkena , + // + ival , + igamma , + istate , + // + oval , + oLapo +); + + `include "rsc2_dec_types.svh" + `include "rsc2_trellis.svh" + `include "rsc2_mmax.svh" + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + input logic iclk ; + input logic ireset ; + input logic iclkena ; + // + input logic ival ; + input gamma_t igamma ; // pB_nF ? (gamma_e + beta [k+1]) : (gamma_e + alpha [k]) + input state_t istate ; // pB_nF ? alpha [k] beta [k+1]) + // + output logic oval ; + output Lapo_t oLapo ; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + logic [5 : 0] val; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + always_ff @(posedge iclk or posedge ireset) begin + if (ireset) + val <= '0; + else if (iclkena) + val <= (val << 1) | ival; + end + + //------------------------------------------------------------------------------------------------------ + // bm(s, s') = alpha(s, k) * gamma_e(s, s') * beta(s',k+1) + //------------------------------------------------------------------------------------------------------ + + bm_t bm ; + + generate + if (pB_nF) begin + always_ff @(posedge iclk) begin + if (iclkena) begin + if (ival) begin + for (int state = 0; state < 16; state++) begin + for (int inb = 0; inb < 4; inb++) begin + bm[state][inb] <= igamma[state][inb] + istate[state]; + end // inb + end // state + end // ival + end // iclkena + end // iclk + end + else begin + always_ff @(posedge iclk) begin + if (iclkena) begin + if (ival) begin + for (int state = 0; state < 16; state++) begin + for (int inb = 0; inb < 4; inb++) begin + bm[state][inb] <= igamma[state][inb] + istate[trel.nextStates[state][inb]]; + end // inb + end // state + end // ival + end // iclkena + end // iclk + end + endgenerate + + //------------------------------------------------------------------------------------------------------ + // sum(bm(s, duobit_data)) + //------------------------------------------------------------------------------------------------------ + + trel_branch_t tmp01 [4]; + trel_branch_t tmp23 [4]; + trel_branch_t tmp45 [4]; + trel_branch_t tmp67 [4]; + trel_branch_t tmp89 [4]; + trel_branch_t tmpAB [4]; + trel_branch_t tmpCD [4]; + trel_branch_t tmpEF [4]; + + trel_branch_t tmp0123 [4]; + trel_branch_t tmp4567 [4]; + trel_branch_t tmp89AB [4]; + trel_branch_t tmpCDEF [4]; + + trel_branch_t tmp01234567 [4]; + trel_branch_t tmp89ABCDEF [4]; + + trel_branch_t tmpLLR [4]; + + always_ff @(posedge iclk) begin + if (iclkena) begin + for (int inb = 0; inb < 4; inb++) begin + if (pMMAX_TYPE == 1) begin + // layer 1 + if (val[0]) begin + tmp01[inb] <= bm_mmax1(bm[0][inb], bm[1][inb]); + tmp23[inb] <= bm_mmax1(bm[2][inb], bm[3][inb]); + tmp45[inb] <= bm_mmax1(bm[4][inb], bm[5][inb]); + tmp67[inb] <= bm_mmax1(bm[6][inb], bm[7][inb]); + tmp89[inb] <= bm_mmax1(bm[8][inb], bm[9][inb]); + tmpAB[inb] <= bm_mmax1(bm[10][inb], bm[11][inb]); + tmpCD[inb] <= bm_mmax1(bm[12][inb], bm[13][inb]); + tmpEF[inb] <= bm_mmax1(bm[14][inb], bm[15][inb]); + end + // layer 2 + if (val[1]) begin + tmp0123[inb] <= bm_mmax1(tmp01[inb], tmp23[inb]); + tmp4567[inb] <= bm_mmax1(tmp45[inb], tmp67[inb]); + tmp89AB[inb] <= bm_mmax1(tmp89[inb], tmpAB[inb]); + tmpCDEF[inb] <= bm_mmax1(tmpCD[inb], tmpEF[inb]); + end + // layer 3 + if (val[2]) begin + tmp01234567[inb] <= bm_mmax1(tmp0123[inb], tmp4567[inb]); + tmp89ABCDEF[inb] <= bm_mmax1(tmp89AB[inb], tmpCDEF[inb]); + end + // layer 4 + if (val[3]) begin + tmpLLR[inb] <= bm_mmax1(tmp01234567[inb], tmp89ABCDEF[inb]); + end + end + else begin + // layer 1 + if (val[0]) begin + tmp01[inb] <= bm_mmax(bm[0][inb], bm[1][inb]); + tmp23[inb] <= bm_mmax(bm[2][inb], bm[3][inb]); + tmp45[inb] <= bm_mmax(bm[4][inb], bm[5][inb]); + tmp67[inb] <= bm_mmax(bm[6][inb], bm[7][inb]); + tmp89[inb] <= bm_mmax(bm[8][inb], bm[9][inb]); + tmpAB[inb] <= bm_mmax(bm[10][inb], bm[11][inb]); + tmpCD[inb] <= bm_mmax(bm[12][inb], bm[13][inb]); + tmpEF[inb] <= bm_mmax(bm[14][inb], bm[15][inb]); + end + // layer 2 + if (val[1]) begin + tmp0123[inb] <= bm_mmax(tmp01[inb], tmp23[inb]); + tmp4567[inb] <= bm_mmax(tmp45[inb], tmp67[inb]); + tmp89AB[inb] <= bm_mmax(tmp89[inb], tmpAB[inb]); + tmpCDEF[inb] <= bm_mmax(tmpCD[inb], tmpEF[inb]); + end + // layer 3 + if (val[2]) begin + tmp01234567[inb] <= bm_mmax(tmp0123[inb], tmp4567[inb]); + tmp89ABCDEF[inb] <= bm_mmax(tmp89AB[inb], tmpCDEF[inb]); + end + // layer 4 + if (val[3]) begin + tmpLLR[inb] <= bm_mmax(tmp01234567[inb], tmp89ABCDEF[inb]); + end + end + end + // offset + if (val[4]) begin + for (int i = 1; i < 4; i++) begin + oLapo[i] <= tmpLLR[i] - tmpLLR[0]; + end + end + end + end + + assign oval = val[5]; + +endmodule diff --git a/rtl/rsc2/dec/rsc2_dec_Lextr.sv b/rtl/rsc2/dec/rsc2_dec_Lextr.sv new file mode 100644 index 0000000..415e29f --- /dev/null +++ b/rtl/rsc2/dec/rsc2_dec_Lextr.sv @@ -0,0 +1,233 @@ +/* + + + + parameter int pLLR_W = 5 ; + parameter int pLLR_FP = 3 ; + parameter int pMMAX_TYPE = 0 ; + + + + logic rsc2_dec_Lextr__iclk ; + logic rsc2_dec_Lextr__ireset ; + logic rsc2_dec_Lextr__iclkena ; + logic rsc2_dec_Lextr__ival ; + logic rsc2_dec_Lextr__ibitswap ; + logic [1 : 0] rsc2_dec_Lextr__idat ; + Lapri_t rsc2_dec_Lextr__iLapri ; + Lapo_t rsc2_dec_Lextr__iLapo ; + logic rsc2_dec_Lextr__oval ; + Lextr_t rsc2_dec_Lextr__oLextr ; + logic [1 : 0] rsc2_dec_Lextr__odat ; + logic [1 : 0] rsc2_dec_Lextr__oerr ; + + + + rsc2_dec_Lextr + #( + .pLLR_W ( pLLR_W ) , + .pLLR_FP ( pLLR_FP ) , + .pMMAX_TYPE ( pMMAX_TYPE ) + ) + rsc2_dec_Lextr + ( + .iclk ( rsc2_dec_Lextr__iclk ) , + .ireset ( rsc2_dec_Lextr__ireset ) , + .iclkena ( rsc2_dec_Lextr__iclkena ) , + .ival ( rsc2_dec_Lextr__ival ) , + .ibitswap ( rsc2_dec_Lextr__ibitswap ) , + .idat ( rsc2_dec_Lextr__idat ) , + .iLapri ( rsc2_dec_Lextr__iLapri ) , + .iLapo ( rsc2_dec_Lextr__iLapo ) , + .oval ( rsc2_dec_Lextr__oval ) , + .oLextr ( rsc2_dec_Lextr__oLextr ) , + .odat ( rsc2_dec_Lextr__odat ) , + .oerr ( rsc2_dec_Lextr__oerr ) + ); + + + assign rsc2_dec_Lextr__iclk = '0 ; + assign rsc2_dec_Lextr__ireset = '0 ; + assign rsc2_dec_Lextr__iclkena = '0 ; + assign rsc2_dec_Lextr__ival = '0 ; + assign rsc2_dec_Lextr__ibitswap = '0 ; + assign rsc2_dec_Lextr__idat = '0 ; + assign rsc2_dec_Lextr__iLapri = '0 ; + assign rsc2_dec_Lextr__iLapo = '0 ; + + + +*/ + +// +// Project : rsc2 +// Author : Shekhalev Denis (des00) +// Workfile : rsc2_dec_Lextr.sv +// Description : module to count sub iteration results : Lextr, bit pairs and estimated corrected errror. +// Module latency is 2 tick. +// + +module rsc2_dec_Lextr +#( + parameter int pLLR_W = 5 , + parameter int pLLR_FP = 3 , + parameter int pMMAX_TYPE = 0 +) +( + iclk , + ireset , + iclkena , + // + ival , + ibitswap , + idat , + iLapri , + iLapo , + // + oval , + oLextr , + odat , + oerr +); + + `include "rsc2_dec_types.svh" + `include "rsc2_trellis.svh" + `include "rsc2_mmax.svh" + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + input logic iclk ; + input logic ireset ; + input logic iclkena ; + // + input logic ival ; + input logic ibitswap ; + input logic [1 : 0] idat ; + input Lapri_t iLapri ; + input Lapo_t iLapo ; + // + output logic oval ; + output Lextr_t oLextr ; + output logic [1 : 0] odat ; + output logic [1 : 0] oerr ; + + //------------------------------------------------------------------------------------------------------ + // reverse pair permutation + //------------------------------------------------------------------------------------------------------ + + Lapri_t ind ; + Lapo_t outd; + + assign ind[1] = ibitswap ? iLapri [2] : iLapri[1] ; + assign ind[2] = ibitswap ? iLapri [1] : iLapri[2] ; + assign ind[3] = iLapri[3] ; + + assign outd[1] = ibitswap ? iLapo [2] : iLapo [1] ; + assign outd[2] = ibitswap ? iLapo [1] : iLapo [2] ; + assign outd[3] = iLapo [3] ; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + logic [1 : 0] val; + + always_ff @(posedge iclk or posedge ireset) begin + if (ireset) begin + val <= '0; + end + else if (iclkena) begin + val <= (val << 1) | ival; + end + end + + //------------------------------------------------------------------------------------------------------ + // Lext + //------------------------------------------------------------------------------------------------------ + + Lapo_t Lext; + + always_ff @(posedge iclk) begin + if (iclkena) begin + if (ival) begin + for (int i = 1; i < 4; i++) begin + Lext[i] <= outd[i] - ind[i]; + end + end // ival + end // iclk + end + + trel_branch_p2_t Lext_scale_sum [1:3]; + Lapo_t Lext_scale; + logic Lext_scale_sign [1:3]; + logic Lext_scale_ovf [1:3]; + Lextr_t Lext_scale_ovf_value; + + always_comb begin + for (int i = 1; i < 4; i++) begin + Lext_scale_sum [i] = (Lext[i] <<< 1) + Lext[i]; + Lext_scale [i] = Lext_scale_sum[i] >>> 2; // 0.75 + // + Lext_scale_sign [i] = Lext_scale[i][cGAMMA_W-1]; + Lext_scale_ovf [i] = Lext_scale_sign[i] ? !(&Lext_scale[i][cGAMMA_W-1 : cL_EXT_W-1]) : + (|Lext_scale[i][cGAMMA_W-1 : cL_EXT_W-1]) ; + + Lext_scale_ovf_value[i] = {Lext_scale_sign[i], ~{{cL_EXT_W-2}{Lext_scale_sign[i]}}, 1'b1}; + end + end + + always_ff @(posedge iclk) begin + if (iclkena) begin + if (val[0]) begin + for (int i = 1; i < 4; i++) begin + oLextr[i] <= Lext_scale_ovf[i] ? Lext_scale_ovf_value[i] : (Lext_scale[i][cL_EXT_W-1:0] + Lext_scale_sign[i]); + end + end + end + end + + //------------------------------------------------------------------------------------------------------ + // odat + //------------------------------------------------------------------------------------------------------ + + trel_branch_t tmp10, tmp11, tmp1; + trel_branch_t tmp00, tmp01, tmp0; + + logic [1 : 0] dat, tdat; + + always_ff @(posedge iclk) begin + if (iclkena) begin + if (ival) begin + dat <= idat; + if (pMMAX_TYPE == 1) begin + // b1 - LLR(11), LLR(10) vs LLR(01), LLR(00) + tmp10 <= bm_mmax1(outd[3], outd[2]); + tmp11 <= bm_mmax1(outd[1], 0); + // b0 - LLR(11), LLR(01) vs LLR(10), LLR(00) + tmp00 <= bm_mmax1(outd[3], outd[1]); + tmp01 <= bm_mmax1(outd[2], 0); + end + else begin + // b1 - LLR(11), LLR(10) vs LLR(01), LLR(00) + tmp10 <= bm_mmax(outd[3], outd[2]); + tmp11 <= bm_mmax(outd[1], 0); + // b0 - LLR(11), LLR(01) vs LLR(10), LLR(00) + tmp00 <= bm_mmax(outd[3], outd[1]); + tmp01 <= bm_mmax(outd[2], 0); + end + end + if (val[0]) begin + tdat <= dat; + tmp1 <= tmp10 - tmp11; + tmp0 <= tmp00 - tmp01; + end + end + end + + assign odat = ~{tmp1[$high(tmp1)], tmp0[$high(tmp0)]}; + assign oerr = odat ^ tdat; + assign oval = val[1]; + +endmodule diff --git a/rtl/rsc2/dec/rsc2_dec_bmc.sv b/rtl/rsc2/dec/rsc2_dec_bmc.sv new file mode 100644 index 0000000..3baf3f5 --- /dev/null +++ b/rtl/rsc2/dec/rsc2_dec_bmc.sv @@ -0,0 +1,252 @@ +/* + + + + parameter int pLLR_W = 5 ; + parameter int pLLR_FP = 3 ; + + + + logic rsc2_dec_bmc__iclk ; + logic rsc2_dec_bmc__ireset ; + logic rsc2_dec_bmc__iclkena ; + logic rsc2_dec_bmc__ival ; + logic rsc2_dec_bmc__ieven ; + logic rsc2_dec_bmc__ibitswap ; + logic rsc2_dec_bmc__iLextr_clr ; + bit_llr_t rsc2_dec_bmc__isLLR [0 : 1] ; + bit_llr_t rsc2_dec_bmc__iyLLR [0 : 1] ; + bit_llr_t rsc2_dec_bmc__iwLLR [0 : 1] ; + Lextr_t rsc2_dec_bmc__iLextr ; + logic rsc2_dec_bmc__oval ; + gamma_t rsc2_dec_bmc__ogamma ; + Lapri_t rsc2_dec_bmc__oLapri ; + logic [1 : 0] rsc2_dec_bmc__ohd ; + + + + rsc2_dec_bmc + #( + .pLLR_W ( pLLR_W ) , + .pLLR_FP ( pLLR_FP ) + ) + rsc2_dec_bmc + ( + .iclk ( rsc2_dec_bmc__iclk ) , + .ireset ( rsc2_dec_bmc__ireset ) , + .iclkena ( rsc2_dec_bmc__iclkena ) , + .ival ( rsc2_dec_bmc__ival ) , + .ieven ( rsc2_dec_bmc__ieven ) , + .ibitswap ( rsc2_dec_bmc__ibitswap ) , + .iLextr_clr ( rsc2_dec_bmc__iLextr_clr ) , + .isLLR ( rsc2_dec_bmc__isLLR ) , + .iyLLR ( rsc2_dec_bmc__iyLLR ) , + .iwLLR ( rsc2_dec_bmc__iwLLR ) , + .iLextr ( rsc2_dec_bmc__iLextr ) , + .oval ( rsc2_dec_bmc__oval ) , + .ogamma ( rsc2_dec_bmc__ogamma ) , + .oLapri ( rsc2_dec_bmc__oLapri ) , + .ohd ( rsc2_dec_bmc__ohd ) + ); + + + assign rsc2_dec_bmc__iclk = '0 ; + assign rsc2_dec_bmc__ireset = '0 ; + assign rsc2_dec_bmc__iclkena = '0 ; + assign rsc2_dec_bmc__ival = '0 ; + assign rsc2_dec_bmc__ieven = '0 ; + assign rsc2_dec_bmc__ibitswap = '0 ; + assign rsc2_dec_bmc__iLextr_clr = '0 ; + assign rsc2_dec_bmc__isLLR = '0 ; + assign rsc2_dec_bmc__iyLLR = '0 ; + assign rsc2_dec_bmc__iwLLR = '0 ; + assign rsc2_dec_bmc__iLextr = '0 ; + assgin rsc2_dec_bmc__ila_norm = '0 ; + + + +*/ + +// +// Project : rsc2 +// Author : Shekhalev Denis (des00) +// Workfile : rsc2_dec_bmc.sv +// Description : data/parity duobit LLR & branch metric LLR calculator with look ahead normalization +// + +module rsc2_dec_bmc +#( + parameter int pLLR_W = 5 , + parameter int pLLR_FP = 3 +) +( + iclk , + ireset , + iclkena , + // + ival , + ieven , + ibitswap , + iLextr_clr , + isLLR , + iyLLR , + iwLLR , + iLextr , + // + oval , + ogamma , + oLapri , + ohd +); + + `include "rsc2_dec_types.svh" + `include "rsc2_trellis.svh" + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + input logic iclk ; + input logic ireset ; + input logic iclkena ; + // + input logic ival ; + input logic ieven ; // 1/0 - no permutate(even)/permutate (odd) + input logic ibitswap ; // swap systematic duobit pair for permutation + input logic iLextr_clr ; // clear extrinsic info (first half iteration) + // + input bit_llr_t isLLR [0 : 1] ; // systematic bit LLR + input bit_llr_t iyLLR [0 : 1] ; // parity y-bit LLR + input bit_llr_t iwLLR [0 : 1] ; // parity w-bit LLR + input Lextr_t iLextr ; // apriory extrinsic info + // + output logic oval ; + output gamma_t ogamma ; // transition metric + output Lapri_t oLapri ; // data apriory duobit LLR + output logic [1 : 0] ohd ; // systematic hard decision + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + logic [2 : 0] val; + + dbit_allr_t dLLR; + dbit_allr_t pLLR; + + Lextr_t Lextr; + + Lapri_t Lapri; + + logic [1 : 0] hd; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + always_ff @(posedge iclk or posedge ireset) begin + if (ireset) begin + val <= '0; + end + else if (iclkena) begin + val <= (val << 1) | ival; + end + end + + //------------------------------------------------------------------------------------------------------ + // get systematic duobits and prepare parity & Lext + //------------------------------------------------------------------------------------------------------ + + wire bitswap = !ieven & ibitswap; + + always_ff @(posedge iclk) begin + if (iclkena) begin + if (ival) begin + // systematic bits & extrinsic + if (iLextr_clr) begin + Lextr[1] <= '0; + Lextr[2] <= '0; + Lextr[3] <= '0; + end + else begin + Lextr[1] <= bitswap ? iLextr[2] : iLextr[1]; + Lextr[2] <= bitswap ? iLextr[1] : iLextr[2]; + Lextr[3] <= iLextr[3]; + end + + dLLR[1] <= bitswap ? get_duobit_LLR(isLLR[1], isLLR[0], 2) : get_duobit_LLR(isLLR[1], isLLR[0], 1); + dLLR[2] <= bitswap ? get_duobit_LLR(isLLR[1], isLLR[0], 1) : get_duobit_LLR(isLLR[1], isLLR[0], 2); + dLLR[3] <= get_duobit_LLR(isLLR[1], isLLR[0], 3); + // hard decicion + hd <= ~{isLLR[1][pLLR_W-1], isLLR[0][pLLR_W-1]}; + + // parity bits + pLLR [1] <= ieven ? get_duobit_LLR(iyLLR[1], iwLLR[1], 1) : get_duobit_LLR(iyLLR[0], iwLLR[0], 1); + pLLR [2] <= ieven ? get_duobit_LLR(iyLLR[1], iwLLR[1], 2) : get_duobit_LLR(iyLLR[0], iwLLR[0], 2); + pLLR [3] <= ieven ? get_duobit_LLR(iyLLR[1], iwLLR[1], 3) : get_duobit_LLR(iyLLR[0], iwLLR[0], 3); + end + end + end + + //------------------------------------------------------------------------------------------------------ + // get transition metric + //------------------------------------------------------------------------------------------------------ + + always_comb begin + for (int i = 1; i < 4; i++) begin + Lapri [i] = dLLR[i] + Lextr[i]; + end + end + + always_ff @(posedge iclk) begin + if (iclkena) begin + if (val[0]) begin + ogamma <= get_gamma(Lapri, pLLR); + oLapri <= Lapri; + ohd <= hd; + end + end + end + + assign oval = val[1]; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + // function to get duobit LLR. + // b1/b0 - LLR of bits + // t - 2'b01/2'b10/2'b11 duobit type + function automatic dbit_llr_t get_duobit_LLR (input bit_llr_t b1, b0, input int t); + case (t) + 2'b01 : return b0; + 2'b10 : return b1; + 2'b11 : return b1 + b0; + default : return 0; + endcase + endfunction + + // + // function to get branch metric + function automatic gamma_t get_gamma (input Lapri_t ind, input dbit_allr_t inp); + int outb; + begin + for (int state = 0; state < 16; state++) begin + for (int inb = 0; inb < 4; inb++) begin + outb = trel.outputs[state][inb]; + // systematic + parity bits + if (inb == 0) begin + get_gamma[state][inb] = ((outb == 0) ? 0 : inp[outb]); + end + else if (outb == 0) begin + get_gamma[state][inb] = ind[inb]; + end + else begin + get_gamma[state][inb] = ind[inb] + inp[outb]; + end + end + end + end + endfunction + +endmodule diff --git a/rtl/rsc2/dec/rsc2_dec_engine.sv b/rtl/rsc2/dec/rsc2_dec_engine.sv new file mode 100644 index 0000000..0099f3e --- /dev/null +++ b/rtl/rsc2/dec/rsc2_dec_engine.sv @@ -0,0 +1,697 @@ +/* + + + + parameter int pLLR_W = 5 ; + parameter int pLLR_FP = 2 ; + parameter int pDTAG_W = 2 ; + parameter int pADDR_W = 8 ; + parameter int pTAG_W = 1 ; + // + parameter int pMMAX_TYPE = 0 ; + parameter int pUSE_IBUF_PIPE = 1 ; + parameter int pUSE_RP_P_COMP = 1 ; + + + + logic rsc2_dec_engine__iclk ; + logic rsc2_dec_engine__ireset ; + logic rsc2_dec_engine__iclkena ; + // + logic rsc2_dec_engine__irbuf_full ; + code_ctx_t rsc2_dec_engine__icode_ctx ; + logic [3 : 0] rsc2_dec_engine__iNiter ; + logic [pTAG_W-1 : 0] rsc2_dec_engine__irtag ; + logic rsc2_dec_engine__orempty ; + // + bit_llr_t rsc2_dec_engine__irfsLLR [2] ; + bit_llr_t rsc2_dec_engine__irfyLLR [2] ; + bit_llr_t rsc2_dec_engine__irfwLLR [2] ; + logic [pDTAG_W-1 : 0] rsc2_dec_engine__irfsLLRtag ; + logic [pADDR_W-1 : 0] rsc2_dec_engine__ofsaddr ; + logic [pADDR_W-1 : 0] rsc2_dec_engine__ofpaddr ; + // + bit_llr_t rsc2_dec_engine__irbsLLR [2] ; + bit_llr_t rsc2_dec_engine__irbyLLR [2] ; + bit_llr_t rsc2_dec_engine__irbwLLR [2] ; + logic [pDTAG_W-1 : 0] rsc2_dec_engine__irbsLLRtag ; + logic [pADDR_W-1 : 0] rsc2_dec_engine__obsaddr ; + logic [pADDR_W-1 : 0] rsc2_dec_engine__obpaddr ; + // + logic rsc2_dec_engine__iwbuf_empty ; + // + logic rsc2_dec_engine__owrite ; + logic rsc2_dec_engine__owfull ; + dbits_num_t rsc2_dec_engine__ownum ; + logic [pTAG_W-1 : 0] rsc2_dec_engine__owtag ; + logic [15 : 0] rsc2_dec_engine__owerr ; + // + logic [pADDR_W-1 : 0] rsc2_dec_engine__owfaddr ; + logic [1 : 0] rsc2_dec_engine__owfdat ; + logic [1 : 0] rsc2_dec_engine__owfderr ; + logic [pDTAG_W-1 : 0] rsc2_dec_engine__owfdtag ; + // + logic [pADDR_W-1 : 0] rsc2_dec_engine__owbaddr ; + logic [1 : 0] rsc2_dec_engine__owbdat ; + logic [1 : 0] rsc2_dec_engine__owbderr ; + logic [pDTAG_W-1 : 0] rsc2_dec_engine__owbdtag ; + + + + rsc2_dec_engine + #( + .pLLR_W ( pLLR_W ) , + .pLLR_FP ( pLLR_FP ) , + .pDTAG_W ( pDTAG_W ) , + .pADDR_W ( pADDR_W ) , + .pTAG_W ( pTAG_W ) , + // + .pMMAX_TYPE ( pMMAX_TYPE ) , + .pUSE_IBUF_PIPE ( pUSE_IBUF_PIPE ) , + .pUSE_RP_P_COMP ( pUSE_RP_P_COMP ) + ) + rsc2_dec_engine + ( + .iclk ( rsc2_dec_engine__iclk ) , + .ireset ( rsc2_dec_engine__ireset ) , + .iclkena ( rsc2_dec_engine__iclkena ) , + // + .irbuf_full ( rsc2_dec_engine__irbuf_full ) , + .icode_ctx ( rsc2_dec_engine__icode_ctx ) , + .iNiter ( rsc2_dec_engine__iNiter ) , + .irtag ( rsc2_dec_engine__irtag ) , + .orempty ( rsc2_dec_engine__orempty ) , + // + .irfsLLR ( rsc2_dec_engine__irfsLLR ) , + .irfyLLR ( rsc2_dec_engine__irfyLLR ) , + .irfwLLR ( rsc2_dec_engine__irfwLLR ) , + .irfsLLRtag ( rsc2_dec_engine__irfsLLRtag ) , + .ofsaddr ( rsc2_dec_engine__ofsaddr ) , + .ofpaddr ( rsc2_dec_engine__ofpaddr ) , + // + .irbsLLR ( rsc2_dec_engine__irbsLLR ) , + .irbyLLR ( rsc2_dec_engine__irbyLLR ) , + .irbwLLR ( rsc2_dec_engine__irbwLLR ) , + .irbsLLRtag ( rsc2_dec_engine__irbsLLRtag ) , + .obsaddr ( rsc2_dec_engine__obsaddr ) , + .obpaddr ( rsc2_dec_engine__obpaddr ) , + // + .iwbuf_empty ( rsc2_dec_engine__iwbuf_empty ) , + // + .owrite ( rsc2_dec_engine__owrite ) , + .owfull ( rsc2_dec_engine__owfull ) , + .ownum ( rsc2_dec_engine__ownum ) , + .owtag ( rsc2_dec_engine__owtag ) , + .owerr ( rsc2_dec_engine__owerr ) , + // + .owfaddr ( rsc2_dec_engine__owfaddr ) , + .owfdat ( rsc2_dec_engine__owfdat ) , + .owfderr ( rsc2_dec_engine__owfderr ) , + .owfdtag ( rsc2_dec_engine__owfdtag ) , + // + .owbaddr ( rsc2_dec_engine__owbaddr ) , + .owbdat ( rsc2_dec_engine__owbdat ) , + .owbderr ( rsc2_dec_engine__owbderr ) , + .owbdtag ( rsc2_dec_engine__owbdtag ) + ); + + + assign rsc2_dec_engine__iclk = '0 ; + assign rsc2_dec_engine__ireset = '0 ; + assign rsc2_dec_engine__iclkena = '0 ; + assign rsc2_dec_engine__irbuf_full = '0 ; + assign rsc2_dec_engine__icode_ctx = '0 ; + assign rsc2_dec_engine__iNiter = '0 ; + assign rsc2_dec_engine__irtag = '0 ; + assign rsc2_dec_engine__irfsLLR = '0 ; + assign rsc2_dec_engine__irfyLLR = '0 ; + assign rsc2_dec_engine__irfwLLR = '0 ; + assign rsc2_dec_engine__irfsLLRtag = '0 ; + assign rsc2_dec_engine__irbsLLR = '0 ; + assign rsc2_dec_engine__irbyLLR = '0 ; + assign rsc2_dec_engine__irbwLLR = '0 ; + assign rsc2_dec_engine__irbsLLRtag = '0 ; + assign rsc2_dec_engine__iwbuf_empty = '0 ; + + + +*/ + +// +// Project : rsc +// Author : Shekhalev Denis (des00) +// Workfile : rsc2_dec_engine.sv +// Description : RSC decoder engine top level +// + +module rsc2_dec_engine +#( + parameter int pLLR_W = 5 , + parameter int pLLR_FP = 2 , + parameter int pDTAG_W = 2 , // duo-bit tag for multichannel + parameter int pADDR_W = 8 , + parameter int pTAG_W = 1 , + // + parameter int pMMAX_TYPE = 0 , + parameter bit pUSE_IBUF_PIPE = 1 , + parameter int pUSE_RP_P_COMP = 1 +) +( + iclk , + ireset , + iclkena , + // + irbuf_full , + icode_ctx , + iNiter , + irtag , + orempty , + // + irfsLLR , + irfyLLR , + irfwLLR , + irfsLLRtag , + ofsaddr , + ofpaddr , + // + irbsLLR , + irbyLLR , + irbwLLR , + irbsLLRtag , + obsaddr , + obpaddr , + // + iwbuf_empty , + // + owrite , + owfull , + ownum , + owtag , + owerr , + // + owfaddr , + owfdat , + owfderr , + owfdtag , + // + owbaddr , + owbdat , + owbderr , + owbdtag +); + + `include "../rsc2_constants.svh" + `include "rsc2_dec_types.svh" + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + input logic iclk ; + input logic ireset ; + input logic iclkena ; + // + input logic irbuf_full ; + input code_ctx_t icode_ctx ; + input logic [3 : 0] iNiter ; + input logic [pTAG_W-1 : 0] irtag ; // block tag + output logic orempty ; + // + input bit_llr_t irfsLLR [2] ; + input bit_llr_t irfyLLR [2] ; + input bit_llr_t irfwLLR [2] ; + input logic [pDTAG_W-1 : 0] irfsLLRtag ; // forward duo-bit tag + output logic [pADDR_W-1 : 0] ofsaddr ; + output logic [pADDR_W-1 : 0] ofpaddr ; + // + input bit_llr_t irbsLLR [2] ; + input bit_llr_t irbyLLR [2] ; + input bit_llr_t irbwLLR [2] ; + input logic [pDTAG_W-1 : 0] irbsLLRtag ; // backward duo-bit tag + output logic [pADDR_W-1 : 0] obsaddr ; + output logic [pADDR_W-1 : 0] obpaddr ; + // + input logic iwbuf_empty ; + // + output logic owrite ; + output logic owfull ; + output dbits_num_t ownum ; + output logic [pTAG_W-1 : 0] owtag ; + output logic [15 : 0] owerr ; + // + output logic [pADDR_W-1 : 0] owfaddr ; + output logic [1 : 0] owfdat ; + output logic [1 : 0] owfderr ; + output logic [pDTAG_W-1 : 0] owfdtag ; + // + output logic [pADDR_W-1 : 0] owbaddr ; + output logic [1 : 0] owbdat ; + output logic [1 : 0] owbderr ; + output logic [pDTAG_W-1 : 0] owbdtag ; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + localparam int cEXTR_RAM_ADDR_W = pADDR_W; + localparam int cEXTR_RAM_DATA_W = cL_EXT_W*3; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + // + // parameter table + ptype_t ptab__iptype ; + dbits_num_t ptab__iN ; + + dbits_num_t used_N ; + dbits_num_t used_Nm1 ; + dbits_num_t used_P [4] ; + dbits_num_t used_P0comp ; + dbits_num_t used_Pincr ; + + // + // ctrl + logic ctrl__oaddr_pmode ; + logic ctrl__oaddr_clear ; + logic ctrl__oaddr_enable ; + + logic ctrl__ofirst_sub_stage ; + logic ctrl__olast_sub_stage ; + logic ctrl__oeven_sub_stage ; + logic ctrl__osub_stage_warm ; + + logic ctrl__idec_eop ; + logic ctrl__odec_sop ; + logic ctrl__odec_val ; + logic ctrl__odec_eop ; + + // address generator + logic addr_gen__obitinv ; + dbits_num_t faddr_gen__osaddr ; + dbits_num_t faddr_gen__opaddr ; + dbits_num_t baddr_gen__osaddr ; + dbits_num_t baddr_gen__opaddr ; + + // + // MAP engine + logic map__ifirst ; + logic map__ilast ; + logic map__ieven ; + logic map__ibitswap ; + logic map__iwarm ; + + logic map__isop ; + logic map__ival ; + logic map__ieop ; + + logic [pADDR_W-1 : 0] map__ifaddr ; + bit_llr_t map__ifsLLR [2] ; + bit_llr_t map__ifyLLR [2] ; + bit_llr_t map__ifwLLR [2] ; + Lextr_t map__ifLextr ; + logic [pDTAG_W-1 : 0] map__ifsLLRtag ; + + logic [pADDR_W-1 : 0] map__ibaddr ; + bit_llr_t map__ibsLLR [2] ; + bit_llr_t map__ibyLLR [2] ; + bit_llr_t map__ibwLLR [2] ; + Lextr_t map__ibLextr ; + logic [pDTAG_W-1 : 0] map__ibsLLRtag ; + + state_t map__if_rp_state_even ; + state_t map__if_rp_state_odd ; + state_t map__ib_rp_state_even ; + state_t map__ib_rp_state_odd ; + + state_t map__of_rp_state_even ; + state_t map__of_rp_state_odd ; + state_t map__ob_rp_state_even ; + state_t map__ob_rp_state_odd ; + + logic map__osop ; + logic map__oeop ; + logic map__oval ; + logic map__odatval ; + + logic [pADDR_W-1 : 0] map__ofaddr ; + Lextr_t map__ofLextr ; + logic [1 : 0] map__ofdat ; + logic [1 : 0] map__ofderr ; + logic [pDTAG_W-1 : 0] map__ofdtag ; + + logic [pADDR_W-1 : 0] map__obaddr ; + Lextr_t map__obLextr ; + logic [1 : 0] map__obdat ; + logic [1 : 0] map__obderr ; + logic [pDTAG_W-1 : 0] map__obdtag ; + + logic map__odone ; + logic [15 : 0] map__oerr ; + + // + // extrinsic ram + logic extr_ram__iwrite ; + logic [cEXTR_RAM_ADDR_W-1 : 0] extr_ram__iwaddr0 ; + logic [cEXTR_RAM_DATA_W-1 : 0] extr_ram__iwdata0 ; + logic [cEXTR_RAM_ADDR_W-1 : 0] extr_ram__iwaddr1 ; + logic [cEXTR_RAM_DATA_W-1 : 0] extr_ram__iwdata1 ; + + logic extr_ram__iread ; + logic [cEXTR_RAM_ADDR_W-1 : 0] extr_ram__iraddr0 ; + logic [cEXTR_RAM_DATA_W-1 : 0] extr_ram__ordata0 ; + logic [cEXTR_RAM_ADDR_W-1 : 0] extr_ram__iraddr1 ; + logic [cEXTR_RAM_DATA_W-1 : 0] extr_ram__ordata1 ; + + //------------------------------------------------------------------------------------------------------ + // permutation type table + //------------------------------------------------------------------------------------------------------ + + rsc2_ptable + ptab + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .iptype ( ptab__iptype ) , + // + .oN ( used_N ) , + .oNm1 ( used_Nm1 ) , + .oNmod15 ( ) , // n.u. + // + .oP ( used_P ) , + .oP0comp ( used_P0comp ) , + .oPincr ( used_Pincr ) + ); + + assign ptab__iptype = icode_ctx.ptype; + + //------------------------------------------------------------------------------------------------------ + // decoder FSM + //------------------------------------------------------------------------------------------------------ + + rsc_dec_ctrl + ctrl + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .iN ( used_N ) , + .iNiter ( iNiter ) , + // + .ibuf_full ( irbuf_full ) , // if ibuffer full start + .obuf_rempty ( orempty ) , + .iobuf_empty ( iwbuf_empty ) , // if obuffer is empty end + // + .oaddr_pmode ( ctrl__oaddr_pmode ) , + .oaddr_clear ( ctrl__oaddr_clear ) , + .oaddr_enable ( ctrl__oaddr_enable ) , + // + .ofirst_sub_stage ( ctrl__ofirst_sub_stage ) , + .olast_sub_stage ( ctrl__olast_sub_stage ) , + .oeven_sub_stage ( ctrl__oeven_sub_stage ) , + .osub_stage_warm ( ctrl__osub_stage_warm ) , + // + .idec_eop ( ctrl__idec_eop ) , + .odec_sop ( ctrl__odec_sop ) , + .odec_val ( ctrl__odec_val ) , + .odec_eop ( ctrl__odec_eop ) + ); + + assign ctrl__idec_eop = map__oeop; + + //------------------------------------------------------------------------------------------------------ + // address generators + //------------------------------------------------------------------------------------------------------ + + rsc_dec_addr_gen + #( + .pB_nF ( 0 ) + ) + faddr_gen + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .ipmode ( ctrl__oaddr_pmode ) , + .iclear ( ctrl__oaddr_clear ) , + .ienable ( ctrl__oaddr_enable ) , + // + .iN ( used_N ) , + .iNm1 ( used_Nm1 ) , + .iP ( used_P ) , + .iP0comp ( used_P0comp ) , + .iPincr ( used_Pincr ) , + .iPdvbinv ( 1'b1 ) , + // + .osaddr ( faddr_gen__osaddr ) , + .opaddr ( faddr_gen__opaddr ) , + .obitinv ( addr_gen__obitinv ) + ); + + assign ofsaddr = faddr_gen__osaddr[pADDR_W-1 : 0]; + assign ofpaddr = faddr_gen__opaddr[pADDR_W-1 : 0]; + + rsc_dec_addr_gen + #( + .pB_nF ( 1 ) + ) + baddr_gen + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .ipmode ( ctrl__oaddr_pmode ) , + .iclear ( ctrl__oaddr_clear ) , + .ienable ( ctrl__oaddr_enable ) , + // + .iN ( used_N ) , + .iNm1 ( used_Nm1 ) , + .iP ( used_P ) , + .iP0comp ( used_P0comp ) , + .iPincr ( used_Pincr ) , + .iPdvbinv ( 1'b1 ) , + // + .osaddr ( baddr_gen__osaddr ) , + .opaddr ( baddr_gen__opaddr ) , + .obitinv ( ) // n.u. + ); + + assign obsaddr = baddr_gen__osaddr[pADDR_W-1 : 0]; + assign obpaddr = baddr_gen__opaddr[pADDR_W-1 : 0]; + + //------------------------------------------------------------------------------------------------------ + // MAP engine + //------------------------------------------------------------------------------------------------------ + + logic map_bitswap ; + logic map_warm ; + logic map_sop ; + logic map_val ; + logic map_eop ; + + logic [pADDR_W-1 : 0] map_faddr ; + logic [pADDR_W-1 : 0] map_baddr ; + + rsc2_dec_map_engine + #( + .pLLR_W ( pLLR_W ) , + .pLLR_FP ( pLLR_FP ) , + .pDTAG_W ( pDTAG_W ) , + // + .pADDR_W ( pADDR_W ) , + .pMM_ADDR_W ( pADDR_W-1 ) , // 1/2 of pN + // + .pMMAX_TYPE ( pMMAX_TYPE ) , + // + .pUSE_RP_P_COMP ( pUSE_RP_P_COMP ) + ) + map + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .ifirst ( map__ifirst ) , + .ilast ( map__ilast ) , + .ieven ( map__ieven ) , + .ibitswap ( map__ibitswap ) , + .iwarm ( map__iwarm ) , + // + .isop ( map__isop ) , + .ival ( map__ival ) , + .ieop ( map__ieop ) , + // + .ifaddr ( map__ifaddr ) , + .ifsLLR ( map__ifsLLR ) , + .ifyLLR ( map__ifyLLR ) , + .ifwLLR ( map__ifwLLR ) , + .ifLextr ( map__ifLextr ) , + .ifsLLRtag ( map__ifsLLRtag ) , + // + .ibaddr ( map__ibaddr ) , + .ibsLLR ( map__ibsLLR ) , + .ibyLLR ( map__ibyLLR ) , + .ibwLLR ( map__ibwLLR ) , + .ibLextr ( map__ibLextr ) , + .ibsLLRtag ( map__ibsLLRtag ) , + // + .if_rp_state_even ( map__if_rp_state_even ) , + .if_rp_state_odd ( map__if_rp_state_odd ) , + .ib_rp_state_even ( map__ib_rp_state_even ) , + .ib_rp_state_odd ( map__ib_rp_state_odd ) , + // + .of_rp_state_even ( map__of_rp_state_even ) , + .of_rp_state_odd ( map__of_rp_state_odd ) , + .ob_rp_state_even ( map__ob_rp_state_even ) , + .ob_rp_state_odd ( map__ob_rp_state_odd ) , + // + .osop ( map__osop ) , + .oeop ( map__oeop ) , + .oval ( map__oval ) , + .odatval ( map__odatval ) , + // + .ofaddr ( map__ofaddr ) , + .ofLextr ( map__ofLextr ) , + .ofdat ( map__ofdat ) , + .ofderr ( map__ofderr ) , + .ofdtag ( map__ofdtag ) , + // + .obaddr ( map__obaddr ) , + .obLextr ( map__obLextr ) , + .obdat ( map__obdat ) , + .obderr ( map__obderr ) , + .obdtag ( map__obdtag ) , + // + .odone ( map__odone ) , + .oerr ( map__oerr ) + ); + + assign map__ifirst = ctrl__ofirst_sub_stage; + assign map__ilast = ctrl__olast_sub_stage; + assign map__ieven = ctrl__oeven_sub_stage; + + assign map__if_rp_state_even = map__of_rp_state_even; + assign map__if_rp_state_odd = map__of_rp_state_odd ; + + assign map__ib_rp_state_even = map__ob_rp_state_even; + assign map__ib_rp_state_odd = map__ob_rp_state_odd ; + + // + // align input buffer read delay + always_ff @(posedge iclk) begin + if (iclkena) begin + if (pUSE_IBUF_PIPE) begin + {map__ifaddr, map_faddr } <= {map_faddr, faddr_gen__osaddr[pADDR_W-1 : 0]}; + {map__ibaddr, map_baddr } <= {map_baddr, baddr_gen__osaddr[pADDR_W-1 : 0]}; + {map__ibitswap, map_bitswap} <= {map_bitswap, addr_gen__obitinv}; + // + {map__iwarm, map_warm} <= {map_warm, ctrl__osub_stage_warm}; + {map__isop, map_sop } <= {map_sop, ctrl__odec_sop}; + {map__ival, map_val } <= {map_val, ctrl__odec_val}; + {map__ieop, map_eop } <= {map_eop, ctrl__odec_eop}; + end + else begin + map__ifaddr <= faddr_gen__osaddr[pADDR_W-1 : 0]; + map__ibaddr <= baddr_gen__osaddr[pADDR_W-1 : 0]; + map__ibitswap <= addr_gen__obitinv; + // + map__iwarm <= ctrl__osub_stage_warm; + map__isop <= ctrl__odec_sop; + map__ival <= ctrl__odec_val; + map__ieop <= ctrl__odec_eop; + end + end + end + + assign map__ifsLLR = irfsLLR; + assign map__ifyLLR = irfyLLR; + assign map__ifwLLR = irfwLLR; + assign map__ifsLLRtag = irfsLLRtag; + + assign {map__ifLextr[3], map__ifLextr[2], map__ifLextr[1]} = extr_ram__ordata0; + + assign map__ibsLLR = irbsLLR; + assign map__ibyLLR = irbyLLR; + assign map__ibwLLR = irbwLLR; + assign map__ibsLLRtag = irbsLLRtag; + + assign {map__ibLextr[3], map__ibLextr[2], map__ibLextr[1]} = extr_ram__ordata1; + + //------------------------------------------------------------------------------------------------------ + // extrinsic buffer + //------------------------------------------------------------------------------------------------------ + + codec_map_dec_extr_ram + #( + .pADDR_W ( cEXTR_RAM_ADDR_W ) , + .pDATA_W ( cEXTR_RAM_DATA_W ) , + // + .pWPIPE ( pUSE_IBUF_PIPE ) , + .pRDPIPE ( pUSE_IBUF_PIPE ) + ) + extr_ram + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .iwrite ( extr_ram__iwrite ) , + // + .iwaddr0 ( extr_ram__iwaddr0 ) , + .iwdata0 ( extr_ram__iwdata0 ) , + // + .iwaddr1 ( extr_ram__iwaddr1 ) , + .iwdata1 ( extr_ram__iwdata1 ) , + // + .iread ( 1'b1 ) , + // + .iraddr0 ( extr_ram__iraddr0 ) , + .ordata0 ( extr_ram__ordata0 ) , + // + .iraddr1 ( extr_ram__iraddr1 ) , + .ordata1 ( extr_ram__ordata1 ) + ); + + // write side + assign extr_ram__iwrite = map__oval ; + + assign extr_ram__iwaddr0 = map__ofaddr; + assign extr_ram__iwdata0 = {map__ofLextr[3], map__ofLextr[2], map__ofLextr[1]}; + // + assign extr_ram__iwaddr1 = map__obaddr ; + assign extr_ram__iwdata1 = {map__obLextr[3], map__obLextr[2], map__obLextr[1]} ; + + // read side + assign extr_ram__iread = 1'b1 ; + // + assign extr_ram__iraddr0 = faddr_gen__osaddr[cEXTR_RAM_ADDR_W-1 : 0] ; + assign extr_ram__iraddr1 = baddr_gen__osaddr[cEXTR_RAM_ADDR_W-1 : 0] ; + + //------------------------------------------------------------------------------------------------------ + // output mapping + //------------------------------------------------------------------------------------------------------ + + assign owrite = map__odatval ; // write only at last half-iteration + assign owfull = map__odone ; + assign owerr = map__oerr ; + // + assign ownum = used_N ; + assign owtag = irtag ; + // + assign owfaddr = map__ofaddr ; + assign owfdat = map__ofdat ; + assign owfderr = map__ofderr ; + assign owfdtag = map__ofdtag ; + // + assign owbaddr = map__obaddr ; + assign owbdat = map__obdat ; + assign owbderr = map__obderr ; + assign owbdtag = map__obdtag ; + +endmodule diff --git a/rtl/rsc2/dec/rsc2_dec_map_engine.sv b/rtl/rsc2/dec/rsc2_dec_map_engine.sv new file mode 100644 index 0000000..a6985de --- /dev/null +++ b/rtl/rsc2/dec/rsc2_dec_map_engine.sv @@ -0,0 +1,942 @@ +/* + + + + parameter int pLLR_W = 5 ; + parameter int pLLR_FP = 3 ; + parameter int pDTAG_W = 8 ; + parameter int pADDR_W = 8 ; + parameter int pMM_ADDR_W = pADDR_W-1; + parameter int pMMAX_TYPE = 0 ; + parameter bit pUSE_RP_P_COMP = 1 ; + + + + logic rsc2_dec_map_engine__iclk ; + logic rsc2_dec_map_engine__ireset ; + logic rsc2_dec_map_engine__iclkena ; + logic rsc2_dec_map_engine__ifirst ; + logic rsc2_dec_map_engine__ilast ; + logic rsc2_dec_map_engine__ieven ; + logic rsc2_dec_map_engine__ibitswap ; + logic rsc2_dec_map_engine__iwarm ; + logic rsc2_dec_map_engine__isop ; + logic rsc2_dec_map_engine__ival ; + logic rsc2_dec_map_engine__ieop ; + logic [pADDR_W-1 : 0] rsc2_dec_map_engine__ifaddr ; + bit_llr_t rsc2_dec_map_engine__ifsLLR [0 : 1] ; + bit_llr_t rsc2_dec_map_engine__ifyLLR [0 : 1] ; + bit_llr_t rsc2_dec_map_engine__ifwLLR [0 : 1] ; + Lextr_t rsc2_dec_map_engine__ifLextr ; + logic [pDTAG_W-1 : 0] rsc2_dec_map_engine__ifsLLRtag ; + logic [pADDR_W-1 : 0] rsc2_dec_map_engine__ibaddr ; + bit_llr_t rsc2_dec_map_engine__ibsLLR [0 : 1] ; + bit_llr_t rsc2_dec_map_engine__ibyLLR [0 : 1] ; + bit_llr_t rsc2_dec_map_engine__ibwLLR [0 : 1] ; + Lextr_t rsc2_dec_map_engine__ibLextr ; + logic [pDTAG_W-1 : 0] rsc2_dec_map_engine__ibsLLRtag ; + state_t rsc2_dec_map_engine__if_rp_state_even ; + state_t rsc2_dec_map_engine__if_rp_state_odd ; + state_t rsc2_dec_map_engine__ib_rp_state_even ; + state_t rsc2_dec_map_engine__ib_rp_state_odd ; + state_t rsc2_dec_map_engine__of_rp_state_even ; + state_t rsc2_dec_map_engine__of_rp_state_odd ; + state_t rsc2_dec_map_engine__ob_rp_state_even ; + state_t rsc2_dec_map_engine__ob_rp_state_odd ; + logic rsc2_dec_map_engine__osop ; + logic rsc2_dec_map_engine__oeop ; + logic rsc2_dec_map_engine__oval ; + logic rsc2_dec_map_engine__odatval ; + logic [pADDR_W-1 : 0] rsc2_dec_map_engine__ofaddr ; + Lextr_t rsc2_dec_map_engine__ofLextr ; + logic [1 : 0] rsc2_dec_map_engine__ofdat ; + logic [1 : 0] rsc2_dec_map_engine__ofderr ; + logic [pDTAG_W-1 : 0] rsc2_dec_map_engine__ofdtag ; + logic [pADDR_W-1 : 0] rsc2_dec_map_engine__obaddr ; + Lextr_t rsc2_dec_map_engine__obLextr ; + logic [1 : 0] rsc2_dec_map_engine__obdat ; + logic [1 : 0] rsc2_dec_map_engine__obderr ; + logic [pDTAG_W-1 : 0] rsc2_dec_map_engine__obdtag ; + logic rsc2_dec_map_engine__odone ; + logic [15 : 0] rsc2_dec_map_engine__oerr ; + + + + rsc2_dec_map_engine + #( + .pLLR_W ( pLLR_W ) , + .pLLR_FP ( pLLR_FP ) , + .pDTAG_W ( pDTAG_W ) , + .pADDR_W ( pADDR_W ) , + .pMM_ADDR_W ( pMM_ADDR_W ) , + .pMMAX_TYPE ( pMMAX_TYPE ) , + .pUSE_RP_P_COMP ( pUSE_RP_P_COMP ) + ) + rsc2_dec_map_engine + ( + .iclk ( rsc2_dec_map_engine__iclk ) , + .ireset ( rsc2_dec_map_engine__ireset ) , + .iclkena ( rsc2_dec_map_engine__iclkena ) , + .ifirst ( rsc2_dec_map_engine__ifirst ) , + .ilast ( rsc2_dec_map_engine__ilast ) , + .ieven ( rsc2_dec_map_engine__ieven ) , + .ibitswap ( rsc2_dec_map_engine__ibitswap ) , + .iwarm ( rsc2_dec_map_engine__iwarm ) , + .isop ( rsc2_dec_map_engine__isop ) , + .ival ( rsc2_dec_map_engine__ival ) , + .ieop ( rsc2_dec_map_engine__ieop ) , + .ifaddr ( rsc2_dec_map_engine__ifaddr ) , + .ifsLLR ( rsc2_dec_map_engine__ifsLLR ) , + .ifyLLR ( rsc2_dec_map_engine__ifyLLR ) , + .ifwLLR ( rsc2_dec_map_engine__ifwLLR ) , + .ifLextr ( rsc2_dec_map_engine__ifLextr ) , + .ifsLLRtag ( rsc2_dec_map_engine__ifsLLRtag ) , + .ibaddr ( rsc2_dec_map_engine__ibaddr ) , + .ibsLLR ( rsc2_dec_map_engine__ibsLLR ) , + .ibyLLR ( rsc2_dec_map_engine__ibyLLR ) , + .ibwLLR ( rsc2_dec_map_engine__ibwLLR ) , + .ibLextr ( rsc2_dec_map_engine__ibLextr ) , + .ibsLLRtag ( rsc2_dec_map_engine__ibsLLRtag ) , + .if_rp_state_even ( rsc2_dec_map_engine__if_rp_state_even ) , + .if_rp_state_odd ( rsc2_dec_map_engine__if_rp_state_odd ) , + .ib_rp_state_even ( rsc2_dec_map_engine__ib_rp_state_even ) , + .ib_rp_state_odd ( rsc2_dec_map_engine__ib_rp_state_odd ) , + .of_rp_state_even ( rsc2_dec_map_engine__of_rp_state_even ) , + .of_rp_state_odd ( rsc2_dec_map_engine__of_rp_state_odd ) , + .ob_rp_state_even ( rsc2_dec_map_engine__ob_rp_state_even ) , + .ob_rp_state_odd ( rsc2_dec_map_engine__ob_rp_state_odd ) , + .osop ( rsc2_dec_map_engine__osop ) , + .oeop ( rsc2_dec_map_engine__oeop ) , + .oval ( rsc2_dec_map_engine__oval ) , + .odatval ( rsc2_dec_map_engine__odatval ) , + .ofaddr ( rsc2_dec_map_engine__ofaddr ) , + .ofLextr ( rsc2_dec_map_engine__ofLextr ) , + .ofdat ( rsc2_dec_map_engine__ofdat ) , + .ofderr ( rsc_dec_map_engine__ofderr ) , + .ofdtag ( rsc_dec_map_engine__ofdtag ) , + .obaddr ( rsc2_dec_map_engine__obaddr ) , + .obLextr ( rsc2_dec_map_engine__obLextr ) , + .obdat ( rsc2_dec_map_engine__obdat ) , + .obderr ( rsc2_dec_map_engine__obderr ) , + .obdtag ( rsc2_dec_map_engine__obdtag ) , + .odone ( rsc2_dec_map_engine__odone ) , + .oerr ( rsc2_dec_map_engine__oerr ) + ); + + + assign rsc2_dec_map_engine__iclk = '0 ; + assign rsc2_dec_map_engine__ireset = '0 ; + assign rsc2_dec_map_engine__iclkena = '0 ; + assign rsc2_dec_map_engine__ifirst = '0 ; + assign rsc2_dec_map_engine__ilast = '0 ; + assign rsc2_dec_map_engine__ieven = '0 ; + assign rsc2_dec_map_engine__ibitswap = '0 ; + assign rsc2_dec_map_engine__iwarm = '0 ; + assign rsc2_dec_map_engine__isop = '0 ; + assign rsc2_dec_map_engine__ival = '0 ; + assign rsc2_dec_map_engine__ieop = '0 ; + assign rsc2_dec_map_engine__ifaddr = '0 ; + assign rsc2_dec_map_engine__ifsLLR = '0 ; + assign rsc2_dec_map_engine__ifyLLR = '0 ; + assign rsc2_dec_map_engine__ifwLLR = '0 ; + assign rsc2_dec_map_engine__ifLextr = '0 ; + assign rsc2_dec_map_engine__ifsLLRtag = '0 ; + assign rsc2_dec_map_engine__ibaddr = '0 ; + assign rsc2_dec_map_engine__ibsLLR = '0 ; + assign rsc2_dec_map_engine__ibyLLR = '0 ; + assign rsc2_dec_map_engine__ibwLLR = '0 ; + assign rsc2_dec_map_engine__ibLextr = '0 ; + assign rsc2_dec_map_engine__ifsLLRtag = '0 ; + assign rsc2_dec_map_engine__if_rp_state_even = '0 ; + assign rsc2_dec_map_engine__if_rp_state_odd = '0 ; + assign rsc2_dec_map_engine__ib_rp_state_even = '0 ; + assign rsc2_dec_map_engine__ib_rp_state_odd = '0 ; + + + +*/ + +// +// Project : rsc2 +// Author : Shekhalev Denis (des00) +// Workfile : rsc2_dec_map_engine.sv +// Description : top module of sub iteration decoder (i.e. decoder engine). Module use concurrent forward and backward +// ways computing. This feature require special rams with two write and read ports. +// + +module rsc2_dec_map_engine +#( + parameter int pLLR_W = 5 , + parameter int pLLR_FP = 3 , + parameter int pDTAG_W = 8 , // duo-bit tag for multichannel modes + parameter int pADDR_W = 8 , + parameter int pMM_ADDR_W = pADDR_W-1 , // metric memory address width. use to create x1/x2/x4 decoders + parameter int pMMAX_TYPE = 0 , // 0 - max Log Map + // 1 - const 1 max Log Map + // 2 - const 2 max Log Map + // 3 - LUT max Log Map + parameter bit pUSE_RP_P_COMP = 1 // use parallel comparator for recursion processor +) +( + iclk , + ireset , + iclkena , + // + ifirst , + ilast , + ieven , + ibitswap , + iwarm , + // + isop , + ival , + ieop , + // + ifaddr , + ifsLLR , + ifyLLR , + ifwLLR , + ifLextr , + ifsLLRtag , + // + ibaddr , + ibsLLR , + ibyLLR , + ibwLLR , + ibLextr , + ibsLLRtag , + // + if_rp_state_even , + if_rp_state_odd , + ib_rp_state_even , + ib_rp_state_odd , + // + of_rp_state_even , + of_rp_state_odd , + ob_rp_state_even , + ob_rp_state_odd , + // + osop , + oeop , + oval , + odatval , + // + ofaddr , + ofLextr , + ofdat , + ofderr , + ofdtag , + // + obaddr , + obLextr , + obdat , + obderr , + obdtag , + // + odone , + oerr +); + + `include "rsc2_dec_types.svh" + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + input logic iclk ; + input logic ireset ; + input logic iclkena ; + // + input logic ifirst ; // first sub iteration + input logic ilast ; // last sub iteration + input logic ieven ; // 1/0 - no permutate(even)/permutate (odd) sub iteration + input logic ibitswap ; // swap bit pair + input logic iwarm ; // engine work mode warm/hot + // + input logic isop ; + input logic ival ; + input logic ieop ; + // + input logic [pADDR_W-1 : 0] ifaddr ; + input bit_llr_t ifsLLR [0 : 1] ; + input bit_llr_t ifyLLR [0 : 1] ; + input bit_llr_t ifwLLR [0 : 1] ; + input Lextr_t ifLextr ; + input logic [pDTAG_W-1 : 0] ifsLLRtag ; + // + input logic [pADDR_W-1 : 0] ibaddr ; + input bit_llr_t ibsLLR [0 : 1] ; + input bit_llr_t ibyLLR [0 : 1] ; + input bit_llr_t ibwLLR [0 : 1] ; + input Lextr_t ibLextr ; + input logic [pDTAG_W-1 : 0] ibsLLRtag ; + // + input state_t if_rp_state_even ; + input state_t if_rp_state_odd ; + input state_t ib_rp_state_even ; + input state_t ib_rp_state_odd ; + + output state_t of_rp_state_even ; + output state_t of_rp_state_odd ; + output state_t ob_rp_state_even ; + output state_t ob_rp_state_odd ; + // + output logic osop ; + output logic oeop ; + output logic oval ; + output logic odatval ; + // + output logic [pADDR_W-1 : 0] ofaddr ; + output Lextr_t ofLextr ; + output logic [1 : 0] ofdat ; + output logic [1 : 0] ofderr ; + output logic [pDTAG_W-1 : 0] ofdtag ; + // + output logic [pADDR_W-1 : 0] obaddr ; + output Lextr_t obLextr ; + output logic [1 : 0] obdat ; + output logic [1 : 0] obderr ; + output logic [pDTAG_W-1 : 0] obdtag ; + // + output logic odone ; // last iteration eop signal + output logic [15 : 0] oerr ; // estimated bit errors + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + localparam int cBMC_DELAY = 2; + localparam int cRP_DELAY = 1; + localparam int cLAPO_DELAY = 6; + localparam int cLEXTR_DELAY = 2; + + localparam int cDELAY = cBMC_DELAY + cRP_DELAY + cLAPO_DELAY + cLEXTR_DELAY; + + //------------------------------------------------------------------------------------------------------ + // common contol line + //------------------------------------------------------------------------------------------------------ + + logic [cDELAY-1 : 0] sop /*synthesis keep */; + logic [cDELAY-1 : 0] val /*synthesis keep */; + logic [cDELAY-1 : 0] eop /*synthesis keep */; + logic [cDELAY-1 : 0] warm /*synthesis keep */; + logic [cDELAY-1 : 0] bitswap /*synthesis keep */; + logic [cDELAY-1 : 0] last /*synthesis keep */; + + logic [pADDR_W-1 : 0] faddr [cDELAY] ; + logic [pADDR_W-1 : 0] baddr [cDELAY] ; + + logic [pDTAG_W-1 : 0] fdtag [cDELAY] ; + logic [pDTAG_W-1 : 0] bdtag [cDELAY] ; + + always_ff @(posedge iclk or posedge ireset) begin + if (ireset) begin + val <= '0; + end + else if (iclkena) begin + val <= (val << 1) | ival; + end + end + + always_ff @(posedge iclk) begin + if (iclkena) begin + sop <= (sop << 1) | isop; + eop <= (eop << 1) | ieop; + last <= (last << 1) | ilast; + warm <= (warm << 1) | iwarm; + bitswap <= (bitswap << 1) | ibitswap; + for (int i = 0; i < cDELAY; i++) begin + faddr[i] <= (i == 0) ? ifaddr : faddr[i-1]; + baddr[i] <= (i == 0) ? ibaddr : baddr[i-1]; + fdtag[i] <= (i == 0) ? ifsLLRtag : fdtag[i-1]; + bdtag[i] <= (i == 0) ? ibsLLRtag : bdtag[i-1]; + end + end + end + +//------------------------------------------------------------------------------------------------------ +// +// forward path BEGIN +// +//------------------------------------------------------------------------------------------------------ + + // branch metric calculator + logic f_bmc__oval ; + gamma_t f_bmc__ogamma ; + Lapri_t f_bmc__oLapri ; + logic [1 : 0] f_bmc__ohd ; + // + // recursion processor + logic f_rp__istate_clr ; + logic f_rp__istate_ld ; + state_t f_rp__istate ; + + logic f_rp__oval ; + gamma_t f_rp__ogamma ; + state_t f_rp__ostate2mm ; + state_t f_rp__ostate_last ; + // + // metric memory LIFO + logic f_mm__iwrite ; + logic [cSTATE_W*16-1 : 0] f_mm__iwdata ; + logic f_mm__iread ; + logic [cSTATE_W*16-1 : 0] f_mm__ordata ; + logic [cSTATE_W*16-1 : 0] b_mm__ordata ; + // + // aposteriory L + logic f_Lapo__ival ; + gamma_t f_Lapo__igamma ; + state_t f_Lapo__istate ; + logic f_Lapo__oval ; + Lapo_t f_Lapo__oLapo ; + // + // extrinsic L + logic f_Lextr__ival ; + logic f_Lextr__ibitswap ; + logic [1 : 0] f_Lextr__idat ; + Lapri_t f_Lextr__iLapri ; + Lapo_t f_Lextr__iLapo ; + + logic f_Lextr__oval ; + Lextr_t f_Lextr__oLextr ; + logic [1 : 0] f_Lextr__odat ; + logic [1 : 0] f_Lextr__oerr ; + + //------------------------------------------------------------------------------------------------------ + // BMC + //------------------------------------------------------------------------------------------------------ + + rsc2_dec_bmc + #( + .pLLR_W ( pLLR_W ) , + .pLLR_FP ( pLLR_FP ) + ) + f_bmc + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .ival ( ival ) , + .ieven ( ieven ) , + .ibitswap ( ibitswap ) , + .iLextr_clr ( ifirst ) , + // + .isLLR ( ifsLLR ) , + .iyLLR ( ifyLLR ) , + .iwLLR ( ifwLLR ) , + // + .iLextr ( ifLextr ) , + // + .oval ( f_bmc__oval ) , + .ogamma ( f_bmc__ogamma ) , + .oLapri ( f_bmc__oLapri ) , + .ohd ( f_bmc__ohd ) + ); + + //------------------------------------------------------------------------------------------------------ + // recursion processor + //------------------------------------------------------------------------------------------------------ + + rsc2_dec_rp_mod + #( + .pB_nF ( 0 ) , + .pLLR_W ( pLLR_W ) , + .pLLR_FP ( pLLR_FP ) , + .pMMAX_TYPE ( pMMAX_TYPE ) , + .pUSE_P_COMP ( pUSE_RP_P_COMP ) + ) + f_rp + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .istate_clr ( f_rp__istate_clr ) , + .istate_ld ( f_rp__istate_ld ) , + .istate ( f_rp__istate ) , + // + .ival ( f_bmc__oval ) , + .igamma ( f_bmc__ogamma ) , + // + .oval ( f_rp__oval ) , + .ostate ( ) , // n.u. + .ogamma ( f_rp__ogamma ) , + .ostate2mm ( f_rp__ostate2mm ) , + .ostate_last ( f_rp__ostate_last ) + ); + + assign f_rp__istate_clr = 1'b0; + + //------------------------------------------------------------------------------------------------------ + // circular trellis logic + //------------------------------------------------------------------------------------------------------ + + assign f_rp__istate_ld = sop[0]; // 1 tick delay for b_rp__istate mux + + wire f_rp_eop = eop[cBMC_DELAY + cRP_DELAY]; // 1 tick delay after true op to f_rp__ostate_last become valid + + always_ff @(posedge iclk) begin + if (iclkena) begin + if (isop & ifirst) begin + f_rp__istate <= '{default : '0}; + of_rp_state_even <= '{default : '0}; + of_rp_state_odd <= '{default : '0}; + end + else begin + f_rp__istate <= ieven ? if_rp_state_even : if_rp_state_odd; + // + if (f_rp_eop) begin + if (ieven) begin + of_rp_state_even <= f_rp__ostate_last; + end + else begin + of_rp_state_odd <= f_rp__ostate_last; + end + end + end + end + end + + //------------------------------------------------------------------------------------------------------ + // mm + //------------------------------------------------------------------------------------------------------ + + codec_map_dec_mm + #( + .pDATA_W ( cSTATE_W * 16 ) , + .pADDR_W ( pMM_ADDR_W ) // 1/N of pN + ) + f_mm + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .iwrite ( f_mm__iwrite ) , + .iwdata ( f_mm__iwdata ) , + .iread ( f_mm__iread ) , + .ordata ( f_mm__ordata ) + ); + + assign f_mm__iwrite = f_rp__oval & warm[cBMC_DELAY + cRP_DELAY-1]; + assign f_mm__iread = f_rp__oval & !warm[cBMC_DELAY + cRP_DELAY-1]; + + assign f_mm__iwdata = {f_rp__ostate2mm[0], f_rp__ostate2mm[1], f_rp__ostate2mm[2], f_rp__ostate2mm[3], + f_rp__ostate2mm[4], f_rp__ostate2mm[5], f_rp__ostate2mm[6], f_rp__ostate2mm[7], + f_rp__ostate2mm[8], f_rp__ostate2mm[9], f_rp__ostate2mm[10], f_rp__ostate2mm[11], + f_rp__ostate2mm[12], f_rp__ostate2mm[13], f_rp__ostate2mm[14], f_rp__ostate2mm[15]}; + + //------------------------------------------------------------------------------------------------------ + // Lapo + //------------------------------------------------------------------------------------------------------ + + rsc2_dec_Lapo + #( + .pB_nF ( 0 ) , + .pLLR_W ( pLLR_W ) , + .pLLR_FP ( pLLR_FP ) , + .pMMAX_TYPE ( pMMAX_TYPE ) + ) + f_Lapo + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .ival ( f_Lapo__ival ) , + .igamma ( f_Lapo__igamma ) , + .istate ( f_Lapo__istate ) , + // + .oval ( f_Lapo__oval ) , + .oLapo ( f_Lapo__oLapo ) + ); + + assign f_Lapo__ival = f_rp__oval & !warm[cBMC_DELAY + cRP_DELAY-1]; + assign f_Lapo__igamma = f_rp__ogamma; + + assign {f_Lapo__istate[0], f_Lapo__istate[1], f_Lapo__istate[2], f_Lapo__istate[3], + f_Lapo__istate[4], f_Lapo__istate[5], f_Lapo__istate[6], f_Lapo__istate[7], + f_Lapo__istate[8], f_Lapo__istate[9], f_Lapo__istate[10], f_Lapo__istate[11], + f_Lapo__istate[12], f_Lapo__istate[13], f_Lapo__istate[14], f_Lapo__istate[15]} = b_mm__ordata; + + //------------------------------------------------------------------------------------------------------ + // delay line for Lapri & hd + //------------------------------------------------------------------------------------------------------ + + Lapri_t f_Lapri [cRP_DELAY + cLAPO_DELAY] /*synthesis keep */; + logic [1 : 0] f_hd [cRP_DELAY + cLAPO_DELAY] /*synthesis keep */; + + always_ff @(posedge iclk) begin + if (iclkena) begin + for (int i = 0; i < cRP_DELAY + cLAPO_DELAY; i++) begin + f_Lapri[i] <= (i == 0) ? f_bmc__oLapri : f_Lapri[i-1]; + f_hd [i] <= (i == 0) ? f_bmc__ohd : f_hd [i-1]; + end + end + end + + //------------------------------------------------------------------------------------------------------ + // Lextr + //------------------------------------------------------------------------------------------------------ + + rsc2_dec_Lextr + #( + .pLLR_W ( pLLR_W ) , + .pLLR_FP ( pLLR_FP ) , + .pMMAX_TYPE ( pMMAX_TYPE ) + ) + f_Lextr + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .ival ( f_Lextr__ival ) , + .ibitswap ( f_Lextr__ibitswap ) , + .idat ( f_Lextr__idat ) , + .iLapri ( f_Lextr__iLapri ) , + .iLapo ( f_Lextr__iLapo ) , + // + .oval ( f_Lextr__oval ) , + .oLextr ( f_Lextr__oLextr ) , + .odat ( f_Lextr__odat ) , + .oerr ( f_Lextr__oerr ) + ); + + assign f_Lextr__ibitswap = !ieven & bitswap[cBMC_DELAY + cRP_DELAY + cLAPO_DELAY-1]; + + assign f_Lextr__ival = f_Lapo__oval; + assign f_Lextr__iLapo = f_Lapo__oLapo; + + assign f_Lextr__idat = f_hd [cRP_DELAY + cLAPO_DELAY-1]; + assign f_Lextr__iLapri = f_Lapri [cRP_DELAY + cLAPO_DELAY-1]; + +//------------------------------------------------------------------------------------------------------ +// +// forward path END +// +//------------------------------------------------------------------------------------------------------ + + + + + +//------------------------------------------------------------------------------------------------------ +// +// backward path BEGIN +// +//------------------------------------------------------------------------------------------------------ + + // branch metric calculator + logic b_bmc__oval ; + gamma_t b_bmc__ogamma ; + Lapri_t b_bmc__oLapri ; + logic [1 : 0] b_bmc__ohd ; + // + // recursion processor + logic b_rp__istate_clr ; + logic b_rp__istate_ld ; + state_t b_rp__istate ; + + logic b_rp__oval ; + gamma_t b_rp__ogamma ; + state_t b_rp__ostate2mm ; + state_t b_rp__ostate_last ; + // + // metric memory LIFO + logic b_mm__iwrite ; + logic [cSTATE_W*16-1 : 0] b_mm__iwdata ; + logic b_mm__iread ; + // + // aposteriory L + logic b_Lapo__ival ; + gamma_t b_Lapo__igamma ; + state_t b_Lapo__istate ; + logic b_Lapo__oval ; + Lapo_t b_Lapo__oLapo ; + // + // extrinsic L + logic b_Lextr__ival ; + logic b_Lextr__ibitswap ; + logic [1 : 0] b_Lextr__idat ; + Lapri_t b_Lextr__iLapri ; + Lapo_t b_Lextr__iLapo ; + + logic b_Lextr__oval ; + Lextr_t b_Lextr__oLextr ; + logic [1 : 0] b_Lextr__odat ; + logic [1 : 0] b_Lextr__oerr ; + + //------------------------------------------------------------------------------------------------------ + // BMC + //------------------------------------------------------------------------------------------------------ + + rsc2_dec_bmc + #( + .pLLR_W ( pLLR_W ) , + .pLLR_FP ( pLLR_FP ) + ) + b_bmc + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .ival ( ival ) , + .ieven ( ieven ) , + .ibitswap ( !ibitswap ) , // inverse to forward !!!! + .iLextr_clr ( ifirst ) , + // + .isLLR ( ibsLLR ) , + .iyLLR ( ibyLLR ) , + .iwLLR ( ibwLLR ) , + // + .iLextr ( ibLextr ) , + // + .oval ( b_bmc__oval ) , + .ogamma ( b_bmc__ogamma ) , + .oLapri ( b_bmc__oLapri ) , + .ohd ( b_bmc__ohd ) + ); + + //------------------------------------------------------------------------------------------------------ + // RP + //------------------------------------------------------------------------------------------------------ + + rsc2_dec_rp_mod + #( + .pB_nF ( 1 ) , + .pLLR_W ( pLLR_W ) , + .pLLR_FP ( pLLR_FP ) , + .pMMAX_TYPE ( pMMAX_TYPE ) , + .pUSE_P_COMP ( pUSE_RP_P_COMP ) + ) + b_rp + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .istate_clr ( b_rp__istate_clr ) , + .istate_ld ( b_rp__istate_ld ) , + .istate ( b_rp__istate ) , + // + .ival ( b_bmc__oval ) , + .igamma ( b_bmc__ogamma ) , + // + .oval ( b_rp__oval ) , + .ostate ( ) , // n.u. + .ogamma ( b_rp__ogamma ) , + .ostate2mm ( b_rp__ostate2mm ) , + .ostate_last ( b_rp__ostate_last ) + ); + + assign b_rp__istate_clr = 1'b0; + + //------------------------------------------------------------------------------------------------------ + // circular trellis logic + //------------------------------------------------------------------------------------------------------ + + assign b_rp__istate_ld = sop[0]; // 1 tick delay for b_rp__istate mux + + wire b_rp_eop = eop[cBMC_DELAY + cRP_DELAY]; // 1 tick delay after true op to f_rp__ostate_last become valid + + always_ff @(posedge iclk) begin + if (iclkena) begin + if (isop & ifirst) begin + b_rp__istate <= '{default : '0}; + ob_rp_state_even <= '{default : '0}; + ob_rp_state_odd <= '{default : '0}; + end + else begin + b_rp__istate <= ieven ? ib_rp_state_even : ib_rp_state_odd; + // + if (b_rp_eop) begin + if (ieven) begin + ob_rp_state_even <= b_rp__ostate_last; + end + else begin + ob_rp_state_odd <= b_rp__ostate_last; + end + end + end + end + end + + //------------------------------------------------------------------------------------------------------ + // mm + //------------------------------------------------------------------------------------------------------ + + codec_map_dec_mm + #( + .pDATA_W ( cSTATE_W * 16 ) , + .pADDR_W ( pMM_ADDR_W ) // 1/N of pN + ) + b_mm + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .iwrite ( b_mm__iwrite ) , + .iwdata ( b_mm__iwdata ) , + .iread ( b_mm__iread ) , + .ordata ( b_mm__ordata ) + ); + + assign b_mm__iwrite = b_rp__oval & warm[cBMC_DELAY + cRP_DELAY-1]; + assign b_mm__iread = b_rp__oval & !warm[cBMC_DELAY + cRP_DELAY-1]; + + assign b_mm__iwdata = {b_rp__ostate2mm[0], b_rp__ostate2mm[1], b_rp__ostate2mm[2], b_rp__ostate2mm[3], + b_rp__ostate2mm[4], b_rp__ostate2mm[5], b_rp__ostate2mm[6], b_rp__ostate2mm[7], + b_rp__ostate2mm[8], b_rp__ostate2mm[9], b_rp__ostate2mm[10], b_rp__ostate2mm[11], + b_rp__ostate2mm[12], b_rp__ostate2mm[13], b_rp__ostate2mm[14], b_rp__ostate2mm[15]}; + + //------------------------------------------------------------------------------------------------------ + // Lapo + //------------------------------------------------------------------------------------------------------ + + rsc2_dec_Lapo + #( + .pB_nF ( 1 ) , + .pLLR_W ( pLLR_W ) , + .pLLR_FP ( pLLR_FP ) , + .pMMAX_TYPE ( pMMAX_TYPE ) + ) + b_Lapo + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .ival ( b_Lapo__ival ) , + .igamma ( b_Lapo__igamma ) , + .istate ( b_Lapo__istate ) , + // + .oval ( b_Lapo__oval ) , + .oLapo ( b_Lapo__oLapo ) + ); + + assign b_Lapo__ival = b_rp__oval & !warm[cBMC_DELAY + cRP_DELAY-1]; + assign b_Lapo__igamma = b_rp__ogamma; + + assign {b_Lapo__istate[0], b_Lapo__istate[1], b_Lapo__istate[2], b_Lapo__istate[3], + b_Lapo__istate[4], b_Lapo__istate[5], b_Lapo__istate[6], b_Lapo__istate[7], + b_Lapo__istate[8], b_Lapo__istate[9], b_Lapo__istate[10], b_Lapo__istate[11], + b_Lapo__istate[12], b_Lapo__istate[13], b_Lapo__istate[14], b_Lapo__istate[15]} = f_mm__ordata; + + //------------------------------------------------------------------------------------------------------ + // delay line for Lapri & hd + //------------------------------------------------------------------------------------------------------ + + Lapri_t b_Lapri [cRP_DELAY + cLAPO_DELAY] /*synthesis keep */; + logic [1 : 0] b_hd [cRP_DELAY + cLAPO_DELAY] /*synthesis keep */; + + always_ff @(posedge iclk) begin + if (iclkena) begin + for (int i = 0; i < cRP_DELAY + cLAPO_DELAY; i++) begin + b_Lapri[i] <= (i == 0) ? b_bmc__oLapri : b_Lapri[i-1]; + b_hd [i] <= (i == 0) ? b_bmc__ohd : b_hd [i-1]; + end + end + end + + //------------------------------------------------------------------------------------------------------ + // Lextr + //------------------------------------------------------------------------------------------------------ + + rsc2_dec_Lextr + #( + .pLLR_W ( pLLR_W ) , + .pLLR_FP ( pLLR_FP ) , + .pMMAX_TYPE ( pMMAX_TYPE ) + ) + b_Lextr + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .ival ( b_Lextr__ival ) , + .ibitswap ( b_Lextr__ibitswap ) , + .idat ( b_Lextr__idat ) , + .iLapri ( b_Lextr__iLapri ) , + .iLapo ( b_Lextr__iLapo ) , + // + .oval ( b_Lextr__oval ) , + .oLextr ( b_Lextr__oLextr ) , + .odat ( b_Lextr__odat ) , + .oerr ( b_Lextr__oerr ) + ); + + assign b_Lextr__ibitswap = !ieven & !bitswap[cBMC_DELAY + cRP_DELAY + cLAPO_DELAY-1]; // inverse to forward !!!! + + assign b_Lextr__ival = b_Lapo__oval; + assign b_Lextr__iLapo = b_Lapo__oLapo; + + assign b_Lextr__idat = b_hd [cRP_DELAY + cLAPO_DELAY-1]; + assign b_Lextr__iLapri = b_Lapri [cRP_DELAY + cLAPO_DELAY-1]; + +//------------------------------------------------------------------------------------------------------ +// +// backward path END +// +//------------------------------------------------------------------------------------------------------ + + + + + + + //------------------------------------------------------------------------------------------------------ + // output interface + //------------------------------------------------------------------------------------------------------ + + assign osop = sop[cDELAY-1]; + assign oeop = eop[cDELAY-1]; + + assign ofaddr = faddr[cDELAY-1]; + assign obaddr = baddr[cDELAY-1]; + + assign oval = f_Lextr__oval; + + assign odatval = f_Lextr__oval;// & last[cDELAY-1]; incorrect for some Wimax combination of (ptype 7/11/13/17 and frame length) + + assign ofLextr = f_Lextr__oLextr; + assign ofdat = f_Lextr__odat; + assign ofderr = f_Lextr__oerr; + + assign ofdtag = fdtag[cDELAY-1]; + + assign obLextr = b_Lextr__oLextr; + assign obdat = b_Lextr__odat; + assign obderr = b_Lextr__oerr; + + assign obdtag = bdtag[cDELAY-1]; + + always_ff @(posedge iclk or posedge ireset) begin + if (ireset) begin + odone <= 1'b0; + end + else if (iclkena) begin + odone <= oval & oeop & last[cDELAY-1]; + end + end + + always_ff @(posedge iclk) begin + if (iclkena) begin + if (osop) begin + oerr <= '0; + end + else if (oval) begin + oerr <= oerr + get_dbit_err(f_Lextr__oerr, b_Lextr__oerr); + end + end + end + + function automatic logic [2 : 0] get_dbit_err (input logic [1 : 0] f, b); + get_dbit_err = f[0] + f[1] + b[0] + b[1]; + endfunction + +endmodule diff --git a/rtl/rsc2/dec/rsc2_dec_rp_mod.sv b/rtl/rsc2/dec/rsc2_dec_rp_mod.sv new file mode 100644 index 0000000..9d81097 --- /dev/null +++ b/rtl/rsc2/dec/rsc2_dec_rp_mod.sv @@ -0,0 +1,279 @@ +/* + + + + parameter bit pB_nF = 0 ; + parameter int pLLR_W = 5 ; + parameter int pLLR_FP = 3 ; + parameter int pMMAX_TYPE = 0 ; + parameter bit pUSE_P_COMP = 1 ; + + + + logic rsc2_dec_rp_mod__iclk ; + logic rsc2_dec_rp_mod__ireset ; + logic rsc2_dec_rp_mod__iclkena ; + logic rsc2_dec_rp_mod__istate_clr ; + logic rsc2_dec_rp_mod__istate_ld ; + state_t rsc2_dec_rp_mod__istate ; + logic rsc2_dec_rp_mod__ival ; + gamma_t rsc2_dec_rp_mod__igamma ; + logic rsc2_dec_rp_mod__oval ; + state_t rsc2_dec_rp_mod__ostate ; + gamma_t rsc2_dec_rp_mod__ogamma ; + state_t rsc2_dec_rp_mod__ostate2mm ; + state_t rsc2_dec_rp_mod__ostate_last ; + + + + rsc2_dec_rp_mod + #( + .pB_nF ( pB_nF ) , + .pLLR_W ( pLLR_W ) , + .pLLR_FP ( pLLR_FP ) , + .pMMAX_TYPE ( pMMAX_TYPE ) , + .pUSE_P_COMP ( pUSE_P_COMP ) + ) + rsc2_dec_rp_mod + ( + .iclk ( rsc2_dec_rp_mod__iclk ) , + .ireset ( rsc2_dec_rp_mod__ireset ) , + .iclkena ( rsc2_dec_rp_mod__iclkena ) , + .istate_clr ( rsc2_dec_rp_mod__istate_clr ) , + .istate_ld ( rsc2_dec_rp_mod__istate_ld ) , + .istate ( rsc2_dec_rp_mod__istate ) , + .ival ( rsc2_dec_rp_mod__ival ) , + .igamma ( rsc2_dec_rp_mod__igamma ) , + .oval ( rsc2_dec_rp_mod__oval ) , + .ostate ( rsc2_dec_rp_mod__ostate ) , + .ogamma ( rsc2_dec_rp_mod__ogamma ) , + .ostate2mm ( rsc2_dec_rp_mod__ostate2mm ) , + .ostate_last ( rsc2_dec_rp_mod__ostate_last ) + ); + + + assign rsc2_dec_rp_mod__iclk = '0 ; + assign rsc2_dec_rp_mod__ireset = '0 ; + assign rsc2_dec_rp_mod__iclkena = '0 ; + assign rsc2_dec_rp_mod__istate_clr = '0 ; + assign rsc2_dec_rp_mod__istate_ld = '0 ; + assign rsc2_dec_rp_mod__istate = '0 ; + assign rsc2_dec_rp_mod__ival = '0 ; + assign rsc2_dec_rp_mod__igamma = '0 ; + + + +*/ + +// +// Project : rsc2 +// Author : Shekhalev Denis (des00) +// Workfile : rsc2_dec_rp_mod.sv +// Description : recursive processor for state metrics with module ariphmetic +// Module latency is 1 tick +// + +module rsc2_dec_rp_mod +#( + parameter bit pB_nF = 0 , // 0/1 - forward/backward recursion + parameter int pLLR_W = 5 , + parameter int pLLR_FP = 3 , + parameter int pMMAX_TYPE = 1 , + parameter bit pUSE_P_COMP = 1 // use parallel comparator +) +( + iclk , + ireset , + iclkena , + // + istate_clr , + istate_ld , + istate , + // + ival , + igamma , + // + oval , + ostate , + ogamma , + ostate2mm , + ostate_last +); + + `include "rsc2_dec_types.svh" + `include "rsc2_trellis.svh" + `include "rsc2_mmax.svh" + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + input logic iclk ; + input logic ireset ; + input logic iclkena ; + // + input logic istate_clr ; // clear init state (used for look ahead) + input logic istate_ld ; // load init state + input state_t istate ; // init_alpha/init_beta for iteration + // + input logic ival ; + input gamma_t igamma ; // gamma(s, s') + // + output logic oval ; + output state_t ostate ; // alpha[k+1] / beta[k] + // + output gamma_t ogamma ; // alpha(s, k) * gamma(s, s') / beta(s, k) * gamma(s, s') + output state_t ostate2mm ; // alpha[k] / beta[k+1] + output state_t ostate_last ; // circulation state + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + gamma_t gamma; + state_t state; + state_t next_state; + + trel_state_t norm_value; + + //------------------------------------------------------------------------------------------------------ + // state recursion + //------------------------------------------------------------------------------------------------------ + + assign gamma = pB_nF ? gamma_p_beta (igamma, state) : gamma_p_alpha (igamma, state); + assign next_state = pB_nF ? get_next_beta (gamma) : get_next_alpha (gamma); + + assign norm_value = get_norm_value(state); + + always_ff @(posedge iclk) begin + if (iclkena) begin + if (istate_clr) begin + state <= '{default : '0}; + end + else if (istate_ld) begin + state <= istate; + end + else if (ival) begin + state <= next_state; + end + // + ogamma <= gnormalize(gamma, norm_value); + ostate2mm <= normalize(state, norm_value); + ostate_last <= normalize(state, norm_value); + end + end + + assign ostate = state; + + always_ff @(posedge iclk or posedge ireset) begin + if (ireset) begin + oval <= 1'b0; + end + else if (iclkena) begin + oval <= ival; + end + end + + //------------------------------------------------------------------------------------------------------ + // functions for alpha recursion + //------------------------------------------------------------------------------------------------------ + + // alpha(s, k) * gamma(s, s') + function gamma_t gamma_p_alpha (input gamma_t gamma, input state_t alpha_in); + for (int state = 0; state < 16; state++) begin + for (int inb = 0; inb < 4; inb++) begin + gamma_p_alpha[state][inb] = gamma[state][inb] + alpha_in[state]; + end + end + endfunction + + // alpha(s', k+1) = sum(alpha(s, k) * gamma(s, s')) + function state_t get_next_alpha (input gamma_t gamma); + for (int nstate = 0; nstate < 16; nstate++) begin + if (pUSE_P_COMP) begin + get_next_alpha[nstate] = st_m_p_mmax(gamma[trel.preStates[nstate][0]][0], gamma[trel.preStates[nstate][1]][1], + gamma[trel.preStates[nstate][2]][2], gamma[trel.preStates[nstate][3]][3]); + end + else begin + get_next_alpha[nstate] = st_m_mmax ( + st_m_mmax (gamma[trel.preStates[nstate][0]][0], gamma[trel.preStates[nstate][1]][1]), + st_m_mmax (gamma[trel.preStates[nstate][2]][2], gamma[trel.preStates[nstate][3]][3]) + ); + end + end + endfunction + + //------------------------------------------------------------------------------------------------------ + // functions for beta recursions + //------------------------------------------------------------------------------------------------------ + + // beta(s, k) * gamma(s, s') + function gamma_t gamma_p_beta (input gamma_t gamma, input state_t beta_in); + for (int state = 0; state < 16; state++) begin + for (int inb = 0; inb < 4; inb++) begin + gamma_p_beta[state][inb] = gamma[state][inb] + beta_in[trel.nextStates[state][inb]]; + end + end + endfunction + + // sum(beta(s', k+1) * gamma(s, s')) + function state_t get_next_beta (input gamma_t gamma); + for (int state = 0; state < 16; state++) begin + if (pUSE_P_COMP) begin + get_next_beta[state] = st_m_p_mmax(gamma[state][0], gamma[state][1], + gamma[state][2], gamma[state][3]); + end + else begin + get_next_beta[state] = st_m_mmax ( + st_m_mmax ( gamma[state][0], gamma[state][1]), + st_m_mmax ( gamma[state][2], gamma[state][3]) + ); + end + end + endfunction + + //------------------------------------------------------------------------------------------------------ + // functions for normalization + //------------------------------------------------------------------------------------------------------ + + // define normalization value for module arithmetic + function trel_state_t get_norm_value (input state_t state_in); + logic [3 : 0] eq; + begin + // detect overflow type + eq = '0; + for (int state = 0; state < 16; state++) begin + eq[0] |= (state_in[state][cSTATE_W-1 : cSTATE_W-2] == 2'b00); + eq[1] |= (state_in[state][cSTATE_W-1 : cSTATE_W-2] == 2'b01); + eq[2] |= (state_in[state][cSTATE_W-1 : cSTATE_W-2] == 2'b10); + eq[3] |= (state_in[state][cSTATE_W-1 : cSTATE_W-2] == 2'b11); + end + // + get_norm_value = '0; + if (eq[3] & !eq[0]) begin + get_norm_value = (2'b01 << (cSTATE_W-2)); + end + else if (eq[2]) begin + get_norm_value = (2'b10 << (cSTATE_W-2)); + end + else if (eq[1]) begin + get_norm_value = (2'b11 << (cSTATE_W-2)); + end + end + endfunction + + function state_t normalize (input state_t state_in, input trel_state_t nvalue); + for (int state = 0; state < 16; state++) begin + normalize[state] = state_in[state] + nvalue; + end + endfunction + + function gamma_t gnormalize (input gamma_t gamma, input trel_state_t nvalue); + for (int state = 0; state < 16; state++) begin + for (int inb = 0; inb < 4; inb++) begin + gnormalize[state][inb] = gamma[state][inb] + nvalue; + end + end + endfunction + +endmodule diff --git a/rtl/rsc2/dec/rsc2_dec_source.sv b/rtl/rsc2/dec/rsc2_dec_source.sv new file mode 100644 index 0000000..c466f72 --- /dev/null +++ b/rtl/rsc2/dec/rsc2_dec_source.sv @@ -0,0 +1,321 @@ +/* + + + + parameter int pLLR_W = 8 ; + parameter int pLLR_FP = 8 ; + parameter int pADDR_W = 8 ; + parameter bit pUSE_W_BIT = 1 ; + parameter bit pUSE_EOP_VAL_MASK = 1 ; + + + + logic rsc2_dec_source__iclk ; + logic rsc2_dec_source__ireset ; + logic rsc2_dec_source__iclkena ; + logic [3 : 0] rsc2_dec_source__icode ; + logic [5 : 0] rsc2_dec_source__iptype ; + logic rsc2_dec_source__isop ; + logic rsc2_dec_source__ieop ; + logic rsc2_dec_source__ival ; + bit_llr_t rsc2_dec_source__iLLR [0 : 1] ; + logic rsc2_dec_source__ifulla ; + logic rsc2_dec_source__iemptya ; + logic rsc2_dec_source__obusy ; + logic rsc2_dec_source__ordy ; + logic rsc2_dec_source__owrite ; + logic rsc2_dec_source__owfull ; + logic [1 : 0] rsc2_dec_source__owsel ; + logic [pADDR_W-1 : 0] rsc2_dec_source__owaddr ; + bit_llr_t rsc2_dec_source__osLLR [0 : 1] ; + bit_llr_t rsc2_dec_source__oyLLR [0 : 1] ; + bit_llr_t rsc2_dec_source__owLLR [0 : 1] ; + + + + rsc2_dec_source + #( + .pLLR_W ( pLLR_W ) , + .pLLR_FP ( pLLR_FP ) , + .pADDR_W ( pADDR_W ) , + .pUSE_W_BIT ( pUSE_W_BIT ) , + .pUSE_EOP_VAL_MASK ( pUSE_EOP_VAL_MASK ) + ) + rsc2_dec_source + ( + .iclk ( rsc2_dec_source__iclk ) , + .ireset ( rsc2_dec_source__ireset ) , + .iclkena ( rsc2_dec_source__iclkena ) , + .icode ( rsc2_dec_source__icode ) , + .iN ( rsc2_dec_source__iN ) , + .isop ( rsc2_dec_source__isop ) , + .ieop ( rsc2_dec_source__ieop ) , + .ival ( rsc2_dec_source__ival ) , + .iLLR ( rsc2_dec_source__iLLR ) , + .ifulla ( rsc2_dec_source__ifulla ) , + .iemptya ( rsc2_dec_source__iemptya ) , + .obusy ( rsc2_dec_source__obusy ) , + .ordy ( rsc2_dec_source__ordy ) , + .owrite ( rsc2_dec_source__owrite ) , + .owfull ( rsc2_dec_source__owfull ) , + .owsel ( rsc2_dec_source__owsel ) , + .owaddr ( rsc2_dec_source__owaddr ) , + .osLLR ( rsc2_dec_source__osLLR ) , + .oyLLR ( rsc2_dec_source__oyLLR ) , + .owLLR ( rsc2_dec_source__owLLR ) + ); + + + assign rsc2_dec_source__iclk = '0 ; + assign rsc2_dec_source__ireset = '0 ; + assign rsc2_dec_source__iclkena = '0 ; + assign rsc2_dec_source__icode = '0 ; + assign rsc2_dec_source__iN = '0 ; + assign rsc2_dec_source__isop = '0 ; + assign rsc2_dec_source__ieop = '0 ; + assign rsc2_dec_source__ival = '0 ; + assign rsc2_dec_source__iLLR = '0 ; + assign rsc2_dec_source__ifulla = '0 ; + assign rsc2_dec_source__iemptya = '0 ; + + + +*/ + +// +// Project : rsc2 +// Author : Shekhalev Denis (des00) +// Workfile : rsc2_dec_source.sv +// Description : Input interface of decoder. Prepare S/Y/W duobits using puncture pattern in input ram buffer +// + + +module rsc2_dec_source +#( + parameter int pLLR_W = 5 , + parameter int pLLR_FP = 2 , + parameter int pADDR_W = 8 , + // + parameter bit pUSE_W_BIT = 1 , // 0/1 - not use/use coderate with W bits (icode == 0) + parameter bit pUSE_EOP_VAL_MASK = 1 // use ieop with ival ANDED, else use single ieop +) +( + iclk , + ireset , + iclkena , + // + icode , + iptype , + // + isop , + ieop , + ival , + iLLR , + // + ifulla , + iemptya , + obusy , + ordy , + // + owrite , + owfull , + owsel , + owaddr , + osLLR , + oyLLR , + owLLR +); + + `include "rsc2_dec_types.svh" + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + input logic iclk ; + input logic ireset ; + input logic iclkena ; + // + input logic [3 : 0] icode ; + input logic [5 : 0] iptype ; + // + input logic isop ; + input logic ieop ; + input logic ival ; + input bit_llr_t iLLR [0 : 1] ; + // + input logic ifulla ; + input logic iemptya ; + output logic obusy ; + output logic ordy ; + // + output logic owrite ; + output logic owfull ; + output logic [1 : 0] owsel ; + output logic [pADDR_W-1 : 0] owaddr ; + output bit_llr_t osLLR [0 : 1] ; + output bit_llr_t oyLLR [0 : 1] ; + output bit_llr_t owLLR [0 : 1] ; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + typedef struct { + bit [3 : 0] y[4], w[4]; + } punct_t; + + localparam punct_t cP_PATTERN [8] = '{ + '{y : '{1, 1, 1, 1}, w : '{1, 1, 1, 1}} , // 1/3 + '{y : '{1, 1, 1, 1}, w : '{0, 0, 0, 0}} , // 1/2 + '{y : '{2, 2, 2, 2}, w : '{0, 0, 0, 0}} , // 2/3 + '{y : '{2, 4, 2, 4}, w : '{0, 0, 0, 0}} , // 3/4 + '{y : '{4, 4, 4, 4}, w : '{0, 0, 0, 0}} , // 4/5 + '{y : '{4, 4, 4, 8}, w : '{0, 0, 0, 0}} , // 5/6 + '{y : '{4, 8, 4, 8}, w : '{0, 0, 0, 0}} , // 6/7 + '{y : '{4, 8, 8, 8}, w : '{0, 0, 0, 0}} // 7/8 + }; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + enum bit [1:0] { + cSTATE_ERR = 2'b00, + cSTATE_PARITY_Y = 2'b01, + cSTATE_PARITY_W = 2'b10, + cSTATE_DATA = 2'b11 + } state /* synthesis syn_encoding = "sequential" */; + + logic [3 : 0] code; + + logic [12 : 0] ntable__oN; + logic [12 : 0] ntable__oNm1; + + logic [pADDR_W : 0] addr; + logic [1 : 0] addr_sel; + logic [3 : 0] addr_incr; + + logic [pADDR_W-1 : 0] edgeS; + logic [pADDR_W-1 : 0] edgeW; + + logic is_edgeS; + logic is_edgeW; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + // synthesis translate_off + initial begin + addr <= '0; + addr_incr <= '0; + end + // synthesis translate_on + //------------------------------------------------------------------------------------------------------ + // decode packet length + //------------------------------------------------------------------------------------------------------ + + rsc2_ntable + ntable + ( + .iptype ( iptype ) , + .oN ( ntable__oN ) , + .oNm1 ( ntable__oNm1 ) + ); + + //------------------------------------------------------------------------------------------------------ + // data preapare & write FSM + //------------------------------------------------------------------------------------------------------ + + assign is_edgeS = (addr >= edgeS); + assign is_edgeW = ((addr + addr_incr) > edgeW); // (addr >= edgeW); + + always_ff @(posedge iclk or posedge ireset) begin + if (ireset) begin + owrite <= 1'b0; + owfull <= 1'b0; + state <= cSTATE_ERR; + end + else if (iclkena) begin + owrite <= ival; + owfull <= ieop & (pUSE_EOP_VAL_MASK ? ival : 1'b1); // sometimes ieop can be used without ival becouse nonintegral puncture is present and direct connection to encoder is possible + if (ival) begin + if (isop) begin + state <= cSTATE_DATA; + end + else if ((state == cSTATE_DATA) & is_edgeS) begin + state <= cSTATE_PARITY_Y; + end + else if ((state == cSTATE_PARITY_Y) & is_edgeW) begin + state <= (cP_PATTERN[code].w[0] == 0 | pUSE_W_BIT == 0) ? cSTATE_ERR : cSTATE_PARITY_W; + end + end + end + end + + always_ff @(posedge iclk) begin + if (iclkena) begin + if (ival) begin + for (int i = 0; i < 2; i++) begin + if (&{iLLR[i][pLLR_W-1], ~iLLR[i][pLLR_W-2 : 0]}) begin // -2^(N-1) + osLLR[i] <= {1'b1, {(pLLR_W-2){1'b0}}, 1'b1}; // -(2^(N-1) - 1) + end + else begin + osLLR[i] <= iLLR[i]; + end + end + // + if (isop) begin + code <= icode; + edgeS <= ntable__oNm1[pADDR_W-1 : 0]; + edgeW <= ntable__oNm1[pADDR_W-1 : 0]; + // + addr <= '0; + addr_incr <= 1'b1; + end + else if ((state == cSTATE_DATA) & is_edgeS) begin + addr <= '0; + addr_incr <= cP_PATTERN[code].y[0]; + addr_sel <= 1'b1; + end + else if ((state == cSTATE_PARITY_Y) & is_edgeW) begin + addr <= '0; + addr_incr <= cP_PATTERN[code].w[0]; + addr_sel <= 1'b1; + end + else begin + addr <= addr + addr_incr; + addr_sel <= addr_sel + 1'b1; + if (state == cSTATE_PARITY_Y || state == cSTATE_PARITY_W) begin + addr_incr <= (state == cSTATE_PARITY_Y) ? cP_PATTERN[code].y[addr_sel] : cP_PATTERN[code].w[addr_sel]; + end + end // addr_incr + end // ival + end // iclkena + end // iclk + + assign owaddr = addr[pADDR_W-1 : 0]; + + always_comb begin + oyLLR = osLLR; + owLLR = osLLR; + if (state == cSTATE_DATA) begin + oyLLR = '{default : '0}; + owLLR = '{default : '0}; + end + end + + always_comb begin + owsel = 2'b00; + case (state) + cSTATE_DATA : owsel = 2'b11; + cSTATE_PARITY_Y : owsel = 2'b01; + cSTATE_PARITY_W : owsel = 2'b10; + default : owsel = 2'b00; + endcase + end + + assign ordy = !owfull & !ifulla; // not ready if all buffers is full + assign obusy = owfull | !iemptya; // busy if any buffer is not empty + +endmodule diff --git a/rtl/rsc2/dec/rsc2_dec_types.svh b/rtl/rsc2/dec/rsc2_dec_types.svh new file mode 100644 index 0000000..ec7a08a --- /dev/null +++ b/rtl/rsc2/dec/rsc2_dec_types.svh @@ -0,0 +1,55 @@ +// +// Project : rsc +// Author : Shekhalev Denis (des00) +// Workfile : rsc_dec_types.sv +// Description : file with all decoder used types +// + +//------------------------------------------------------------------------------------------------------ +// used types for decoder +//------------------------------------------------------------------------------------------------------ + + localparam int cDLLR_W = pLLR_W + 1; // duo-bin LLR + localparam int cL_EXT_W = cDLLR_W + 2; // Lextrinsic ~= 4*cDLLR_W + localparam int cSTATE_W = cL_EXT_W + 3; // state(k) ~= Lextrinsic + gamma + state(k) + localparam int cGAMMA_W = cSTATE_W + 1; // Lextrinsic + gammaL + alpha(k) + beta(k+1) + + localparam int cSTATE_DIFF_W = cSTATE_W - 2; // State difference is 2 bit less then state + + // + // single word type + typedef logic signed [pLLR_W-1 : 0] bit_llr_t; + typedef logic signed [cDLLR_W-1 : 0] dbit_llr_t; + + typedef logic signed [cL_EXT_W-1 : 0] extr_llr_t; + + typedef logic signed [cSTATE_W-1 : 0] trel_state_t; + typedef logic signed [cSTATE_DIFF_W-1 : 0] trel_state_diff_t; + + typedef logic signed [cGAMMA_W-1 : 0] trel_branch_t; + typedef logic signed [cGAMMA_W : 0] trel_branch_p1_t; + typedef logic signed [cGAMMA_W+1 : 0] trel_branch_p2_t; + + // + // arrays type + typedef dbit_llr_t dbit_allr_t [1:3]; + + typedef extr_llr_t Lextr_t [1:3]; + typedef trel_state_t Lapri_t [1:3]; + typedef trel_branch_t Lapo_t [1:3]; + + typedef trel_state_t state_t [16]; + typedef trel_state_t gamma_t [16][4]; + + typedef trel_branch_t bm_t [16][4]; + + // + // packed types for metric memory : TODO in future + typedef struct packed { + trel_state_t basea; + trel_state_diff_t diffa0, diffa1, diff2; + trel_state_t baseb; + trel_state_diff_t diffb0, diffb1, diffb2; + } metric_mem_t; + + diff --git a/rtl/rsc2/dec/rsc2_mmax.svh b/rtl/rsc2/dec/rsc2_mmax.svh new file mode 100644 index 0000000..e540df7 --- /dev/null +++ b/rtl/rsc2/dec/rsc2_mmax.svh @@ -0,0 +1,112 @@ +// +// Project : rsc2 +// Author : Shekhalev Denis (des00) +// Workfile : rsc2_mmax.svh +// Description : file with MAX* function realisation for different decoder data types +// + + //------------------------------------------------------------------------------------------------------ + // define used MAX* functions + //------------------------------------------------------------------------------------------------------ + + function trel_state_t st_mmax (input trel_state_t a, b); + st_mmax = (a > b) ? a : b; + endfunction + + // + // module based max for state processor + function trel_state_t st_m_mmax (input trel_state_t a, b); + trel_state_t tmp; + begin + tmp = a - b; + st_m_mmax = tmp[cSTATE_W-1] ? b : a; + end + endfunction + + function trel_branch_t bm_mmax (input trel_branch_t a, b); + bm_mmax = (a > b) ? a : b; + endfunction + + function trel_branch_t bm_mmax1 (input trel_branch_t a, b); + trel_branch_p1_t tmp; + begin + tmp = a - b; + bm_mmax1 = (tmp[cGAMMA_W] ? b : a) + (~|tmp[cGAMMA_W : pLLR_FP+1] | &tmp[cGAMMA_W : pLLR_FP+1]); + end + endfunction + + // + // module parallel max selector + function trel_state_t st_m_p_mmax (input trel_state_t a, b, c, d); + trel_state_t tmp_ab; + trel_state_t tmp_ac; + trel_state_t tmp_ad; + trel_state_t tmp_bc; + trel_state_t tmp_bd; + trel_state_t tmp_cd; + // + bit b_more_a, c_more_a, d_more_a; + bit c_more_b, d_more_b; + bit d_more_c; + // + trel_state_t tmpH; + trel_state_t tmpL; + begin + tmp_ab = a - b; tmp_ac = a - c; tmp_ad = a - d; + tmp_bc = b - c; tmp_bd = b - d; + tmp_cd = c - d; + // + b_more_a = tmp_ab[cSTATE_W-1]; + c_more_a = tmp_ac[cSTATE_W-1]; + d_more_a = tmp_ad[cSTATE_W-1]; + c_more_b = tmp_bc[cSTATE_W-1]; + d_more_b = tmp_bd[cSTATE_W-1]; + d_more_c = tmp_cd[cSTATE_W-1]; + // + tmpH = b_more_a ? b : a; + tmpL = d_more_c ? d : c; + + case ({b_more_a, d_more_c}) + 2'b00 : st_m_p_mmax = c_more_a ? tmpL : tmpH; + 2'b01 : st_m_p_mmax = d_more_a ? tmpL : tmpH; + 2'b10 : st_m_p_mmax = c_more_b ? tmpL : tmpH; + default : st_m_p_mmax = d_more_b ? tmpL : tmpH; + endcase + end + endfunction + + // + // parallel max selector + function trel_state_t st_p_mmax (input trel_state_t a, b, c, d); + bit a_more_b, a_more_c, a_more_d; + bit b_more_c, b_more_d; + bit c_more_d; + bit [1 : 0] sel; + begin + a_more_b = (a > b); a_more_c = (a > c); a_more_d = (a > d); + b_more_c = (b > c); b_more_d = (b > d); + c_more_d = (c > d); + // + if (a_more_b) begin + if (c_more_d) + sel = a_more_c ? 2'b00 : 2'b10; + else // d_more_c + sel = a_more_d ? 2'b00 : 2'b11; + end + else begin // b_more_a + if (c_more_d) + sel = b_more_c ? 2'b01 : 2'b10; + else // d_more_c + sel = b_more_d ? 2'b01 : 2'b11; + end + // + case (sel) + 2'b00 : st_p_mmax = a; + 2'b01 : st_p_mmax = b; + 2'b10 : st_p_mmax = c; + 2'b11 : st_p_mmax = d; + default : st_p_mmax = a; + endcase + end + endfunction + diff --git a/rtl/rsc2/dec/rsc2_trellis.svh b/rtl/rsc2/dec/rsc2_trellis.svh new file mode 100644 index 0000000..5393169 --- /dev/null +++ b/rtl/rsc2/dec/rsc2_trellis.svh @@ -0,0 +1,60 @@ +// +// Project : rsc2 +// Author : Shekhalev Denis (des00) +// Workfile : rsc2_trellis.svh +// Description : file with RSC2 trellis generate functions +// + + //------------------------------------------------------------------------------------------------------ + // define types and functions to get RSC2 trellis + //------------------------------------------------------------------------------------------------------ + + typedef struct { + bit [3 : 0] nextStates [16][4]; + bit [3 : 0] preStates [16][4]; + bit [1 : 0] outputs [16][4]; + bit outputsy [16][4]; + bit outputsw [16][4]; + } trellis_t; + + trellis_t trel; + + always_comb begin + trel = get_rsc2_trellis (0); + end + + //------------------------------------------------------------------------------------------------------ + // function's to get RSC2 trellis + //------------------------------------------------------------------------------------------------------ + + function trellis_t get_rsc2_trellis (input int tmp); + trellis_t trel; + bit [3 : 0] nstate; + bit y, w; + begin + for (int ab = 0; ab < 4; ab++) begin + for (int state = 0; state < 16; state++) begin + nstate = {ab[1] ^ state[0] ^ state[1], state[3:1]}; // feedback poly [1 0 0 1 1] + nstate = nstate ^ {ab[0], ab[0], 1'b0, ab[0]}; + + y = nstate[3] ^ state[3] ^ state[2] ^ state[0]; // poly [1 1 1 0 1] + w = nstate[3] ^ state[2] ^ state[1] ^ state[0]; // poly [1 0 1 1 1] + // + trel.nextStates[state][ab] = nstate; + trel.outputsy [state][ab] = y; + trel.outputsw [state][ab] = w; + trel.outputs [state][ab] = {y, w}; + end + end + // + for (int ab = 0; ab < 4; ab++) begin + for (int state = 0; state < 16; state++) begin + nstate = trel.nextStates[state][ab]; + trel.preStates[nstate][ab] = state[3 : 0]; + end + end + // + get_rsc2_trellis = trel; + end + endfunction + diff --git a/rtl/rsc2/enc/rsc2_enc.sv b/rtl/rsc2/enc/rsc2_enc.sv new file mode 100644 index 0000000..7b584b9 --- /dev/null +++ b/rtl/rsc2/enc/rsc2_enc.sv @@ -0,0 +1,527 @@ +/* + + + + parameter int pTAG_W = 8 ; + parameter int pN_MAX = 48 ; + parameter bit pUSE_FIXED_CODE = 0 ; + parameter bit pUSE_OBUFFER = 0 ; + + + + logic rsc2_enc__iclk ; + logic rsc2_enc__ireset ; + logic rsc2_enc__iclkena ; + logic [3 : 0] rsc2_enc__icode ; + logic [5 : 0] rsc2_enc__iptype ; + logic rsc2_enc__isop ; + logic rsc2_enc__ieop ; + logic rsc2_enc__ival ; + logic [1 : 0] rsc2_enc__idat ; + logic [pTAG_W-1 : 0] rsc2_enc__itag ; + logic rsc2_enc__obusy ; + logic rsc2_enc__ordy ; + logic rsc2_enc__idbsclk ; + logic rsc2_enc__ofull ; + logic rsc2_enc__osop ; + logic rsc2_enc__oeop ; + logic rsc2_enc__oeof ; + logic rsc2_enc__oval ; + logic [1 : 0] rsc2_enc__odat ; + logic [pTAG_W-1 : 0] rsc2_enc__otag ; + + + + rsc2_enc + #( + .pTAG_W ( pTAG_W ) , + .pN_MAX ( pN_MAX ) , + .pUSE_FIXED_CODE ( pUSE_FIXED_CODE ) , + .pUSE_OBUFFER ( pUSE_OBUFFER ) + ) + rsc2_enc + ( + .iclk ( rsc2_enc__iclk ) , + .ireset ( rsc2_enc__ireset ) , + .iclkena ( rsc2_enc__iclkena ) , + .icode ( rsc2_enc__icode ) , + .iptype ( rsc2_enc__iptype ) , + .isop ( rsc2_enc__isop ) , + .ieop ( rsc2_enc__ieop ) , + .ival ( rsc2_enc__ival ) , + .idat ( rsc2_enc__idat ) , + .itag ( rsc2_enc__itag ) , + .obusy ( rsc2_enc__obusy ) , + .ordy ( rsc2_enc__ordy ) , + .idbsclk ( rsc2_enc__idbsclk ) , + .ofull ( rsc2_enc__ofull ) , + .osop ( rsc2_enc__osop ) , + .oeop ( rsc2_enc__oeop ) , + .oeof ( rsc2_enc__oeof ) , + .oval ( rsc2_enc__oval ) , + .odat ( rsc2_enc__odat ) , + .otag ( rsc2_enc__otag ) + ); + + + assign rsc2_enc__iclk = '0 ; + assign rsc2_enc__ireset = '0 ; + assign rsc2_enc__iclkena = '0 ; + assign rsc2_enc__icode = '0 ; + assign rsc2_enc__iptype = '0 ; + assign rsc2_enc__isop = '0 ; + assign rsc2_enc__ieop = '0 ; + assign rsc2_enc__ival = '0 ; + assign rsc2_enc__idat = '0 ; + assign rsc2_enc__itag = '0 ; + assign rsc2_enc__idbsclk = '0 ; + + +*/ + +// +// Project : rsc2 +// Author : Shekhalev Denis (des00) +// Workfile : rsc2_enc.sv +// Description : RSC2 encoder with dynamic encoding parameters change on fly : coderate/permutation type vs packet length. +// + +`include "define.vh" + +module rsc2_enc +#( + parameter int pTAG_W = 8 , + parameter int pN_MAX = 2048 , // maximum number of data duobit's <= 4096 + parameter bit pUSE_FIXED_CODE = 0 , // 1 - icode/iptype/iN is constant, 0 - icode/iptype/iN is variable + parameter bit pUSE_OBUFFER = 0 // use output buffer at encoder output +) +( + iclk , + ireset , + iclkena , + // + icode , + iptype , + // + isop , + ieop , + ival , + idat , + itag , + // + obusy , + ordy , + // + idbsclk , + ofull , + // + osop , + oeop , + oeof , + oval , + odat , + otag +); + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + input logic iclk ; + input logic ireset ; + input logic iclkena ; + // + input logic [3 : 0] icode ; // coderate [0 : 7] - [1/3; 1/2; 2/3; 3/4; 4/5; 5/6; 6/7; 7/8] + input logic [5 : 0] iptype ; // permutation type [0: 33] - reordered Table A-1/2/4/5 + // + input logic isop ; + input logic ieop ; + input logic ival ; + input logic [1 : 0] idat ; + input logic [pTAG_W-1 : 0] itag ; + // + output logic obusy ; + output logic ordy ; + // + input logic idbsclk ; // output debit symbol clock + output logic ofull ; + // + output logic osop ; + output logic oeop ; + output logic oeof ; + output logic oval ; + output logic [1 : 0] odat ; + output logic [pTAG_W-1 : 0] otag ; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + `include "../rsc2_constants.svh" + + localparam int cIB_ADDR_W = clogb2(pN_MAX); + localparam int cIB_TAG_W = (pUSE_FIXED_CODE ? 0 : $bits(code_ctx_t)) + pTAG_W; // {icode, iptype, iN, itag} + + localparam int cOB_ADDR_W = clogb2(pN_MAX*3); // min coderare is 1/3 + localparam int cOB_TAG_W = cOB_ADDR_W + pTAG_W; // {Ndbits, itag} + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + code_ctx_t used_code_ctx ; + // + // source + logic source__iempty ; + logic source__iemptya ; + logic source__ifull ; + logic source__ifulla ; + // + logic source__owrite ; + logic source__owfull ; + logic [cIB_ADDR_W-1 : 0] source__owaddr ; + logic [1 : 0] source__owdat ; + // + // input buffer + logic ibuf__iwrite ; + logic ibuf__iwfull ; + logic [cIB_ADDR_W-1 : 0] ibuf__iwaddr ; + logic [1 : 0] ibuf__iwdata ; + logic [cIB_TAG_W-1 : 0] ibuf__iwtag ; + + logic ibuf__iread ; + logic ibuf__irempty ; + logic [cIB_ADDR_W-1 : 0] ibuf__iraddr0 ; + logic [1 : 0] ibuf__ordata0 ; + logic [cIB_ADDR_W-1 : 0] ibuf__iraddr1 ; + logic [1 : 0] ibuf__ordata1 ; + logic [cIB_TAG_W-1 : 0] ibuf__ortag ; + + logic ibuf__oempty ; + logic ibuf__oemptya ; + logic ibuf__ofull ; + logic ibuf__ofulla ; + // + // engine + logic engine__idbsclk ; + // + logic engine__irbuf_full ; + code_ctx_t engine__icode_ctx ; + // + logic [1 : 0] engine__irdat ; + logic [1 : 0] engine__irpdat ; + logic [pTAG_W-1 : 0] engine__irtag ; + logic engine__orempty ; + logic [cIB_ADDR_W-1 : 0] engine__oaddr ; + logic [cIB_ADDR_W-1 : 0] engine__opaddr ; + // + logic engine__iwbuf_empty ; + // + logic engine__osop ; + logic engine__oeop ; + logic engine__oeof ; + logic engine__oval ; + logic [1 : 0] engine__odat ; + logic [pTAG_W-1 : 0] engine__otag ; + // + logic engine__owrite ; + logic engine__owfull ; + logic [cOB_ADDR_W-1 : 0] engine__ownum ; + logic [cOB_ADDR_W-1 : 0] engine__owaddr ; + logic [1 : 0] engine__owdat ; + logic [pTAG_W-1 : 0] engine__owtag ; + // + // output buffer + logic obuf__iwrite ; + logic obuf__iwfull ; + logic [cOB_ADDR_W-1 : 0] obuf__iwaddr ; + logic [1 : 0] obuf__iwdat ; + logic [cOB_TAG_W-1 : 0] obuf__iwtag ; + // + logic obuf__irempty ; + logic [cOB_ADDR_W-1 : 0] obuf__iraddr ; + logic [1 : 0] obuf__ordat ; + logic [cOB_TAG_W-1 : 0] obuf__ortag ; + // + logic obuf__oempty ; + logic obuf__oemptya ; + logic obuf__ofull ; + logic obuf__ofulla ; + // + // sink + logic [cOB_ADDR_W-1 : 0] sink__irsize ; + logic sink__irfull ; + logic [1 : 0] sink__irdat ; + logic [pTAG_W-1 : 0] sink__irtag ; + logic sink__orempty ; + logic [cOB_ADDR_W-1 : 0] sink__oraddr ; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + assign used_code_ctx.code = icode ; + assign used_code_ctx.ptype = iptype ; + + //------------------------------------------------------------------------------------------------------ + // source unit + //------------------------------------------------------------------------------------------------------ + + rsc_enc_source + #( + .pADDR_W ( cIB_ADDR_W ) + ) + source + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .ival ( ival ) , + .isop ( isop ) , + .ieop ( ieop ) , + .idat ( idat ) , + // + .obusy ( obusy ) , + .ordy ( ordy ) , + // + .iempty ( source__iempty ) , + .iemptya ( source__iemptya ) , + .ifull ( source__ifull ) , + .ifulla ( source__ifulla ) , + // + .owrite ( source__owrite ) , + .owfull ( source__owfull ) , + .owaddr ( source__owaddr ) , + .owdat ( source__owdat ) + ); + + assign source__iempty = ibuf__oempty ; + assign source__iemptya = ibuf__oemptya ; + assign source__ifull = ibuf__ofull ; + assign source__ifulla = ibuf__ofulla ; + + //------------------------------------------------------------------------------------------------------ + // input data buffer + //------------------------------------------------------------------------------------------------------ + + rsc_enc_ibuffer + #( + .pADDR_W ( cIB_ADDR_W ) , + .pDATA_W ( 2 ) , // duobit + .pTAG_W ( cIB_TAG_W ) , + .pBNUM_W ( 1 ) , // double buffering + .pPIPE ( 0 ) + ) + ibuf + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .iwrite ( ibuf__iwrite ) , + .iwfull ( ibuf__iwfull ) , + .iwaddr ( ibuf__iwaddr ) , + .iwdata ( ibuf__iwdata ) , + .iwtag ( ibuf__iwtag ) , + // + .iread ( ibuf__iread ) , + .irempty ( ibuf__irempty ) , + .iraddr0 ( ibuf__iraddr0 ) , + .ordata0 ( ibuf__ordata0 ) , + .iraddr1 ( ibuf__iraddr1 ) , + .ordata1 ( ibuf__ordata1 ) , + .ortag ( ibuf__ortag ) , + // + .oempty ( ibuf__oempty ) , + .oemptya ( ibuf__oemptya ) , + .ofull ( ibuf__ofull ) , + .ofulla ( ibuf__ofulla ) + ); + + // write side + assign ibuf__iwrite = source__owrite; + assign ibuf__iwfull = source__owfull; + assign ibuf__iwaddr = source__owaddr; + assign ibuf__iwdata = source__owdat ; + + assign ibuf__iwtag = pUSE_FIXED_CODE ? itag : {used_code_ctx, itag}; + + // read side + assign ibuf__iread = 1'b1; + assign ibuf__irempty = engine__orempty; + assign ibuf__iraddr1 = engine__oaddr ; + assign ibuf__iraddr0 = engine__opaddr; + + //------------------------------------------------------------------------------------------------------ + // encoder engine + //------------------------------------------------------------------------------------------------------ + + rsc2_enc_engine + #( + .pRADDR_W ( cIB_ADDR_W ) , + .pWADDR_W ( cOB_ADDR_W ) , + // + .pTAG_W ( pTAG_W ) + ) + engine + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .idbsclk ( engine__idbsclk ) , + // + .irbuf_full ( engine__irbuf_full ) , + .icode_ctx ( engine__icode_ctx ) , + // + .irdat ( engine__irdat ) , + .irpdat ( engine__irpdat ) , + .irtag ( engine__irtag ) , + .orempty ( engine__orempty ) , + .oaddr ( engine__oaddr ) , + .opaddr ( engine__opaddr ) , + // + .iwbuf_empty ( engine__iwbuf_empty ) , + // + .osop ( engine__osop ) , + .oeop ( engine__oeop ) , + .oeof ( engine__oeof ) , + .oval ( engine__oval ) , + .odat ( engine__odat ) , + .otag ( engine__otag ) , + // + .owrite ( engine__owrite ) , + .owfull ( engine__owfull ) , + .ownum ( engine__ownum ) , + .owaddr ( engine__owaddr ) , + .owdat ( engine__owdat ) , + .owtag ( engine__owtag ) + ); + + assign engine__irbuf_full = ibuf__ofull ; + + assign engine__irdat = ibuf__ordata1 ; + assign engine__irpdat = ibuf__ordata0 ; + + always_comb begin + if (pUSE_FIXED_CODE) begin + engine__icode_ctx = used_code_ctx; + engine__irtag = ibuf__ortag; + end + else begin + {engine__icode_ctx, + engine__irtag} = ibuf__ortag; + end + end + + //------------------------------------------------------------------------------------------------------ + // output buffer + //------------------------------------------------------------------------------------------------------ + + generate + if (pUSE_OBUFFER) begin + + assign engine__idbsclk = 1'b1; + + assign engine__iwbuf_empty = obuf__oempty; + + // + // output buffer + // + codec_buffer + #( + .pADDR_W ( cOB_ADDR_W ) , + .pDAT_W ( 2 ) , // duobit + .pTAG_W ( cOB_TAG_W ) , + .pBNUM_W ( 1 ) , // double buffering + .pPIPE ( 0 ) + ) + obuf + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .iwrite ( obuf__iwrite ) , + .iwfull ( obuf__iwfull ) , + .iwaddr ( obuf__iwaddr ) , + .iwdat ( obuf__iwdat ) , + .iwtag ( obuf__iwtag ) , + // + .irempty ( obuf__irempty ) , + .iraddr ( obuf__iraddr ) , + .ordat ( obuf__ordat ) , + .ortag ( obuf__ortag ) , + // + .oempty ( obuf__oempty ) , + .oemptya ( obuf__oemptya ) , + .ofull ( obuf__ofull ) , + .ofulla ( obuf__ofulla ) + ); + + assign obuf__iwrite = engine__owrite ; + assign obuf__iwfull = engine__owfull ; + assign obuf__iwaddr = engine__owaddr ; + assign obuf__iwdat = engine__owdat ; + + assign obuf__iwtag = {engine__ownum, engine__owtag} ; + + assign obuf__irempty = sink__orempty; + assign obuf__iraddr = sink__oraddr; + // + // sink + // + rsc_enc_sink + #( + .pADDR_W ( cOB_ADDR_W ) , + .pTAG_W ( pTAG_W ) + ) + sink + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .irsize ( sink__irsize ) , + // + .irfull ( sink__irfull ) , + .irdat ( sink__irdat ) , + .irtag ( sink__irtag ) , + .orempty ( sink__orempty ) , + .oraddr ( sink__oraddr ) , + // + .ireq ( idbsclk ) , + .ofull ( ofull ) , + // + .osop ( osop ) , + .oeop ( oeop ) , + .oval ( oval ) , + .odat ( odat ) , + .otag ( otag ) + ); + + assign sink__irfull = obuf__ofull ; + assign sink__irdat = obuf__ordat ; + + assign {sink__irsize, + sink__irtag} = obuf__ortag ; + + // use for compatibility + assign oeof = oeop & oval; + end + else begin + assign engine__idbsclk = idbsclk; + + assign engine__iwbuf_empty = 1'b1; + + assign osop = engine__osop; + assign oeop = engine__oeop; + assign oeof = engine__oeof; + assign oval = engine__oval; + assign odat = engine__odat; + assign otag = engine__otag; + end + endgenerate + +endmodule diff --git a/rtl/rsc2/enc/rsc2_enc_conv_engine.sv b/rtl/rsc2/enc/rsc2_enc_conv_engine.sv new file mode 100644 index 0000000..67fb93d --- /dev/null +++ b/rtl/rsc2/enc/rsc2_enc_conv_engine.sv @@ -0,0 +1,194 @@ +/* + + + parameter int pTAG_W = 3; + + + + + logic rsc2_enc_conv_engine__iclk ; + logic rsc2_enc_conv_engine__ireset ; + logic rsc2_enc_conv_engine__iclkena ; + logic rsc2_enc_conv_engine__iclear ; + logic rsc2_enc_conv_engine__iload ; + logic [3 : 0] rsc2_enc_conv_engine__istate ; + logic rsc2_enc_conv_engine__isop ; + logic rsc2_enc_conv_engine__ival ; + logic rsc2_enc_conv_engine__ieop ; + logic [1 : 0] rsc2_enc_conv_engine__idat ; + logic [pTAG_W-1 : 0] rsc2_enc_conv_engine__itag ; + logic rsc2_enc_conv_engine__osop ; + logic rsc2_enc_conv_engine__oval ; + logic rsc2_enc_conv_engine__oeop ; + logic [1 : 0] rsc2_enc_conv_engine__odat ; + logic rsc2_enc_conv_engine__odaty ; + logic rsc2_enc_conv_engine__odatw ; + logic [pTAG_W-1 : 0] rsc2_enc_conv_engine__otag ; + logic [3 : 0] rsc2_enc_conv_engine__ostate ; + + + + c + #( + .pTAG_W ( pTAG_W ) + ) + rsc2_enc_conv_engine + ( + .iclk ( rsc2_enc_conv_engine__iclk ) , + .ireset ( rsc2_enc_conv_engine__ireset ) , + .iclkena ( rsc2_enc_conv_engine__iclkena ) , + .iclear ( rsc2_enc_conv_engine__iclear ) , + .iload ( rsc2_enc_conv_engine__iload ) , + .istate ( rsc2_enc_conv_engine__istate ) , + .isop ( rsc2_enc_conv_engine__isop ) , + .ival ( rsc2_enc_conv_engine__ival ) , + .ieop ( rsc2_enc_conv_engine__ieop ) , + .idat ( rsc2_enc_conv_engine__idat ) , + .itag ( rsc2_enc_conv_engine__itag ) , + .osop ( rsc2_enc_conv_engine__osop ) , + .oval ( rsc2_enc_conv_engine__oval ) , + .oeop ( rsc2_enc_conv_engine__oeop ) , + .odat ( rsc2_enc_conv_engine__odat ) , + .odaty ( rsc2_enc_conv_engine__odaty ) , + .odatw ( rsc2_enc_conv_engine__odatw ) , + .otag ( rsc2_enc_conv_engine__otag ) , + .ostate ( rsc2_enc_conv_engine__ostate ) + ); + + + assign rsc2_enc_conv_engine__iclk = '0 ; + assign rsc2_enc_conv_engine__ireset = '0 ; + assign rsc2_enc_conv_engine__iclkena = '0 ; + assign rsc2_enc_conv_engine__iclear = '0 ; + assign rsc2_enc_conv_engine__iload = '0 ; + assign rsc2_enc_conv_engine__istate = '0 ; + assign rsc2_enc_conv_engine__isop = '0 ; + assign rsc2_enc_conv_engine__ival = '0 ; + assign rsc2_enc_conv_engine__ieop = '0 ; + assign rsc2_enc_conv_engine__idat = '0 ; + assign rsc2_enc_conv_engine__itag = '0 ; + + + +*/ + +// +// Project : rsc2 +// Author : Shekhalev Denis (des00) +// Workfile : rsc2_enc_conv_engine.sv +// Description : rsc2 convolution engine +// + +module rsc2_enc_conv_engine +#( + parameter int pTAG_W = 3 +) +( + iclk , + ireset , + iclkena , + // + iclear , + iload , + istate , + // + isop , + ival , + ieop , + idat , + itag , + // + osop , + oval , + oeop , + odat , + odaty , + odatw , + otag , + // + ostate +); + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + input logic iclk ; + input logic ireset ; + input logic iclkena ; + // + input logic iclear ; + input logic iload ; + input logic [3 : 0] istate ; + // + input logic isop ; + input logic ival ; + input logic ieop ; + input logic [1 : 0] idat ; + input logic [pTAG_W-1 : 0] itag ; + // + output logic osop ; + output logic oval ; + output logic oeop ; + output logic [1 : 0] odat ; + output logic odaty ; + output logic odatw ; + output logic [pTAG_W-1 : 0] otag ; + // + output logic [3 : 0] ostate ; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + logic [3 : 0] state; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + always_ff @(posedge iclk or posedge ireset) begin + if (ireset) begin + osop <= 1'b0; + oval <= 1'b0; + oeop <= 1'b0; + end + else if (iclkena) begin + osop <= ival & isop; + oval <= ival; + oeop <= ival & ieop; + end + end + + always_ff @(posedge iclk) begin + if (iclkena) begin + if (ival) begin + otag <= itag; + odat <= idat; + {odaty, odatw, state} <= do_encode(idat[1], idat[0], state); + end + // + if (iclear) + state <= '0; + else if (iload) + state <= istate; + end + end + + assign ostate = state; + + function logic [5 : 0] do_encode (input logic a, b, input logic [3 : 0] state); + logic [3 : 0] nstate; + logic y, w; + begin + nstate = {a ^ state[0] ^ state[1], state[3:1]}; // feedback poly [1 0 0 1 1] + nstate = nstate ^ {b, b, 1'b0, b}; + + y = nstate[3] ^ state[3] ^ state[2] ^ state[0]; // poly [1 1 1 0 1] + w = nstate[3] ^ state[2] ^ state[1] ^ state[0]; // poly [1 0 1 1 1] + + do_encode = {y, w, nstate}; + end + endfunction + +endmodule diff --git a/rtl/rsc2/enc/rsc2_enc_engine.sv b/rtl/rsc2/enc/rsc2_enc_engine.sv new file mode 100644 index 0000000..f50207f --- /dev/null +++ b/rtl/rsc2/enc/rsc2_enc_engine.sv @@ -0,0 +1,584 @@ +/* + + + + parameter int pRADDR_W = 16 ; + parameter int pWADDR_W = 16 ; + parameter int pTAG_W = 4 ; + + + logic rsc2_enc_engine__iclk ; + logic rsc2_enc_engine__ireset ; + logic rsc2_enc_engine__iclkena ; + // + logic rsc2_enc_engine__idbsclk ; + // + logic rsc2_enc_engine__irbuf_full ; + code_ctx_t rsc2_enc_engine__icode_ctx ; + // + logic [1 : 0] rsc2_enc_engine__irdat ; + logic [1 : 0] rsc2_enc_engine__irpdat ; + logic [pTAG_W-1 : 0] rsc2_enc_engine__irtag ; + logic rsc2_enc_engine__orempty ; + logic [pRADDR_W-1 : 0] rsc2_enc_engine__oaddr ; + logic [pRADDR_W-1 : 0] rsc2_enc_engine__opaddr ; + // + logic rsc2_enc_engine__iwbuf_empty ; + // + logic rsc2_enc_engine__osop ; + logic rsc2_enc_engine__oeop ; + logic rsc2_enc_engine__oeof ; + logic rsc2_enc_engine__oval ; + logic [1 : 0] rsc2_enc_engine__odat ; + logic [pTAG_W-1 : 0] rsc2_enc_engine__otag ; + // + logic rsc2_enc_engine__owrite ; + logic rsc2_enc_engine__owfull ; + logic [pWADDR_W-1 : 0] rsc2_enc_engine__ownum ; + logic [pWADDR_W-1 : 0] rsc2_enc_engine__owaddr ; + logic [1 : 0] rsc2_enc_engine__owdat ; + logic [pTAG_W-1 : 0] rsc2_enc_engine__owtag ; + + + + rsc2_enc_engine + #( + .pRADDR_W ( pRADDR_W ) , + .pWADDR_W ( pWADDR_W ) , + // + .pTAG_W ( pTAG_W ) + ) + rsc2_enc_engine + ( + .iclk ( rsc2_enc_engine__iclk ) , + .ireset ( rsc2_enc_engine__ireset ) , + .iclkena ( rsc2_enc_engine__iclkena ) , + // + .idbsclk ( rsc2_enc_engine__idbsclk ) , + // + .irbuf_full ( rsc2_enc_engine__irbuf_full ) , + .icode_ctx ( rsc2_enc_engine__icode_ctx ) , + // + .irdat ( rsc2_enc_engine__irdat ) , + .irpdat ( rsc2_enc_engine__irpdat ) , + .irtag ( rsc2_enc_engine__irtag ) , + .orempty ( rsc2_enc_engine__orempty ) , + .oaddr ( rsc2_enc_engine__oaddr ) , + .opaddr ( rsc2_enc_engine__opaddr ) , + // + .iwbuf_empty ( rsc2_enc_engine__iwbuf_empty ) , + // + .osop ( rsc2_enc_engine__osop ) , + .oeop ( rsc2_enc_engine__oeop ) , + .oeof ( rsc2_enc_engine__oeof ) , + .oval ( rsc2_enc_engine__oval ) , + .odat ( rsc2_enc_engine__odat ) , + .otag ( rsc2_enc_engine__otag ) , + // + .owrite ( rsc2_enc_engine__owrite ) , + .owfull ( rsc2_enc_engine__owfull ) , + .ownum ( rsc2_enc_engine__ownum ) , + .owaddr ( rsc2_enc_engine__owaddr ) , + .owdat ( rsc2_enc_engine__owdat ) , + .owtag ( rsc2_enc_engine__owtag ) + ); + + + assign rsc2_enc_engine__iclk = '0 ; + assign rsc2_enc_engine__ireset = '0 ; + assign rsc2_enc_engine__iclkena = '0 ; + assign rsc2_enc_engine__idbsclk = '0 ; + assign rsc2_enc_engine__irbuf_full = '0 ; + assign rsc2_enc_engine__icode_ctx = '0 ; + assign rsc2_enc_engine__irdat = '0 ; + assign rsc2_enc_engine__irpdat = '0 ; + assign rsc2_enc_engine__irtag = '0 ; + assign rsc2_enc_engine__iwbuf_empty = '0 ; + + + +*/ + +// +// Project : rsc2 +// Author : Shekhalev Denis (des00) +// Workfile : rsc2_enc_engine.sv +// Description : RSC2 encoder engine top level +// + +module rsc2_enc_engine +#( + parameter int pRADDR_W = 16 , + parameter int pWADDR_W = 16 , + // + parameter int pTAG_W = 4 +) +( + iclk , + ireset , + iclkena , + // + idbsclk , + // + irbuf_full , + icode_ctx , + // + irdat , + irpdat , + irtag , + orempty , + oaddr , + opaddr , + // + iwbuf_empty , + // + osop , + oeop , + oeof , + oval , + odat , + otag , + // + owrite , + owfull , + ownum , + owaddr , + owdat , + owtag +); + + `include "../rsc2_constants.svh" + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + input logic iclk ; + input logic ireset ; + input logic iclkena ; + // + input logic idbsclk ; + // + input logic irbuf_full ; + input code_ctx_t icode_ctx ; + // input ram interface + input logic [1 : 0] irdat ; // direct data + input logic [1 : 0] irpdat ; // permutated data + input logic [pTAG_W-1 : 0] irtag ; + output logic orempty ; + output logic [pRADDR_W-1 : 0] oaddr ; // direct address + output logic [pRADDR_W-1 : 0] opaddr ; // permutated address + // + input logic iwbuf_empty ; + // output bit interface + output logic osop ; + output logic oeop ; + output logic oeof ; + output logic oval ; + output logic [1 : 0] odat ; + output logic [pTAG_W-1 : 0] otag ; + // output ram interface + output logic owrite ; + output logic owfull ; + output logic [pWADDR_W-1 : 0] ownum ; + output logic [pWADDR_W-1 : 0] owaddr ; + output logic [1 : 0] owdat ; + output logic [pTAG_W-1 : 0] owtag ; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + // + // parameter table + logic [5 : 0] ptab__iptype ; + + logic [12 : 0] used_N ; + logic [3 : 0] used_Nmod15 ; + logic [12 : 0] used_P [0 : 3] ; + logic [12 : 0] used_Pincr ; + + logic [3 : 0] used_code ; + logic [3 : 0] used_code_r [0 : 1] ; + + // + // address generator + logic paddr_gen__iclear ; + logic paddr_gen__ienable ; + + logic [12 : 0] paddr_gen__oaddr ; + logic [12 : 0] paddr_gen__opaddr ; + logic paddr_gen__obitinv ; + + // + // ctrl + logic ctrl__oaddr_clear ; + logic ctrl__oaddr_enable ; + + logic ctrl__ostate_clear ; + logic ctrl__ostate_load ; + + logic ctrl__oval ; + logic ctrl__osop ; + logic ctrl__oeop ; + logic ctrl__olast ; + logic [1 : 0] ctrl__ostage ; + + // + // convolution engine + logic enc__iclear ; + logic enc__iload ; + logic [3 : 0] enc__istate [0 : 1] ; + logic enc__isop ; + logic enc__ival ; + logic enc__ieop ; + logic [2 : 0] enc__itag ; + logic [1 : 0] enc__idat [0 : 1] ; + + logic enc__osop [0 : 1] ; + logic enc__oval [0 : 1] ; + logic enc__oeop [0 : 1] ; + logic [2 : 0] enc__otag [0 : 1] ; + logic [1 : 0] enc__odat [0 : 1] ; + logic [1 : 0] enc__odaty ; + logic [1 : 0] enc__odatw ; + logic [3 : 0] enc__ostate [0 : 1] ; + + // + // puncture modules + logic punct_sop; + logic punct_val; + logic punct_eop; + logic punct_eof; + logic [1 : 0] punct_dat; + logic [1 : 0] punct_type; + + logic puncty__oval; + logic [1 : 0] puncty__odat; + + logic punctw__oval; + logic [1 : 0] punctw__odat; + + //------------------------------------------------------------------------------------------------------ + // decode permutation type parameters + //------------------------------------------------------------------------------------------------------ + + rsc2_ptable + ptab + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .iptype ( ptab__iptype ) , + // + .oN ( used_N ) , + .oNm1 ( ) , // n.u. + .oNmod15 ( used_Nmod15 ) , + // + .oP ( used_P ) , + .oP0comp ( ) , // n.u. + .oPincr ( used_Pincr ) + ); + + assign used_code = icode_ctx.code; + + assign ptab__iptype = icode_ctx.ptype; + + //------------------------------------------------------------------------------------------------------ + // input data buffer address generator + //------------------------------------------------------------------------------------------------------ + + rsc_enc_paddr_gen + paddr_gen + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .iclear ( paddr_gen__iclear ) , + .ienable ( paddr_gen__ienable ) , + // + .iP ( used_P ) , + .iN ( used_N ) , + .iPincr ( used_Pincr ) , + .iPdvbinv ( 1'b1 ) , + // + .oaddr ( paddr_gen__oaddr ) , + .opaddr ( paddr_gen__opaddr ) , + .obitinv ( paddr_gen__obitinv ) + ); + + assign paddr_gen__iclear = ctrl__oaddr_clear; + assign paddr_gen__ienable = ctrl__oaddr_enable; + + assign oaddr = paddr_gen__oaddr [pRADDR_W-1 : 0]; + assign opaddr = paddr_gen__opaddr [pRADDR_W-1 : 0]; + + //------------------------------------------------------------------------------------------------------ + // align input buffer read latency + //------------------------------------------------------------------------------------------------------ + + logic buffin_bit_inv; + + always_ff @(posedge iclk) begin + if (iclkena) begin + buffin_bit_inv <= paddr_gen__obitinv; + end + end + + //------------------------------------------------------------------------------------------------------ + // main FSM + //------------------------------------------------------------------------------------------------------ + + rsc_enc_ctrl + ctrl + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .idbsclk ( idbsclk ) , + // + .icode ( used_code ) , + .iN ( used_N ) , + // + .ibuf_full ( irbuf_full ) , + .obuf_empty ( orempty ) , + .iobuf_empty ( iwbuf_empty ) , + // + .oaddr_clear ( ctrl__oaddr_clear ) , + .oaddr_enable ( ctrl__oaddr_enable ) , + // + .ostate_clear ( ctrl__ostate_clear ) , + .ostate_load ( ctrl__ostate_load ) , + // + .osop ( ctrl__osop ) , + .oeop ( ctrl__oeop ) , + .oval ( ctrl__oval ) , + .olast ( ctrl__olast ) , + .ostage ( ctrl__ostage ) + ); + + //------------------------------------------------------------------------------------------------------ + // convolution coders with SC counters + //------------------------------------------------------------------------------------------------------ + + generate + genvar i; + for (i = 0; i < 2; i++) begin : engine_inst + rsc2_enc_conv_engine + #( + .pTAG_W ( 3 ) + ) + enc + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .iclear ( enc__iclear ) , + .iload ( enc__iload ) , + .istate ( enc__istate [i] ) , + // + .isop ( enc__isop ) , + .ival ( enc__ival ) , + .ieop ( enc__ieop ) , + .idat ( enc__idat [i] ) , + .itag ( enc__itag ) , + // + .osop ( enc__osop [i] ) , + .oval ( enc__oval [i] ) , + .oeop ( enc__oeop [i] ) , + .otag ( enc__otag [i] ) , + .odat ( enc__odat [i] ) , + .odaty ( enc__odaty [i] ) , + .odatw ( enc__odatw [i] ) , + .ostate ( enc__ostate [i] ) + ); + + rsc2_sctable + sctab0 + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .iNmod15 ( used_Nmod15 ) , + // + .istate ( enc__ostate [i] ) , + .ostate ( enc__istate [i] ) , + .ostate_r ( ) + ); + end + endgenerate + + assign enc__idat[1] = irdat; + assign enc__idat[0] = buffin_bit_inv ? {irpdat[0], irpdat[1]} : irpdat; + + // + // align input buffer read latency + always_ff @(posedge iclk or posedge ireset) begin + if (ireset) begin + enc__ival <= 1'b0; + end + else if (iclkena) begin + enc__ival <= ctrl__oval; + end + end + + always_ff @(posedge iclk) begin + if (iclkena) begin + enc__iclear <= ctrl__ostate_clear; + enc__iload <= ctrl__ostate_load ; + // + enc__isop <= ctrl__osop; + enc__ieop <= ctrl__oeop; + enc__itag <= {ctrl__olast, ctrl__ostage}; + // + used_code_r[0] <= used_code; + end + end + + //------------------------------------------------------------------------------------------------------ + // align engine delay + //------------------------------------------------------------------------------------------------------ + + always_ff @(posedge iclk) begin + if (iclkena) begin + used_code_r[1] <= used_code_r[0]; + end + end + + //------------------------------------------------------------------------------------------------------ + // puncture modules has 1 tick delay + //------------------------------------------------------------------------------------------------------ + + always_ff @(posedge iclk or posedge ireset) begin + if (ireset) begin + punct_val <= 1'b0; + end + else if (iclkena) begin + punct_val <= enc__oval [1]; + end + end + + always_ff @(posedge iclk) begin + if (iclkena) begin + punct_dat <= enc__odat [1]; + punct_sop <= enc__osop [1] & (enc__otag[1][1 : 0] == 0); + punct_eop <= enc__oeop [1] & (enc__otag[1][1 : 0] == 0); + punct_eof <= enc__oeop [1] & enc__otag[1][2]; + punct_type <= enc__otag [1][1 : 0] ; + end + end + + rsc2_enc_punct + #( + .pWnY ( 0 ) + ) + puncty + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .icode ( used_code_r[1] ) , + // + .isop ( enc__osop [1] ) , + .ival ( enc__oval [1] ) , + .idat ( enc__odaty ) , + // + .oval ( puncty__oval ) , + .odat ( puncty__odat ) + ); + + rsc2_enc_punct + #( + .pWnY ( 1 ) + ) + punctw + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .icode ( used_code_r[1] ) , + // + .isop ( enc__osop [1] ) , + .ival ( enc__oval [1] ) , + .idat ( enc__odatw ) , + // + .oval ( punctw__oval ) , + .odat ( punctw__odat ) + ); + + //------------------------------------------------------------------------------------------------------ + // output stream assembler + //------------------------------------------------------------------------------------------------------ + + always_ff @(posedge iclk) begin + if (iclkena) begin + osop <= punct_sop; + oeop <= punct_eop; + // + if (punct_val) begin + case (punct_type) + 2'b00 : odat <= punct_dat; + 2'b01 : odat <= puncty__odat; + 2'b10 : odat <= punctw__odat; + default : begin end + endcase + // + if (punct_sop) begin + otag <= irtag; + end + end + end + end + + always_ff @(posedge iclk or posedge ireset) begin + if (ireset) begin + oval <= 1'b0; + oeof <= 1'b0; // is single strobe too + end + else if (iclkena) begin + oeof <= punct_eof; + case (punct_type) + 2'b00 : oval <= punct_val; + 2'b01 : oval <= puncty__oval; + 2'b10 : oval <= punctw__oval; + default : oval <= punct_val; + endcase + end + end + + //------------------------------------------------------------------------------------------------------ + // output ram converter + //------------------------------------------------------------------------------------------------------ + + // make 1 tick offset to get owaddr == number of output dbits + always_ff @(posedge iclk or posedge ireset) begin + if (ireset) begin + owfull <= 1'b0; + end + else if (iclkena) begin + owfull <= oeof; + end + end + + assign owrite = oval; + assign owdat = odat; + assign owtag = otag; + + // ownum has enough bitwidth because its x3 of input maximum data length + assign ownum = owaddr; // +1 of last owaddr because owfull has 1 tick offset + + always_ff @(posedge iclk) begin + if (iclkena) begin + owaddr <= (punct_val & punct_sop) ? '0 : (owaddr + owrite); + end + end + +endmodule + diff --git a/rtl/rsc2/enc/rsc2_enc_punct.sv b/rtl/rsc2/enc/rsc2_enc_punct.sv new file mode 100644 index 0000000..e2a264f --- /dev/null +++ b/rtl/rsc2/enc/rsc2_enc_punct.sv @@ -0,0 +1,142 @@ +/* + + + + parameter bit pWnY = 0; + + + logic rsc2_enc_punct__iclk ; + logic rsc2_enc_punct__ireset ; + logic rsc2_enc_punct__iclkena ; + logic [3 : 0] rsc2_enc_punct__icode ; + logic rsc2_enc_punct__isop ; + logic rsc2_enc_punct__ival ; + logic [1 : 0] rsc2_enc_punct__idat ; + logic rsc2_enc_punct__oval ; + logic [1 : 0] rsc2_enc_punct__odat ; + + + + rsc2_enc_punct + #( + .pWnY ( pWnY ) + ) + rsc2_enc_punct + ( + .iclk ( rsc2_enc_punct__iclk ) , + .ireset ( rsc2_enc_punct__ireset ) , + .iclkena ( rsc2_enc_punct__iclkena ) , + .icode ( rsc2_enc_punct__icode ) , + .isop ( rsc2_enc_punct__isop ) , + .ival ( rsc2_enc_punct__ival ) , + .idat ( rsc2_enc_punct__idat ) , + .oval ( rsc2_enc_punct__oval ) , + .odat ( rsc2_enc_punct__odat ) + ); + + + assign rsc2_enc_punct__iclk = '0 ; + assign rsc2_enc_punct__ireset = '0 ; + assign rsc2_enc_punct__iclkena = '0 ; + assign rsc2_enc_punct__icode = '0 ; + assign rsc2_enc_punct__isop = '0 ; + assign rsc2_enc_punct__ival = '0 ; + assign rsc2_enc_punct__idat = '0 ; + + + +*/ + +// +// Project : rsc2 +// Author : Shekhalev Denis (des00) +// Workfile : rsc2_enc_punct.sv +// Description : module to implement used puncture pattern for Y/W duobits +// + +module rsc2_enc_punct +#( + parameter bit pWnY = 0 // 0/1 y/w bit +) +( + iclk , + ireset , + iclkena , + // + icode , + // + isop , + ival , + idat , + // + oval , + odat +); + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + input logic iclk ; + input logic ireset ; + input logic iclkena ; + // + input logic [3 : 0] icode ; // coderate [0 : 7] - [1/3; 1/2; 2/3; 3/4; 4/5; 5/6; 6/7; 7/8] + // + input logic isop ; + input logic ival ; + input logic [1 : 0] idat ; + // + output logic oval ; + output logic [1 : 0] odat ; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + typedef struct { + logic [27 : 0] y; + logic [27 : 0] w; + logic [4 : 0] s; // up to 32 + } punct_t; + + localparam punct_t cPATTERN [0 : 7] = '{ + '{y : 28'b000000000000000000000000000_1, w : 28'b000000000000000000000000000_1, s : 0} , // 1/3 + '{y : 28'b000000000000000000000000000_1, w : 28'b000000000000000000000000000_0, s : 0} , // 1/2 + '{y : 28'b00000000000000000000000000_01, w : 28'b00000000000000000000000000_00, s : 1} , // 2/3 + '{y : 28'b0000000000000000000000_000101, w : 28'b0000000000000000000000_000000, s : 5} , // 3/4 + '{y : 28'b000000000000000000000000_0001, w : 28'b000000000000000000000000_0000, s : 3} , // 4/5 + '{y : 28'b00000000_00000001000100010001, w : 28'b00000000_00000000000000000000, s : 19} , // 5/6 + '{y : 28'b0000000000000000_000000010001, w : 28'b0000000000000000_000000000000, s : 11} , // 6/7 + '{y : 28'b_0000000100000001000000010001, w : 28'b_0000000000000000000000000000, s : 27} // 7/8 + }; + + logic [4 : 0] cnt; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + always_ff @(posedge iclk) begin + if (iclkena) begin + if (ival) begin + odat <= idat; + // + if (isop) + cnt <= (cPATTERN[icode].s != 0); + else if (cnt == cPATTERN[icode].s) + cnt <= '0; + else + cnt <= cnt + 1'b1; + end + end + end + + always_ff @(posedge iclk or posedge ireset) begin + if (ireset) + oval <= 1'b0; + else if (iclkena) + oval <= ival & (isop | (pWnY ? cPATTERN[icode].w[cnt] : cPATTERN[icode].y[cnt])); + end + +endmodule diff --git a/rtl/rsc2/rsc2_constants.svh b/rtl/rsc2/rsc2_constants.svh new file mode 100644 index 0000000..fd3a1a7 --- /dev/null +++ b/rtl/rsc2/rsc2_constants.svh @@ -0,0 +1,18 @@ +// +// Project : rsc +// Author : Shekhalev Denis (des00) +// Workfile : rsc2_constants.svh +// Description : DVB RSC2 constants and constant types +// + + typedef logic [3 : 0] code_t; // coderate [0 : 7] - [1/3; 1/2; 2/3; 3/4; 4/5; 5/6; 6/7; 7/8] + + typedef logic [5 : 0] ptype_t; // permutation type [0: 33] - reordered Table A-1/2/4/5 + + typedef logic [12 : 0] dbits_num_t; // number of data duobits/byte size [32:4096]/[8:1024] + + typedef struct packed { + code_t code; // coderate [0 : 7] - [1/3; 1/2; 2/3; 3/4; 4/5; 5/6; 6/7; 7/8] + ptype_t ptype; // permutation type [0: 33] - reordered Table A-1/2/4/5 + } code_ctx_t; + diff --git a/rtl/rsc2/rsc2_dvb_ptable.svh b/rtl/rsc2/rsc2_dvb_ptable.svh new file mode 100644 index 0000000..e566c39 --- /dev/null +++ b/rtl/rsc2/rsc2_dvb_ptable.svh @@ -0,0 +1,49 @@ +// +// Project : rsc2 +// Author : Shekhalev Denis (des00) +// Workfile : rsc2_dvb_ptable.svh +// Description : file with RSC2 reordered permutation tables A-1/2/4/5 +// + + localparam int cDVB_PTABLE_SIZE = 34; + + typedef int tab_t [6]; // {P, Q0, Q1, Q2, Q3, N} + typedef tab_t tab_dvb_t [cDVB_PTABLE_SIZE]; + + // {P, Q0, Q1, Q2, Q3, N} + localparam tab_dvb_t cDVB_PTABLE = '{ + '{ 9, 2, 2, 8, 0, 14 * 4 } , // 0 + '{ 17, 9, 5, 14, 1, 38 * 4 } , // 1 + '{ 23, 10, 5, 0, 0, 51 * 4 } , // 2 + '{ 23, 6, 10, 4, 0, 55 * 4 } , // 3 + '{ 23, 10, 2, 11, 1, 59 * 4 } , // 4 + '{ 23, 6, 8, 1, 1, 62 * 4 } , // 5 + '{ 25, 1, 1, 2, 0, 69 * 4 } , // 6 + '{ 23, 8, 1, 4, 1, 84 * 4 } , // 7 + '{ 23, 6, 13, 10, 0, 85 * 4 } , // 8 + '{ 25, 1, 7, 2, 1, 93 * 4 } , // 9 + '{ 25, 1, 2, 0, 1, 96 * 4 } , // 10 + '{ 23, 10, 8, 2, 1, 100 * 4 } , // 11 + '{ 29, 1, 4, 1, 1, 108 * 4 } , // 12 + '{ 29, 6, 5, 0, 0, 115 * 4 } , // 13 + '{ 31, 0, 3, 1, 0, 123 * 4 } , // 14 + '{ 31, 1, 1, 2, 1, 128 * 4 } , // 15 + '{ 31, 0, 1, 2, 0, 130 * 4 } , // 16 + '{ 31, 0, 0, 0, 0, 144 * 4 } , // 17 + '{ 33, 9, 15, 3, 1, 170 * 4 } , // 18 + '{ 37, 0, 2, 0, 2, 175 * 4 } , // 19 + '{ 37, 1, 3, 4, 2, 188 * 4 } , // 20 + '{ 37, 6, 1, 15, 0, 192 * 4 } , // 21 + '{ 39, 7, 0, 0, 0, 194 * 4 } , // 22 + '{ 45, 1, 1, 4, 0, 256 * 4 } , // 23 + '{ 43, 0, 0, 6, 2, 264 * 4 } , // 24 + '{ 49, 0, 3, 5, 0, 298 * 4 } , // 25 + '{ 49, 0, 6, 0, 1, 307 * 4 } , // 26 + '{ 49, 0, 5, 0, 5, 333 * 4 } , // 27 + '{ 53, 1, 4, 6, 2, 355 * 4 } , // 28 + '{ 53, 1, 10, 7, 1, 400 * 4 } , // 29 + '{ 59, 1, 1, 2, 1, 438 * 4 } , // 30 + '{ 59, 3, 8, 5, 1, 444 * 4 } , // 31 + '{ 65, 0, 3, 7, 0, 539 * 4 } , // 32 + '{ 81, 1, 2, 5, 2, 599 * 4 } // 33 + }; diff --git a/rtl/rsc2/rsc2_ntable.sv b/rtl/rsc2/rsc2_ntable.sv new file mode 100644 index 0000000..7fd599a --- /dev/null +++ b/rtl/rsc2/rsc2_ntable.sv @@ -0,0 +1,90 @@ +/* + + + + parameter pW = 13 ; + + + + logic [5 : 0] rsc2_ntable__iptype ; + logic [pW-1 : 0] rsc2_ntable__oN ; + logic [pW-1 : 0] rsc2_ntable__oNm1 ; + + + + + rsc2_ntable + #( + .pW ( pW ) + ) + rsc2_ntable + ( + .iptype ( rsc2_ntable__iptype ) , + .oN ( rsc2_ntable__oN ) , + .oNm1 ( rsc2_ntable__oNm1 ) + ); + + + assign rsc2_ntable__iptype = '0 ; + + + +*/ + +// +// Project : rsc2 +// Author : Shekhalev Denis (des00) +// Workfile : rsc2_ntable.sv +// Description : Packet length in duobits parameters table. +// + +module rsc2_ntable +#( + parameter pW = 13 // fixed, don't change +) +( + iptype , + // + oN , + oNm1 +); + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + input logic [5 : 0] iptype ; // permutation type [ 0: 33] - reordered Table A-1/2/4/5 + // + output logic [pW-1 : 0] oN ; // used data pair size + output logic [pW-1 : 0] oNm1 ; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + `include "rsc2_dvb_ptable.svh" + + typedef int used_tab_t [2]; // {N, Nm1} + typedef used_tab_t used_tab_dvb_t [cDVB_PTABLE_SIZE]; + + localparam used_tab_dvb_t cUSED_DVB_NTABLE = get_dvb_ntable(0); + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + function used_tab_dvb_t get_dvb_ntable (input int pipa); + for (int i = 0; i < cDVB_PTABLE_SIZE; i++) begin + get_dvb_ntable[i][0] = cDVB_PTABLE[i][5]; + get_dvb_ntable[i][1] = cDVB_PTABLE[i][5] - 1; + end + endfunction + + //------------------------------------------------------------------------------------------------------ + // length decoding + //------------------------------------------------------------------------------------------------------ + + assign oN = cUSED_DVB_NTABLE[iptype][0][pW-1 : 0]; + assign oNm1 = cUSED_DVB_NTABLE[iptype][1][pW-1 : 0]; + +endmodule diff --git a/rtl/rsc2/rsc2_ptable.sv b/rtl/rsc2/rsc2_ptable.sv new file mode 100644 index 0000000..1086710 --- /dev/null +++ b/rtl/rsc2/rsc2_ptable.sv @@ -0,0 +1,159 @@ +/* + + + + parameter pW = 13 ; + + + + logic rsc2_ptable__iclk ; + logic rsc2_ptable__ireset ; + logic rsc2_ptable__iclkena ; + logic [5 : 0] rsc2_ptable__iptype ; + logic [pW-1 : 0] rsc2_ptable__oN ; + logic [pW-1 : 0] rsc2_ptable__oNm1 ; + logic [3 : 0] rsc2_ptable__oNmod15 ; + logic [pW-1 : 0] rsc2_ptable__oP [4] ; + logic [pW-1 : 0] rsc2_ptable__oP0comp ; + logic [pW-1 : 0] rsc2_ptable__oPincr ; + + + + + rsc2_ptable + #( + .pW ( pW ) + ) + rsc2_ptable + ( + .iclk ( rsc2_ptable__iclk ) , + .ireset ( rsc2_ptable__ireset ) , + .iclkena ( rsc2_ptable__iclkena ) , + .iptype ( rsc2_ptable__iptype ) , + .oN ( rsc2_ptable__oN ) , + .oNm1 ( rsc2_ptable__oNm1 ) , + .oNmod15 ( rsc2_ptable__oNmod15 ) , + .oP ( rsc2_ptable__oP ) , + .oP0comp ( rsc2_ptable__oP0comp ) , + .oPincr ( rsc2_ptable__oPincr ) + ); + + + assign rsc2_ptable__iclk = '0 ; + assign rsc2_ptable__ireset = '0 ; + assign rsc2_ptable__iclkena = '0 ; + assign rsc2_ptable__iptype = '0 ; + + + +*/ + +// +// Project : rsc2 +// Author : Shekhalev Denis (des00) +// Workfile : rsc2_ptable.sv +// Description : Permutation parameters table. There is static tables for DVB permutation parameters, +// special parameters for decoder permutation, circulation state LUT selector. +// It takes 2 clock cycles to apply new parameters +// + +module rsc2_ptable +#( + parameter pW = 13 // fixed, don't change +) +( + iclk , + ireset , + iclkena , + // + iptype , + // + oN , + oNm1 , + oNmod15 , + // + oP , + oP0comp , + oPincr +); + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + input logic iclk ; + input logic ireset ; + input logic iclkena ; + // + input logic [5 : 0] iptype ; // permutation type [ 0: 33] - reordered Table A-1/2/4/5 + // + output logic [pW-1 : 0] oN ; // used data pair size + output logic [pW-1 : 0] oNm1 ; + output logic [3 : 0] oNmod15 ; + // + output logic [pW-1 : 0] oP [4] ; + output logic [pW-1 : 0] oP0comp ; // complement oP[0] for backward recursion address process + output logic [pW-1 : 0] oPincr ; // base increment for address counter at j = 0 + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + `include "rsc2_dvb_ptable.svh" + + typedef int used_tab_t [6]; // {P0, P1, P2, P3, N, Nmod15} + typedef used_tab_t used_tab_dvb_t [cDVB_PTABLE_SIZE]; + + localparam used_tab_dvb_t cUSED_DVB_PTABLE = get_dvb_ptable(0); + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + function used_tab_dvb_t get_dvb_ptable (input int pipa); + for (int i = 0; i < cDVB_PTABLE_SIZE; i++) begin + get_dvb_ptable[i][0] = cDVB_PTABLE[i][0]; + + get_dvb_ptable[i][1] = (3 + 4 * cDVB_PTABLE[i][2] ) % cDVB_PTABLE[i][5]; + get_dvb_ptable[i][2] = (3 + 4 * (cDVB_PTABLE[i][1] * cDVB_PTABLE[i][0] + cDVB_PTABLE[i][3])) % cDVB_PTABLE[i][5]; + get_dvb_ptable[i][3] = (3 + 4 * (cDVB_PTABLE[i][1] * cDVB_PTABLE[i][0] + cDVB_PTABLE[i][4])) % cDVB_PTABLE[i][5]; + + get_dvb_ptable[i][4] = cDVB_PTABLE[i][5]; + get_dvb_ptable[i][5] = cDVB_PTABLE[i][5] % 15; + end + endfunction + + //------------------------------------------------------------------------------------------------------ + // 1 tick parameter decoding + //------------------------------------------------------------------------------------------------------ + + // increment for permutation address generator + assign oPincr = 3; + + always_ff @(posedge iclk) begin + if (iclkena) begin + // detect permutation paramters + oP[0] <= cUSED_DVB_PTABLE[iptype][0][pW-1 : 0]; + oP[1] <= cUSED_DVB_PTABLE[iptype][1][pW-1 : 0]; + oP[2] <= cUSED_DVB_PTABLE[iptype][2][pW-1 : 0]; + oP[3] <= cUSED_DVB_PTABLE[iptype][3][pW-1 : 0]; + // detect length + oN <= cUSED_DVB_PTABLE[iptype][4][pW-1 : 0]; + // get circulation state LUT selector + oNmod15 <= cUSED_DVB_PTABLE[iptype][5][3 : 0]; + end + end + + //------------------------------------------------------------------------------------------------------ + // 2 tick cycle parameter decoding + //------------------------------------------------------------------------------------------------------ + + always_ff @(posedge iclk) begin + if (iclkena) begin + // detect permutation complement for P[0] + oP0comp <= oN - oP[0]; + oNm1 <= oN - 1'b1; + end + end + +endmodule diff --git a/rtl/rsc2/rsc2_sctable.sv b/rtl/rsc2/rsc2_sctable.sv new file mode 100644 index 0000000..be685ce --- /dev/null +++ b/rtl/rsc2/rsc2_sctable.sv @@ -0,0 +1,110 @@ +/* + + + logic rsc2_sctable__iclk ; + logic rsc2_sctable__ireset ; + logic rsc2_sctable__iclkena ; + logic [3 : 0] rsc2_sctable__iNmod15 ; + logic [3 : 0] rsc2_sctable__istate ; + logic [3 : 0] rsc2_sctable__ostate ; + logic [3 : 0] rsc2_sctable__ostate_r ; + + + + rsc2_sctable + rsc2_sctable + ( + .iclk ( rsc2_sctable__iclk ) , + .ireset ( rsc2_sctable__ireset ) , + .iclkena ( rsc2_sctable__iclkena ) , + .iNmod15 ( rsc2_sctable__iNmod15 ) , + .istate ( rsc2_sctable__istate ) , + .ostate ( rsc2_sctable__ostate ) , + .ostate_r ( rsc2_sctable__ostate_r ) + ); + + + assign rsc2_sctable__iclk = '0 ; + assign rsc2_sctable__ireset = '0 ; + assign rsc2_sctable__iclkena = '0 ; + assign rsc2_sctable__iNmod15 = '0 ; + assign rsc2_sctable__istate = '0 ; + + + +*/ + +// +// Project : rsc2 +// Author : Shekhalev Denis (des00) +// Workfile : rsc2_sctable.sv +// Description : Circullar state correspondence table. Its static table for different packet lengths +// Module can use asynchronus or register output for correspondence state +// + +module rsc2_sctable +( + iclk , + ireset , + iclkena , + iNmod15 , + istate , + ostate , + ostate_r +); + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + input logic iclk ; + input logic ireset ; + input logic iclkena ; + input logic [3 : 0] iNmod15 ; + input logic [3 : 0] istate ; + output logic [3 : 0] ostate ; + output logic [3 : 0] ostate_r ; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + typedef bit [3 : 0] lut_line_t [0 : 15]; + typedef lut_line_t lut_t [0 : 15]; + + localparam lut_t cLUT = '{ + '{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} , // 0 + '{0, 14, 3, 13, 7, 9, 4, 10, 15, 1, 12, 2, 8, 6, 11, 5} , // 1 + '{0, 11, 13, 6, 10, 1, 7, 12, 5, 14, 8, 3, 15, 4, 2, 9} , // 2 + '{0, 8, 9, 1, 2, 10, 11, 3, 4, 12, 13, 5, 6, 14, 15, 7} , // 3 + '{0, 3, 4, 7, 8, 11, 12, 15, 1, 2, 5, 6, 9, 10, 13, 14} , // 4 + '{0, 12, 5, 9, 11, 7, 14, 2, 6, 10, 3, 15, 13, 1, 8, 4} , // 5 + '{0, 4, 12, 8, 9, 13, 5, 1, 2, 6, 14, 10, 11, 15, 7, 3} , // 6 + '{0, 6, 10, 12, 5, 3, 15, 9, 11, 13, 1, 7, 14, 8, 4, 2} , // 7 + '{0, 7, 8, 15, 1, 6, 9, 14, 3, 4, 11, 12, 2, 5, 10, 13} , // 8 + '{0, 5, 14, 11, 13, 8, 3, 6, 10, 15, 4, 1, 7, 2, 9, 12} , // 9 + '{0, 13, 7, 10, 15, 2, 8, 5, 14, 3, 9, 4, 1, 12, 6, 11} , // 10 + '{0, 2, 6, 4, 12, 14, 10, 8, 9, 11, 15, 13, 5, 7, 3, 1} , // 11 + '{0, 9, 11, 2, 6, 15, 13, 4, 12, 5, 7, 14, 10, 3, 1, 8} , // 12 + '{0, 10, 15, 5, 14, 4, 1, 11, 13, 7, 2, 8, 3, 9, 12, 6} , // 13 + '{0, 15, 1, 14, 3, 12, 2, 13, 7, 8, 6, 9, 4, 11, 5, 10} , // 14 + '{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} // 15 + }; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + assign ostate = cLUT[iNmod15][istate]; + + always_ff @(posedge iclk) begin + if (iclkena) begin + ostate_r <= ostate; + end + end + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + +endmodule diff --git a/testbench/rsc2/bertest.sv b/testbench/rsc2/bertest.sv new file mode 100644 index 0000000..b308575 --- /dev/null +++ b/testbench/rsc2/bertest.sv @@ -0,0 +1,417 @@ +// +// Project : rsc2 +// Author : Shekhalev Denis (des00) +// Workfile : bertest.sv +// Description : testbench for RTL RSC2 coder/decoder for QPSK +// + +`include "define.vh" +`include "awgn_class.svh" +`include "pkt_class.svh" + +module bertest ; + +//parameter int pCODE = 0 ; + parameter int pCODE = 1 ; +//parameter int pCODE = 2 ; +//parameter int pCODE = 3 ; +//parameter int pCODE = 4 ; +//parameter int pCODE = 5 ; +//parameter int pCODE = 6 ; +//parameter int pCODE = 7 ; + +//parameter int pPTYPE = 0 ; // 14 bytes == 56 dbits + parameter int pPTYPE = 1 ; // 38 bytes == 152 dbits + +//parameter int pN = 56 ; + parameter int pN = 152; + + parameter int pNiter = 8; + + parameter int pODAT_W = 2; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + real cCODE_RATE [] = '{ 1.0/3, + 1.0/2, 2.0/3, 3.0/4, 4.0/5, 5.0/6, 6.0/7, 7.0/8}; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + logic iclk ; + logic ireset ; + logic iclkena ; + // + logic enc__isop ; + logic enc__ieop ; + logic enc__ival ; + logic [1 : 0] enc__idat ; + // + logic enc__obusy ; + logic enc__ordy ; + // + bit enc__idbsclk ; + + logic enc__osop ; + logic enc__oeop ; + logic enc__oeof ; + logic enc__oval ; + logic [1 : 0] enc__odat ; + + logic [3 : 0] iqam; + + bit dec__isop ; + bit dec__ieop ; + bit dec__ieof ; + bit dec__ival ; + + logic dec__obusy ; + logic dec__ordy ; + + logic dec__osop ; + logic dec__oeop ; + logic dec__oval ; + logic [1 : 0] dec__odat ; + logic [15 : 0] dec__oerr ; + + //------------------------------------------------------------------------------------------------------ + // encoder + //------------------------------------------------------------------------------------------------------ + + rsc2_enc + #( + .pN_MAX ( pN ) + ) + enc + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .icode ( pCODE ) , + .iptype ( pPTYPE ) , + // + .itag ( '0 ) , + .isop ( enc__isop ) , + .ieop ( enc__ieop ) , + .ival ( enc__ival ) , + .idat ( enc__idat ) , + // + .obusy ( enc__obusy ) , + .ordy ( enc__ordy ) , + // + .idbsclk ( enc__idbsclk ) , + .ofull ( ) , + // + .otag ( ) , + .osop ( enc__osop ) , + .oeop ( enc__oeop ) , + .oeof ( enc__oeof ) , + .oval ( enc__oval ) , + .odat ( enc__odat ) + ); + + assign enc__idbsclk = 1'b1; + + //------------------------------------------------------------------------------------------------------ + // QPSK mapper. + // 00 = -1 - 1i + // 01 = -1 + 1i + // 10 = 1 - 1i + // 11 = 1 + 1i + //------------------------------------------------------------------------------------------------------ + + const real cQPSK_POW = 2.0; + + bit map_val; + bit map_sop; + bit map_eop; + cmplx_real_dat_t map_dat; + + always_ff @(posedge iclk) begin + map_sop <= enc__osop; + map_val <= enc__oval; + map_eop <= enc__oeof; + map_dat.re <= enc__odat[0] ? 1 : -1; + map_dat.im <= enc__odat[1] ? 1 : -1; + end + + //------------------------------------------------------------------------------------------------------ + // awgn channel + //------------------------------------------------------------------------------------------------------ + + awgn_class awgn = new; + + cmplx_real_dat_t awgn_ch; + + const bit awgn_bypass = 0; + + always_ff @(posedge iclk) begin + dec__isop <= map_sop; + dec__ieop <= map_eop; + dec__ival <= map_val; + if (map_val) begin + awgn_ch <= awgn.add(map_dat, awgn_bypass); + end + end + + //------------------------------------------------------------------------------------------------------ + // scale data: set QPSK ref point to -+1024 point and saturate canstellation to -2047 : + 2047 point + //------------------------------------------------------------------------------------------------------ + + const int NGC_MAX = 2047; + const int NGC_REF = 1024; + + bit signed [15 : 0] ngc_dat_re; + bit signed [15 : 0] ngc_dat_im; + + always_comb begin + ngc_dat_re = $floor(awgn_ch.re * NGC_REF + 0.5); + ngc_dat_im = $floor(awgn_ch.im * NGC_REF + 0.5); + // saturate + if (ngc_dat_re > NGC_MAX) begin + ngc_dat_re = NGC_MAX; + end + else if (ngc_dat_re < -NGC_MAX) begin + ngc_dat_re = -NGC_MAX; + end + // + if (ngc_dat_im > NGC_MAX) begin + ngc_dat_im = NGC_MAX; + end + else if (ngc_dat_im < -NGC_MAX) begin + ngc_dat_im = -NGC_MAX; + end + end + + //------------------------------------------------------------------------------------------------------ + // cut off bits for decoder + // take 5bits {5.3} from ref point + //------------------------------------------------------------------------------------------------------ + +//localparam int cDAT_W = 4; // {4.2} + localparam int cDAT_W = 5; // {5.3} +//localparam int cDAT_W = 6; // {5.3} + + bit signed [cDAT_W-1 : 0] dat2llr_re; + bit signed [cDAT_W-1 : 0] dat2llr_im; + + always_comb begin + dat2llr_re = ngc_dat_re[11 : 12-cDAT_W]; + dat2llr_im = ngc_dat_im[11 : 12-cDAT_W]; + end + + //------------------------------------------------------------------------------------------------------ + // decoder + //------------------------------------------------------------------------------------------------------ + + logic dec__ireq; + logic dec__ofull; + + rsc2_dec + #( + .pLLR_W ( cDAT_W ) , + .pODAT_W ( pODAT_W ) , + .pN_MAX ( pN ) , + .pUSE_W_BIT ( 1 ) , + .pUSE_SRC_EOP_VAL_MASK ( 0 ) + ) + uut + ( + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .icode ( pCODE ) , + .iptype ( pPTYPE ) , + .iNiter ( pNiter ) , + // + .itag ( '0 ) , + .isop ( dec__isop ) , + .ieop ( dec__ieop ) , + .ival ( dec__ival ) , + // + .iLLR ( '{dat2llr_re, dat2llr_im} ) , + // + .obusy ( dec__obusy ) , + .ordy ( dec__ordy ) , + // + .ireq ( dec__ireq ) , + .ofull ( dec__ofull ) , + // + .osop ( dec__osop ) , + .oeop ( dec__oeop ) , + .oval ( dec__oval ) , + .odat ( dec__odat ) , + .otag ( ) , // n.u. + // + .oerr ( dec__oerr ) + ); + + assign dec__ireq = 1'b1; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + initial begin + iclk <= 1'b0; + #5ns forever #5ns iclk = ~iclk; + end + + initial begin + ireset = 1'b1; + repeat (2) @(negedge iclk); + ireset = 1'b0; + end + + assign iclkena = 1'b1; + + assign iqam = 2; + + //------------------------------------------------------------------------------------------------------ + // tb settings + //------------------------------------------------------------------------------------------------------ +`ifdef __DIRECT_MODE__ + const int Npkt = 1; + real EbNo [] = '{2.5}; +`else +//const int Npkt = 4; +//const int Npkt = 128; +//const int Npkt = 1024; + + const int B = 1e5; + const int Npkt = B/(pN*2); + +//real EbNo [] = '{5.0}; +//real EbNo [] = '{0.0}; + real EbNo [] = '{1.0, 1.5, 2.0, 2.5, 3.0}; +//real EbNo [] = '{1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0} ; +//real EbNo [] = '{0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5}; +//real EbNo [] = '{0.5, 1.0, 1.5, 2.0, 2.5, 3.0}; +//real EbNo [] = '{1.0, 2.0, 3.0, 4.0, 5.0, 6.0}; +//real EbNo [] = '{0.5, 0.75, 1.0, 1.25, 1.5, 1.75}; +`endif + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + pkt_class #(2) code_queue [$]; + + initial begin + pkt_class #(2) code; + // + code_queue.delete(); + // + enc__isop <= '0; + enc__ieop <= '0; + enc__ival <= '0; + enc__idat <= '0; + // + awgn.init_EbNo(.EbNo(EbNo[0]), .bps(2), .coderate(1.0), .Ps(cQPSK_POW), .seed(0)); + // + $display("Test modulation %0d bps", iqam); + // + @(posedge iclk iff !ireset); + + foreach (EbNo[k]) begin + // + repeat (10) @(posedge iclk); + awgn.init_EbNo(.EbNo(EbNo[k]), .bps(2), .coderate(cCODE_RATE[pCODE]), .Ps(cQPSK_POW), .seed(2)); + awgn.log(); + void'(awgn.add('{0, 0}, 0)); + repeat (10) @(posedge iclk); + // + @(posedge iclk iff enc__ordy); + // + for (int n = 0; n < Npkt; n++) begin + // generate data + code = new(pN); + void'(code.randomize()); + // drive data + for (int i = 0; i < pN; i++) begin + enc__ival <= 1'b1; + enc__isop <= (i == 0); + enc__ieop <= (i == (pN-1)); + enc__idat <= code.dat[i]; + @(posedge iclk); + end + enc__ival <= 1'b0; + // save reference + code_queue.push_back(code); + // wait all modules free + @(posedge iclk iff !enc__obusy); + repeat (16) @(posedge iclk); // true hack + @(posedge iclk iff dec__ordy); + // + if ((n % 32) == 0) begin + $display("sent %0d packets", n); + end + end + end + end + + int numerr []; + int est_numerr []; + + initial begin + pkt_class #(2) decode; + pkt_class #(2) code; + int addr; + int err; + int n; + int bits; + string s; + // + numerr = new[EbNo.size()]; + est_numerr = new[EbNo.size()]; + foreach (numerr[k]) begin + numerr[k] = 0; + est_numerr[k] = 0; + end + decode = new(pN); + // + bits = 2*pN*Npkt; + // + foreach (EbNo[k]) begin + n = 0; + // + do begin + @(posedge iclk); + if (dec__oval) begin + if (dec__osop) addr = 0; + // + for (int i = 0; i < pODAT_W; i += 2) begin + decode.dat[addr] = dec__odat[i +: 2]; + addr++; + end + // + if (dec__oeop) begin + n++; + code = code_queue.pop_front(); + err = code.do_compare(decode); + numerr[k] += err; + est_numerr[k] += dec__oerr; + // + if ((n % 32) == 0) begin + $display("decode done %0d. err = %0d, est err %0d", n, numerr[k], est_numerr[k]); + end + end + end + end + while (n < Npkt); + $display("decode EbN0 = %0f done. ber = %0e, fer = %0e", EbNo[k], numerr[k]*1.0/bits, est_numerr[k]*1.0/bits); + // + end + for (int k = 0; k < EbNo.size(); k++) begin + $display("bits %0d EbNo = %f: ber = %0e. fer = %0e", bits, EbNo[k], numerr[k]*1.0/bits, est_numerr[k]*1.0/bits); + end + $stop; + end + +endmodule + +