diff --git a/README.md b/README.md index fcf93f5..79e537b 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ The library contain: 7. 3GPP LDPC code 8. 3GPP Polar code 9. Soft decision Golay code -10. DVB-S LDPC code +10. DVB-S2 LDPC code 11. CCSDS Turbo code 12. 4D-8PSK TCM code 13. Hamming code diff --git a/rtl/ldpc_dvb/README.md b/rtl/ldpc_dvb/README.md index bdab186..890b7c5 100644 --- a/rtl/ldpc_dvb/README.md +++ b/rtl/ldpc_dvb/README.md @@ -20,14 +20,14 @@ Decoder settings : coderate = 1/2, block length = 64800 bits, 8 LLR/bits per tic pNODE_W = 6 bits (optimal codegain for 4 bit LLR) -Decoder : LUT/REG/RAMB 56k/69k/133.5 iface >250MHz, core >250MHz (480Mbps -> 240Mbps) +Decoder : LUT/REG/RAMB 59k/63k/97.5 iface >250MHz, core >250MHz (480Mbps -> 240Mbps) pNODE_W = 5 bits (good codegain for 4 bit LLR) -Decoder : LUT/REG/RAMB 47k/61k/118.5 iface >250MHz, core >250MHz (480Mbps -> 240Mbps) +Decoder : LUT/REG/RAMB 49k/55k/87.5 iface >250MHz, core >250MHz (480Mbps -> 240Mbps) pNODE_W = 4 bits (worst codegain for 4 bit LLR) -Decoder : LUT/REG/RAMB 38k/53k/103.5 iface >250MHz, core >250MHz (480Mbps -> 240Mbps) +Decoder : LUT/REG/RAMB 40k/48k/77.5 iface >250MHz, core >250MHz (480Mbps -> 240Mbps) Attention: The coder and decoder correspond each other but can have different bit order with standard codes. Strongly speaking it's not DVB-S2 codec, because there is no parity bits reorder inside. It should be done external of codec during bit interleaving procedure !!! diff --git a/rtl/ldpc_dvb/dec/ldpc_dvb_dec_2d_engine.sv b/rtl/ldpc_dvb/dec/ldpc_dvb_dec_2d_engine.sv index 5adc07f..67d6bef 100644 --- a/rtl/ldpc_dvb/dec/ldpc_dvb_dec_2d_engine.sv +++ b/rtl/ldpc_dvb/dec/ldpc_dvb_dec_2d_engine.sv @@ -2,21 +2,25 @@ - parameter int pLLR_W = 8 ; - parameter int pNODE_W = 8 ; + parameter int pLLR_W = 8 ; + parameter int pNODE_W = 8 ; // - parameter int pRADDR_W = 8 ; - parameter int pWADDR_W = 8 ; + parameter int pRADDR_W = 8 ; + parameter int pWADDR_W = 8 ; + // + parameter int pTAG_W = 4 ; // - parameter int pTAG_W = 4 ; + parameter int pERR_W = 16 ; // - parameter int pERR_W = 16 ; + parameter bit pCODEGR = 1 ; // - parameter int pCNORM_FACTOR = 6 ; + parameter int pCNORM_FACTOR = 6 ; // - parameter bit pUSE_SC_MODE = 1 ; + parameter bit pDO_LLR_INVERSION = 1 ; + parameter bit pUSE_SRL_FIFO = 1 ; + parameter bit pUSE_SC_MODE = 1 ; // - parameter bit pFIX_MODE = 1 ; + parameter bit pFIX_MODE = 1 ; @@ -63,9 +67,11 @@ // .pERR_W ( pERR_W ) , // + .pCODEGR ( pCODEGR ) , .pCNORM_FACTOR ( pCNORM_FACTOR ) , // .pDO_LLR_INVERSION ( pDO_LLR_INVERSION ) , + .pUSE_SRL_FIFO ( pUSE_SRL_FIFO ) , .pUSE_SC_MODE ( pUSE_SC_MODE ) , // .pFIX_MODE ( pFIX_MODE ) @@ -166,15 +172,19 @@ module ldpc_dvb_dec_2d_engine // parameter int pERR_W = 16 ; // - parameter int pCNORM_FACTOR = 6 ; + parameter int pCNORM_FACTOR = 7 ; // horizontal step normalization factor + + parameter bit pDO_LLR_INVERSION = 1 ; // do metric inversion inside decoder - parameter bit pDO_LLR_INVERSION = 0 ; + parameter bit pUSE_SRL_FIFO = 1 ; // use SRL based internal FIFO // - parameter int pFIX_MODE = 0 ; + parameter int pFIX_MODE = 0 ; // fix mode decoder `include "../ldpc_dvb_constants.svh" `include "ldpc_dvb_dec_types.svh" + parameter bit pCODEGR = cCODEGR_LARGE ; // maximum used graph short(0)/large(1) + //------------------------------------------------------------------------------------------------------ // //------------------------------------------------------------------------------------------------------ @@ -212,10 +222,10 @@ module ldpc_dvb_dec_2d_engine // //------------------------------------------------------------------------------------------------------ - localparam int cNODE_RAM_ADDR_W = cHS_CYCLE_W ; + localparam int cNODE_RAM_ADDR_W = pCODEGR ? cHS_CYCLE_W : cHS_SHORT_CYCLE_W; localparam int cNODE_RAM_DAT_W = pNODE_W * cZC_MAX; - localparam int cSTATE_RAM_ADDR_W = cHS_CYCLE_W ; + localparam int cSTATE_RAM_ADDR_W = cNODE_RAM_ADDR_W ; localparam int cSTATE_RAM_DAT_W = (1 + (pUSE_SC_MODE ? $bits(node_state_t) : 0)) * cZC_MAX; // +1 for syndrome decision //------------------------------------------------------------------------------------------------------ @@ -337,6 +347,8 @@ module ldpc_dvb_dec_2d_engine zdat_t vnode__obitdat ; zdat_t vnode__obiterr ; col_t vnode__obitaddr ; + // + logic vnode__obusy ; //------------------------------------------------------------------------------------------------------ // Hs "generator" @@ -519,9 +531,9 @@ module ldpc_dvb_dec_2d_engine assign ctrl__iused_row = hs_gen__oused_row; assign ctrl__icycle_max_num = hs_gen__ocycle_max_num; - assign ctrl__ivnode_busy = (ctrl__ocycle_read | vnode__ovnode_val); + assign ctrl__ivnode_busy = (ctrl__ocycle_read | vnode__obusy); - assign ctrl__icnode_busy = (ctrl__ocycle_read | cnode__ocnode_val); + assign ctrl__icnode_busy = (ctrl__ocycle_read | cnode__obusy); assign ctrl__icnode_decfail = cnode__odecfail; //------------------------------------------------------------------------------------------------------ @@ -551,7 +563,7 @@ module ldpc_dvb_dec_2d_engine .ordat ( node_ram__ordat ) ); - assign node_ram__iraddr = hs_gen__ocycle_node_raddr; + assign node_ram__iraddr = hs_gen__ocycle_node_raddr[cNODE_RAM_ADDR_W-1 : 0]; always_comb begin for (int z = 0; z < cZC_MAX; z++) begin @@ -563,15 +575,15 @@ module ldpc_dvb_dec_2d_engine always_ff @(posedge iclk) begin if (iclkena) begin - if (ctrl__oc_nv_mode) begin - node_ram__iwrite <= cnode__ocnode_val ; - node_ram__iwaddr <= cnode__ocnode_addr ; - node_ram_wdat <= cnode__ocnode ; + node_ram__iwrite <= cnode__ocnode_val | vnode__ovnode_val; + // + if (cnode__ocnode_val) begin + node_ram__iwaddr <= cnode__ocnode_addr[cNODE_RAM_ADDR_W-1 : 0]; + node_ram_wdat <= cnode__ocnode; end else begin - node_ram__iwrite <= vnode__ovnode_val ; - node_ram__iwaddr <= vnode__ovnode_addr ; - node_ram_wdat <= vnode__ovnode ; + node_ram__iwaddr <= vnode__ovnode_addr[cNODE_RAM_ADDR_W-1 : 0]; + node_ram_wdat <= vnode__ovnode; end end end @@ -603,12 +615,12 @@ module ldpc_dvb_dec_2d_engine .ordat ( state_ram__ordat ) ); - assign state_ram__iraddr = hs_gen__ocycle_node_raddr; + assign state_ram__iraddr = hs_gen__ocycle_node_raddr[cSTATE_RAM_ADDR_W-1 : 0]; always_ff @(posedge iclk) begin if (iclkena) begin state_ram__iwrite <= vnode__ovnode_val; - state_ram__iwaddr <= vnode__ovnode_addr; + state_ram__iwaddr <= vnode__ovnode_addr[cSTATE_RAM_ADDR_W-1 : 0]; if (pUSE_SC_MODE) begin state_ram__iwdat[cSTATE_RAM_DAT_W-1 -: cZC_MAX] <= vnode__ovnode_hd; // @@ -642,9 +654,12 @@ module ldpc_dvb_dec_2d_engine ldpc_dvb_dec_cnode #( - .pLLR_W ( pLLR_W ) , - .pNODE_W ( pNODE_W ) , - .pNORM_FACTOR ( pCNORM_FACTOR ) + .pLLR_W ( pLLR_W ) , + .pNODE_W ( pNODE_W ) , + // + .pNORM_FACTOR ( pCNORM_FACTOR ) , + // + .pUSE_SRL_FIFO ( pUSE_SRL_FIFO ) ) cnode ( @@ -691,7 +706,9 @@ module ldpc_dvb_dec_2d_engine .pNODE_W ( pNODE_W ) , // .pUSE_SC_MODE ( pUSE_SC_MODE ) , - .pDO_LLR_INVERSION ( pDO_LLR_INVERSION ) + .pDO_LLR_INVERSION ( pDO_LLR_INVERSION ) , + // + .pUSE_SRL_FIFO ( pUSE_SRL_FIFO ) ) vnode ( @@ -720,7 +737,9 @@ module ldpc_dvb_dec_2d_engine .obiteop ( vnode__obiteop ) , .obitdat ( vnode__obitdat ) , .obiterr ( vnode__obiterr ) , - .obitaddr ( vnode__obitaddr ) + .obitaddr ( vnode__obitaddr ) , + // + .obusy ( vnode__obusy ) ); assign vnode__istart = ctrl__ocycle_start;// & !ctrl__oc_nv_mode; diff --git a/rtl/ldpc_dvb/dec/ldpc_dvb_dec_cnode.sv b/rtl/ldpc_dvb/dec/ldpc_dvb_dec_cnode.sv index 689d0e2..b7767a1 100644 --- a/rtl/ldpc_dvb/dec/ldpc_dvb_dec_cnode.sv +++ b/rtl/ldpc_dvb/dec/ldpc_dvb_dec_cnode.sv @@ -2,9 +2,10 @@ - parameter int pLLR_W = 4 ; - parameter int pNODE_W = 8 ; - parameter int pNORM_FACTOR = 6 ; + parameter int pLLR_W = 4 ; + parameter int pNODE_W = 8 ; + parameter int pNORM_FACTOR = 6 ; + parameter bit pUSE_SRL_FIFO = 1 ; @@ -33,9 +34,10 @@ ldpc_dvb_dec_cnode #( - .pLLR_W ( pLLR_W ) , - .pNODE_W ( pNODE_W ) , - .pNORM_FACTOR ( pNORM_FACTOR ) + .pLLR_W ( pLLR_W ) , + .pNODE_W ( pNODE_W ) , + .pNORM_FACTOR ( pNORM_FACTOR ) , + .pUSE_SRL_FIFO ( pUSE_SRL_FIFO ) ) ldpc_dvb_dec_cnode ( @@ -110,7 +112,8 @@ module ldpc_dvb_dec_cnode obusy ); - parameter int pNORM_FACTOR = 7; + parameter int pNORM_FACTOR = 7; + parameter bit pUSE_SRL_FIFO = 1; // use SRL based internal FIFO `include "../ldpc_dvb_constants.svh" `include "ldpc_dvb_dec_types.svh" @@ -168,21 +171,24 @@ module ldpc_dvb_dec_cnode logic signed [cIBS_NODE_W-1 : 0] ibs__odat [cZC_MAX]; // // sort unit - zdat_t sort__istart ; + zdat_t sort__istart ; // - zdat_t sort__ival ; - strb_t sort__istrb [cZC_MAX]; - node_t sort__ivnode [cZC_MAX]; - zdat_t sort__ivmask ; + zdat_t sort__ival ; + strb_t sort__istrb [cZC_MAX]; + node_t sort__ivnode [cZC_MAX]; + zdat_t sort__ivmask ; // - zdat_t sort__osort_val ; - vn_min_t sort__osort_rslt [cZC_MAX]; - vn_min_col_t sort__osort_num_m1 [cZC_MAX]; + zdat_t sort__osort_val ; + vn_min_t sort__osort_rslt [cZC_MAX]; + vn_min_col_t sort__osort_num_m1 [cZC_MAX]; // - zdat_t sort__osort_pre_val ; - vn_min_col_t sort__osort_pre_num_m1 [cZC_MAX]; + zdat_t sort__osort_b1_pre_val ; + vn_min_col_t sort__osort_b1_pre_num_m1 [cZC_MAX]; // - zdat_t sort__odecfail ; + zdat_t sort__osort_b2_pre_val ; + vn_min_col_t sort__osort_b2_pre_num_m1 [cZC_MAX]; + // + zdat_t sort__odecfail ; // // syndrome counter logic syndrome__istart ; @@ -201,6 +207,7 @@ module ldpc_dvb_dec_cnode logic [cVNODE_FIFO_DAT_W-1 : 0] vnode_fifo__iwdat ; // logic vnode_fifo__iread ; + logic vnode_fifo__orval ; logic [cVNODE_FIFO_DAT_W-1 : 0] vnode_fifo__ordat ; // logic vnode_fifo__oempty ; @@ -312,25 +319,28 @@ module ldpc_dvb_dec_cnode ) sort ( - .iclk ( iclk ) , - .ireset ( ireset ) , - .iclkena ( iclkena ) , + .iclk ( iclk ) , + .ireset ( ireset ) , + .iclkena ( iclkena ) , + // + .istart ( sort__istart [g] ) , // - .istart ( sort__istart [g] ) , + .ival ( sort__ival [g] ) , + .istrb ( sort__istrb [g] ) , + .ivnode ( sort__ivnode [g] ) , + .ivmask ( sort__ivmask [g] ) , // - .ival ( sort__ival [g] ) , - .istrb ( sort__istrb [g] ) , - .ivnode ( sort__ivnode [g] ) , - .ivmask ( sort__ivmask [g] ) , + .osort_val ( sort__osort_val [g] ) , + .osort_rslt ( sort__osort_rslt [g] ) , + .osort_num_m1 ( sort__osort_num_m1 [g] ) , // - .osort_val ( sort__osort_val [g] ) , - .osort_rslt ( sort__osort_rslt [g] ) , - .osort_num_m1 ( sort__osort_num_m1 [g] ) , + .osort_b1_pre_val ( sort__osort_b1_pre_val [g] ) , + .osort_b1_pre_num_m1 ( sort__osort_b1_pre_num_m1 [g] ) , // - .osort_pre_val ( sort__osort_pre_val [g] ) , - .osort_pre_num_m1 ( sort__osort_pre_num_m1 [g] ) , + .osort_b2_pre_val ( sort__osort_b2_pre_val [g] ) , + .osort_b2_pre_num_m1 ( sort__osort_b2_pre_num_m1 [g] ) , // - .odecfail ( sort__odecfail [g] ) + .odecfail ( sort__odecfail [g] ) ); assign sort__istart [g] = istart; @@ -386,31 +396,61 @@ module ldpc_dvb_dec_cnode end //------------------------------------------------------------------------------------------------------ - // vnode dynamic align line : save vnode sign and vnode context + // vnode dynamic align line : save vnode sign and vnode context (1 tick delay) //------------------------------------------------------------------------------------------------------ - ldpc_dvb_dec_fifo - #( - .pDEPTH_W ( cVNODE_FIFO_DEPTH_W ) , - .pDAT_W ( cVNODE_FIFO_DAT_W ) - ) - vnode_fifo - ( - .iclk ( iclk ) , - .ireset ( 1'b0 ) , // don'n need because there is iclear used - .iclkena ( iclkena ) , - // - .iclear ( vnode_fifo__iclear ) , - // - .iwrite ( vnode_fifo__iwrite ) , - .iwdat ( vnode_fifo__iwdat ) , - // - .iread ( vnode_fifo__iread ) , - .ordat ( vnode_fifo__ordat ) , - // - .oempty ( vnode_fifo__oempty ) , - .ofull ( vnode_fifo__ofull ) - ); + generate + if (pUSE_SRL_FIFO) begin + ldpc_dvb_dec_srl_fifo + #( + .pDEPTH_W ( cVNODE_FIFO_DEPTH_W ) , + .pDAT_W ( cVNODE_FIFO_DAT_W ) + ) + vnode_fifo + ( + .iclk ( iclk ) , + .ireset ( 1'b0 ) , // don'n need because there is iclear used + .iclkena ( iclkena ) , + // + .iclear ( vnode_fifo__iclear ) , + // + .iwrite ( vnode_fifo__iwrite ) , + .iwdat ( vnode_fifo__iwdat ) , + // + .iread ( vnode_fifo__iread ) , + .orval ( vnode_fifo__orval ) , + .ordat ( vnode_fifo__ordat ) , + // + .oempty ( vnode_fifo__oempty ) , + .ofull ( vnode_fifo__ofull ) + ); + end + else begin + ldpc_dvb_dec_fifo + #( + .pDEPTH_W ( cVNODE_FIFO_DEPTH_W ) , + .pDAT_W ( cVNODE_FIFO_DAT_W ) + ) + vnode_fifo + ( + .iclk ( iclk ) , + .ireset ( 1'b0 ) , // don'n need because there is iclear used + .iclkena ( iclkena ) , + // + .iclear ( vnode_fifo__iclear ) , + // + .iwrite ( vnode_fifo__iwrite ) , + .iwdat ( vnode_fifo__iwdat ) , + // + .iread ( vnode_fifo__iread ) , + .orval ( vnode_fifo__orval ) , + .ordat ( vnode_fifo__ordat ) , + // + .oempty ( vnode_fifo__oempty ) , + .ofull ( vnode_fifo__ofull ) + ); + end + endgenerate assign vnode_fifo__iclear = istart; @@ -424,7 +464,10 @@ module ldpc_dvb_dec_cnode end end - assign vnode_fifo__iread = ctrl__oread; + // + // any FIFO version use look ahead reading but with different tick offset + // + assign vnode_fifo__iread = ctrl__oread | ctrl__irdy; // look ahead reading //------------------------------------------------------------------------------------------------------ // cnode generator ctrl @@ -447,8 +490,19 @@ module ldpc_dvb_dec_cnode .oread_idx ( ctrl__oread_idx ) ); - assign ctrl__irdy = sort__osort_pre_val [0]; - assign ctrl__inum_m1 = sort__osort_pre_num_m1 [0]; + // + // RAMB fifo read 2 tick before result, SRL fifo read 1 tick before result + // + generate + if (pUSE_SRL_FIFO) begin + assign ctrl__irdy = sort__osort_b1_pre_val [0] ; + assign ctrl__inum_m1 = sort__osort_b1_pre_num_m1 [0] - 1'b1; // do -1 offset because use look ahead reading + end + else begin + assign ctrl__irdy = sort__osort_b2_pre_val [0] ; + assign ctrl__inum_m1 = sort__osort_b2_pre_num_m1 [0] - 1'b1; // do -1 offset because use look ahead reading + end + endgenerate //------------------------------------------------------------------------------------------------------ // cnode generator @@ -482,23 +536,45 @@ module ldpc_dvb_dec_cnode .ocnode ( restore__ocnode [g] ) ); - assign restore__ivnode_mask [g] = (g == 0); // mask_0_bit is insode restore unit + assign restore__ivnode_mask [g] = (g == 0); // mask_0_bit is inside restore unit + + if (pUSE_SRL_FIFO) begin + + assign restore__ival [g] = vnode_fifo__orval ; + + assign restore__ivnode_idx [g] = ctrl__oread_idx ; + + assign restore__ivn_min [g] = sort__osort_rslt[g]; // decision holded for all cycle + + // + // srl fifo has 1 tick delay + assign restore__icnode_ctx [g] = vnode_fifo__ordat[cVNODE_FIFO_DAT_W-1 -: cNODE_TAG_W]; + assign restore__ivnode_sign [g] = vnode_fifo__ordat[g]; + + end + else begin + + always_ff @(posedge iclk) begin + if (iclkena) begin + restore__ival [g] <= vnode_fifo__orval ; + + restore__ivnode_idx [g] <= ctrl__oread_idx ; + end + end + + assign restore__ivn_min [g] = sort__osort_rslt[g]; // decision holded for all cycle - // - // - always_ff @(posedge iclk) begin - if (iclkena) begin - restore__ival [g] <= ctrl__oread ; - restore__ivnode_idx [g] <= ctrl__oread_idx ; - // - restore__ivn_min [g] <= sort__osort_rslt[g]; // decision holded for all cycle + // + // add + 1 tick delay to FIFO + always_ff @(posedge iclk) begin + if (iclkena) begin + restore__icnode_ctx [g] <= vnode_fifo__ordat[cVNODE_FIFO_DAT_W-1 -: cNODE_TAG_W]; + restore__ivnode_sign [g] <= vnode_fifo__ordat[g]; + end end + end - // - // srl fifo has 1 tick delay - assign restore__icnode_ctx [g] = vnode_fifo__ordat[cVNODE_FIFO_DAT_W-1 -: cNODE_TAG_W]; - assign restore__ivnode_sign [g] = vnode_fifo__ordat[g]; end endgenerate @@ -543,4 +619,19 @@ module ldpc_dvb_dec_cnode end end + //------------------------------------------------------------------------------------------------------ + // obusy is look ahead signal for control + // there is 4 tick betwen write/read to node ram + // this logic save 2 tick for cBS_DELAY == 3 (!!!) for each iteration + //------------------------------------------------------------------------------------------------------ + + always_ff @(posedge iclk or posedge ireset) begin + if (ireset) begin + obusy <= 1'b0; + end + else if (iclkena) begin + obusy <= obs__ival | !vnode_fifo__oempty; // fifo_empty use because there can be holes in oval flow (!!!) + end + end + endmodule diff --git a/rtl/ldpc_dvb/dec/ldpc_dvb_dec_fifo.sv b/rtl/ldpc_dvb/dec/ldpc_dvb_dec_fifo.sv index 88cca7a..9d35fb7 100644 --- a/rtl/ldpc_dvb/dec/ldpc_dvb_dec_fifo.sv +++ b/rtl/ldpc_dvb/dec/ldpc_dvb_dec_fifo.sv @@ -17,6 +17,7 @@ logic [pDAT_W-1 : 0] ldpc_dvb_dec_fifo__iwdat ; // logic ldpc_dvb_dec_fifo__iread ; + logic ldpc_dvb_dec_fifo__orval ; logic [pDAT_W-1 : 0] ldpc_dvb_dec_fifo__ordat ; // logic ldpc_dvb_dec_fifo__oempty ; @@ -41,6 +42,7 @@ .iwdat ( ldpc_dvb_dec_fifo__iwdat ) , // .iread ( ldpc_dvb_dec_fifo__iread ) , + .orval ( ldpc_dvb_dec_fifo__orval ) , .ordat ( ldpc_dvb_dec_fifo__ordat ) , // .oempty ( ldpc_dvb_dec_fifo__oempty ) , @@ -83,6 +85,7 @@ module ldpc_dvb_dec_fifo iwdat , // iread , + orval , ordat , // oempty , @@ -103,6 +106,7 @@ module ldpc_dvb_dec_fifo input logic [pDAT_W-1 : 0] iwdat ; // input logic iread ; + output logic orval ; output logic [pDAT_W-1 : 0] ordat ; // output logic oempty ; @@ -157,6 +161,15 @@ module ldpc_dvb_dec_fifo assign oempty = (cnt == 0); assign ofull = cnt[pDEPTH_W]; + always_ff @(posedge iclk or posedge ireset) begin + if (ireset) begin + orval <= 1'b0; + end + else if (iclkena) begin + orval <= read; + end + end + always_ff @(posedge iclk) begin if (iclkena) begin if (write) begin diff --git a/rtl/ldpc_dvb/dec/ldpc_dvb_dec_fix.sv b/rtl/ldpc_dvb/dec/ldpc_dvb_dec_fix.sv index 64e5251..9e460bb 100644 --- a/rtl/ldpc_dvb/dec/ldpc_dvb_dec_fix.sv +++ b/rtl/ldpc_dvb/dec/ldpc_dvb_dec_fix.sv @@ -18,6 +18,7 @@ parameter int pCNORM_FACTOR = 7 ; parameter bit pDO_TRANSPONSE = 0 ; parameter bit pDO_LLR_INVERSION = 1 ; + parameter bit pUSE_SRL_FIFO = 1 ; parameter bit pFULL_BITS_OUTPUT = 0 ; @@ -72,6 +73,7 @@ .pCNORM_FACTOR ( pCNORM_FACTOR ) , .pDO_TRANSPONSE ( pDO_TRANSPONSE ) , .pDO_LLR_INVERSION ( pDO_LLR_INVERSION ) , + .pUSE_SRL_FIFO ( pUSE_SRL_FIFO ) , .pFULL_BITS_OUTPUT ( pFULL_BITS_OUTPUT ) , .pUSE_SC_MODE ( pUSE_SC_MODE ) , ) @@ -174,6 +176,7 @@ module ldpc_dvb_dec_fix // parameter bit pDO_TRANSPONSE = 0 ; // do input transponse to be like DVB-S standart or not parameter bit pDO_LLR_INVERSION = 1 ; // do metric inversion or not + parameter bit pUSE_SRL_FIFO = 1 ; // use SRL based internal FIFO parameter bit pFULL_BITS_OUTPUT = 0 ; // send all(1)/data(0) bits to output // parameter int pERR_W = 16 ; @@ -500,9 +503,11 @@ module ldpc_dvb_dec_fix // .pERR_W ( pERR_W ) , // + .pCODEGR ( pCODEGR ) , .pCNORM_FACTOR ( pCNORM_FACTOR ) , // .pDO_LLR_INVERSION ( pDO_LLR_INVERSION ) , + .pUSE_SRL_FIFO ( pUSE_SRL_FIFO ) , .pUSE_SC_MODE ( pUSE_SC_MODE ) , // .pFIX_MODE ( 1 ) diff --git a/rtl/ldpc_dvb/dec/ldpc_dvb_dec_sort_engine.sv b/rtl/ldpc_dvb/dec/ldpc_dvb_dec_sort_engine.sv index a90e3ae..6218fb1 100644 --- a/rtl/ldpc_dvb/dec/ldpc_dvb_dec_sort_engine.sv +++ b/rtl/ldpc_dvb/dec/ldpc_dvb_dec_sort_engine.sv @@ -8,25 +8,28 @@ - logic ldpc_dvb_dec_sort_engine__iclk ; - logic ldpc_dvb_dec_sort_engine__ireset ; - logic ldpc_dvb_dec_sort_engine__iclkena ; + logic ldpc_dvb_dec_sort_engine__iclk ; + logic ldpc_dvb_dec_sort_engine__ireset ; + logic ldpc_dvb_dec_sort_engine__iclkena ; // - logic ldpc_dvb_dec_sort_engine__istart ; + logic ldpc_dvb_dec_sort_engine__istart ; // - logic ldpc_dvb_dec_sort_engine__ival ; - strb_t ldpc_dvb_dec_sort_engine__istrb ; - logic ldpc_dvb_dec_sort_engine__ivmask ; - node_t ldpc_dvb_dec_sort_engine__ivnode ; + logic ldpc_dvb_dec_sort_engine__ival ; + strb_t ldpc_dvb_dec_sort_engine__istrb ; + logic ldpc_dvb_dec_sort_engine__ivmask ; + node_t ldpc_dvb_dec_sort_engine__ivnode ; // - logic ldpc_dvb_dec_sort_engine__osort_val ; - vn_min_t ldpc_dvb_dec_sort_engine__osort_rslt ; - min_col_idx_t ldpc_dvb_dec_sort_engine__osort_num_m1 ; + logic ldpc_dvb_dec_sort_engine__osort_val ; + vn_min_t ldpc_dvb_dec_sort_engine__osort_rslt ; + min_col_idx_t ldpc_dvb_dec_sort_engine__osort_num_m1 ; // - logic ldpc_dvb_dec_sort_engine__osort_pre_val ; - min_col_idx_t ldpc_dvb_dec_sort_engine__osort_pre_num_m1 ; + logic ldpc_dvb_dec_sort_engine__osort_b1_pre_val ; + min_col_idx_t ldpc_dvb_dec_sort_engine__osort_b1_pre_num_m1 ; // - logic ldpc_dvb_dec_sort_engine__odecfail ; + logic ldpc_dvb_dec_sort_engine__osort_b2_pre_val ; + min_col_idx_t ldpc_dvb_dec_sort_engine__osort_b2_pre_num_m1 ; + // + logic ldpc_dvb_dec_sort_engine__odecfail ; @@ -38,25 +41,28 @@ ) ldpc_dvb_dec_sort_engine ( - .iclk ( ldpc_dvb_dec_sort_engine__iclk ) , - .ireset ( ldpc_dvb_dec_sort_engine__ireset ) , - .iclkena ( ldpc_dvb_dec_sort_engine__iclkena ) , + .iclk ( ldpc_dvb_dec_sort_engine__iclk ) , + .ireset ( ldpc_dvb_dec_sort_engine__ireset ) , + .iclkena ( ldpc_dvb_dec_sort_engine__iclkena ) , + // + .istart ( ldpc_dvb_dec_sort_engine__istart ) , // - .istart ( ldpc_dvb_dec_sort_engine__istart ) , + .ival ( ldpc_dvb_dec_sort_engine__ival ) , + .istrb ( ldpc_dvb_dec_sort_engine__istrb ) , + .ivmask ( ldpc_dvb_dec_sort_engine__ivmask ) , + .ivnode ( ldpc_dvb_dec_sort_engine__ivnode ) , // - .ival ( ldpc_dvb_dec_sort_engine__ival ) , - .istrb ( ldpc_dvb_dec_sort_engine__istrb ) , - .ivmask ( ldpc_dvb_dec_sort_engine__ivmask ) , - .ivnode ( ldpc_dvb_dec_sort_engine__ivnode ) , + .osort_val ( ldpc_dvb_dec_sort_engine__osort_val ) , + .osort_rslt ( ldpc_dvb_dec_sort_engine__osort_rslt ) , + .osort_num_m1 ( ldpc_dvb_dec_sort_engine__osort_num_m1 ) , // - .osort_val ( ldpc_dvb_dec_sort_engine__osort_val ) , - .osort_rslt ( ldpc_dvb_dec_sort_engine__osort_rslt ) , - .osort_num_m1 ( ldpc_dvb_dec_sort_engine__osort_num_m1 ) , + .osort_b1_pre_val ( ldpc_dvb_dec_sort_engine__osort_b1_pre_val ) , + .osort_b1_pre_num_m1 ( ldpc_dvb_dec_sort_engine__osort_b1_pre_num_m1 ) , // - .osort_pre_val ( ldpc_dvb_dec_sort_engine__osort_pre_val ) , - .osort_pre_num_m1 ( ldpc_dvb_dec_sort_engine__osort_pre_num_m1 ) , + .osort_b2_pre_val ( ldpc_dvb_dec_sort_engine__osort_b2_pre_val ) , + .osort_b2_pre_num_m1 ( ldpc_dvb_dec_sort_engine__osort_b2_pre_num_m1 ) , // - .odecfail ( ldpc_dvb_dec_sort_engine__odecfail ) + .odecfail ( ldpc_dvb_dec_sort_engine__odecfail ) ); @@ -83,22 +89,25 @@ module ldpc_dvb_dec_sort_engine ( iclk , - ireset , - iclkena , + ireset , + iclkena , // - istart , + istart , // - ival , - istrb , - ivmask , - ivnode , + ival , + istrb , + ivmask , + ivnode , // - osort_val , - osort_rslt , - osort_num_m1 , + osort_val , + osort_rslt , + osort_num_m1 , // - osort_pre_val , - osort_pre_num_m1 , + osort_b1_pre_val , + osort_b1_pre_num_m1 , + // + osort_b2_pre_val , + osort_b2_pre_num_m1 , // odecfail ); @@ -112,38 +121,42 @@ module ldpc_dvb_dec_sort_engine // //------------------------------------------------------------------------------------------------------ - input logic iclk ; - input logic ireset ; - input logic iclkena ; + input logic iclk ; + input logic ireset ; + input logic iclkena ; + // + input logic istart ; // - input logic istart ; + input logic ival ; + input strb_t istrb ; + input logic ivmask ; + input node_t ivnode ; // - input logic ival ; - input strb_t istrb ; - input logic ivmask ; - input node_t ivnode ; + output logic osort_val ; + output vn_min_t osort_rslt ; + output vn_min_col_t osort_num_m1 ; // - output logic osort_val ; - output vn_min_t osort_rslt ; - output vn_min_col_t osort_num_m1 ; + output logic osort_b1_pre_val ; // look ahead decision (before 1 tick) + output vn_min_col_t osort_b1_pre_num_m1 ; // - output logic osort_pre_val ; // look ahead decision (-1 tick) - output vn_min_col_t osort_pre_num_m1 ; + output logic osort_b2_pre_val ; // look ahead decision (before 2 tick) + output vn_min_col_t osort_b2_pre_num_m1 ; // - output logic odecfail ; + output logic odecfail ; //------------------------------------------------------------------------------------------------------ // //------------------------------------------------------------------------------------------------------ - logic val ; - strb_t strb ; + logic val ; + strb_t strb ; - logic pmask ; + logic pmask ; - vn_min_col_t vnode_col ; - logic sign_vnode ; - vnode_t abs_vnode ; + logic vnode_done; + vn_min_col_t vnode_col; + logic sign_vnode; + vnode_t abs_vnode; logic vn_sort_done; logic vn_sort_pmask; @@ -156,10 +169,12 @@ module ldpc_dvb_dec_sort_engine always_ff @(posedge iclk or posedge ireset) begin if (ireset) begin - val <= 1'b0; + val <= 1'b0; + vnode_done <= 1'b0; end else if (iclkena) begin - val <= ival; + val <= ival; + vnode_done <= ival & istrb.eop; end end @@ -191,7 +206,7 @@ module ldpc_dvb_dec_sort_engine vn_sort_done <= 1'b0; end else if (iclkena) begin - vn_sort_done <= val & strb.eop; + vn_sort_done <= vnode_done; end end @@ -245,7 +260,7 @@ module ldpc_dvb_dec_sort_engine odecfail <= 1'b0; end else if (vn_sort_done) begin - odecfail <= odecfail | vn_sort.prod_sign | !vn_sort_leq1; + odecfail <= odecfail | vn_sort.prod_sign | vn_sort_leq1; end // if (vn_sort_done) begin @@ -257,9 +272,17 @@ module ldpc_dvb_dec_sort_engine end end - // look ahead signals to save resources - assign osort_pre_val = vn_sort_done; - assign osort_pre_num_m1 = vn_sort_num_m1; + //------------------------------------------------------------------------------------------------------ + // look ahead signals + //------------------------------------------------------------------------------------------------------ + + // before 2 tick of osort val signal + assign osort_b2_pre_val = vnode_done; + assign osort_b2_pre_num_m1 = vnode_col; + + // before 1 tick of osort_val signal + assign osort_b1_pre_val = vn_sort_done; + assign osort_b1_pre_num_m1 = vn_sort_num_m1; //------------------------------------------------------------------------------------------------------ // used functions diff --git a/rtl/ldpc_dvb/dec/ldpc_dvb_dec_srl_fifo.sv b/rtl/ldpc_dvb/dec/ldpc_dvb_dec_srl_fifo.sv new file mode 100644 index 0000000..6a4d23e --- /dev/null +++ b/rtl/ldpc_dvb/dec/ldpc_dvb_dec_srl_fifo.sv @@ -0,0 +1,192 @@ +/* + + + + parameter int pDEPTH_W = 8 ; + parameter int pDAT_W = 8 ; + + + + logic ldpc_dvb_dec_srl_fifo__iclk ; + logic ldpc_dvb_dec_srl_fifo__ireset ; + logic ldpc_dvb_dec_srl_fifo__iclkena ; + // + logic ldpc_dvb_dec_srl_fifo__iclear ; + // + logic ldpc_dvb_dec_srl_fifo__iwrite ; + logic [pDAT_W-1 : 0] ldpc_dvb_dec_srl_fifo__iwdat ; + // + logic ldpc_dvb_dec_srl_fifo__iread ; + logic ldpc_dvb_dec_srl_fifo__orval ; + logic [pDAT_W-1 : 0] ldpc_dvb_dec_srl_fifo__ordat ; + // + logic ldpc_dvb_dec_srl_fifo__oempty ; + logic ldpc_dvb_dec_srl_fifo__ofull ; + + + + ldpc_dvb_dec_srl_fifo + #( + .pDEPTH_W ( pDEPTH_W ) , + .pDAT_W ( pDAT_W ) + ) + ldpc_dvb_dec_srl_fifo + ( + .iclk ( ldpc_dvb_dec_srl_fifo__iclk ) , + .ireset ( ldpc_dvb_dec_srl_fifo__ireset ) , + .iclkena ( ldpc_dvb_dec_srl_fifo__iclkena ) , + // + .iclear ( ldpc_dvb_dec_srl_fifo__iclear ) , + // + .iwrite ( ldpc_dvb_dec_srl_fifo__iwrite ) , + .iwdat ( ldpc_dvb_dec_srl_fifo__iwdat ) , + // + .iread ( ldpc_dvb_dec_srl_fifo__iread ) , + .orval ( ldpc_dvb_dec_srl_fifo__orval ) , + .ordat ( ldpc_dvb_dec_srl_fifo__ordat ) , + // + .oempty ( ldpc_dvb_dec_srl_fifo__oempty ) , + .ofull ( ldpc_dvb_dec_srl_fifo__ofull ) + ); + + + assign ldpc_dvb_dec_srl_fifo__iclk = '0 ; + assign ldpc_dvb_dec_srl_fifo__ireset = '0 ; + assign ldpc_dvb_dec_srl_fifo__iclkena = '0 ; + assing ldpc_dvb_dec_srl_fifo__iclear = '0 ; + assign ldpc_dvb_dec_srl_fifo__iwrite = '0 ; + assign ldpc_dvb_dec_srl_fifo__iwdat = '0 ; + assign ldpc_dvb_dec_srl_fifo__iread = '0 ; + + + +*/ + +// +// Project : ldpc DVB-S2 +// Author : Shekhalev Denis (des00) +// Workfile : ldpc_dvb_dec_srl_fifo.sv +// Description : Small SRL based fifo with synchronous output +// + +module ldpc_dvb_dec_srl_fifo +#( + parameter int pDEPTH_W = 8 , + parameter int pDAT_W = 8 +) +( + iclk , + ireset , + iclkena , + // + iclear , + // + iwrite , + iwdat , + // + iread , + orval , + ordat , + // + oempty , + ofull +); + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + input logic iclk ; + input logic ireset ; + input logic iclkena ; + // + input logic iclear ; + // + input logic iwrite ; + input logic [pDAT_W-1 : 0] iwdat ; + // + input logic iread ; + output logic orval ; + output logic [pDAT_W-1 : 0] ordat ; + // + output logic oempty ; + output logic ofull ; + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + bit [pDAT_W-1 : 0] ram [2**pDEPTH_W]; + + logic [pDEPTH_W : 0] cnt; // + 1 bit for correct work + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + wire write = iwrite & !ofull; + wire read = iread & !oempty; + + always_ff @(posedge iclk or posedge ireset) begin + if (ireset) begin + cnt <= '0; + end + else if (iclkena) begin + if (iclear) begin + cnt <= '0; + end + else if (write ^ read) begin + cnt <= write ? (cnt + 1'b1) : (cnt - 1'b1); + end + end + end + + assign oempty = (cnt == 0); + assign ofull = cnt[pDEPTH_W]; + + always_ff @(posedge iclk or posedge ireset) begin + if (ireset) begin + orval <= 1'b0; + end + else if (iclkena) begin + orval <= read; + end + end + + always_ff @(posedge iclk) begin + if (iclkena) begin + if (write) begin + ram[0] <= iwdat; + for (int i = 1; i < 2**pDEPTH_W; i++) begin + ram[i] <= ram[i-1]; + end + end + // + ordat <= ram[cnt - 1'b1]; + end + end + + //------------------------------------------------------------------------------------------------------ + // + //------------------------------------------------------------------------------------------------------ + + // synthesis translate_off + always_ff @(posedge iclk) begin + if (iclkena) begin + if (iwrite & !iclear) begin + assert (!ofull) else begin + $error("fifo %m overflow"); + $stop; + end + end + if (iread & !iclear) begin + assert(!oempty) else begin + $error("fifo %m underflow"); + $stop; + end + end + end + end + // synthesis translate_on +endmodule + diff --git a/rtl/ldpc_dvb/dec/ldpc_dvb_dec_vnode.sv b/rtl/ldpc_dvb/dec/ldpc_dvb_dec_vnode.sv index 9aca992..b7a80f3 100644 --- a/rtl/ldpc_dvb/dec/ldpc_dvb_dec_vnode.sv +++ b/rtl/ldpc_dvb/dec/ldpc_dvb_dec_vnode.sv @@ -9,6 +9,7 @@ // parameter int pUSE_SC_MODE = 1 ; parameter bit pDO_LLR_INVERSION = 0 ; + parameter bit pUSE_SRL_FIFO = 0 ; logic ldpc_dvb_dec_vnode__iclk ; @@ -37,6 +38,8 @@ zdat_t ldpc_dvb_dec_vnode__obitdat ; zdat_t ldpc_dvb_dec_vnode__obiterr ; col_t ldpc_dvb_dec_vnode__obitaddr ; + // + logic ldpc_dvb_dec_vnode__obusy ; @@ -48,7 +51,8 @@ .pNORM_FACTOR ( pNORM_FACTOR ) , // .pUSE_SC_MODE ( pUSE_SC_MODE ) , - .pDO_LLR_INVERSION ( pDO_LLR_INVERSION ) + .pDO_LLR_INVERSION ( pDO_LLR_INVERSION ) , + .pUSE_SRL_FIFO ( pUSE_SRL_FIFO ) ) ldpc_dvb_dec_vnode ( @@ -133,11 +137,14 @@ module ldpc_dvb_dec_vnode obiteop , obitdat , obiterr , - obitaddr + obitaddr , + // + obusy ); parameter int pNORM_FACTOR = 0; parameter bit pDO_LLR_INVERSION = 0; + parameter bit pUSE_SRL_FIFO = 1; // use SRL based internal FIFO `include "../ldpc_dvb_constants.svh" `include "ldpc_dvb_dec_types.svh" @@ -172,6 +179,8 @@ module ldpc_dvb_dec_vnode output zdat_t obitdat ; output zdat_t obiterr ; output col_t obitaddr ; + // + output logic obusy ; //------------------------------------------------------------------------------------------------------ // @@ -211,6 +220,7 @@ module ldpc_dvb_dec_vnode logic [cCNODE_FIFO_DAT_W-1 : 0] cnode_fifo__iwdat ; // logic cnode_fifo__iread ; + logic cnode_fifo__orval ; logic [cCNODE_FIFO_DAT_W-1 : 0] cnode_fifo__ordat ; // logic cnode_fifo__oempty ; @@ -286,28 +296,58 @@ module ldpc_dvb_dec_vnode // cnode dynamic align line (1 tick delay) //------------------------------------------------------------------------------------------------------ - ldpc_dvb_dec_fifo - #( - .pDEPTH_W ( cCNODE_FIFO_DEPTH_W ) , - .pDAT_W ( cCNODE_FIFO_DAT_W ) - ) - cnode_fifo - ( - .iclk ( iclk ) , - .ireset ( 1'b0 ) , // don'n need because there is iclear used - .iclkena ( iclkena ) , - // - .iclear ( cnode_fifo__iclear ) , - // - .iwrite ( cnode_fifo__iwrite ) , - .iwdat ( cnode_fifo__iwdat ) , - // - .iread ( cnode_fifo__iread ) , - .ordat ( cnode_fifo__ordat ) , - // - .oempty ( cnode_fifo__oempty ) , - .ofull ( cnode_fifo__ofull ) - ); + generate + if (pUSE_SRL_FIFO) begin + ldpc_dvb_dec_srl_fifo + #( + .pDEPTH_W ( cCNODE_FIFO_DEPTH_W ) , + .pDAT_W ( cCNODE_FIFO_DAT_W ) + ) + cnode_fifo + ( + .iclk ( iclk ) , + .ireset ( 1'b0 ) , // don'n need because there is iclear used + .iclkena ( iclkena ) , + // + .iclear ( cnode_fifo__iclear ) , + // + .iwrite ( cnode_fifo__iwrite ) , + .iwdat ( cnode_fifo__iwdat ) , + // + .iread ( cnode_fifo__iread ) , + .orval ( cnode_fifo__orval ) , + .ordat ( cnode_fifo__ordat ) , + // + .oempty ( cnode_fifo__oempty ) , + .ofull ( cnode_fifo__ofull ) + ); + end + else begin + ldpc_dvb_dec_fifo + #( + .pDEPTH_W ( cCNODE_FIFO_DEPTH_W ) , + .pDAT_W ( cCNODE_FIFO_DAT_W ) + ) + cnode_fifo + ( + .iclk ( iclk ) , + .ireset ( 1'b0 ) , // don'n need because there is iclear used + .iclkena ( iclkena ) , + // + .iclear ( cnode_fifo__iclear ) , + // + .iwrite ( cnode_fifo__iwrite ) , + .iwdat ( cnode_fifo__iwdat ) , + // + .iread ( cnode_fifo__iread ) , + .orval ( cnode_fifo__orval ) , + .ordat ( cnode_fifo__ordat ) , + // + .oempty ( cnode_fifo__oempty ) , + .ofull ( cnode_fifo__ofull ) + ); + end + endgenerate assign cnode_fifo__iclear = istart; @@ -321,7 +361,17 @@ module ldpc_dvb_dec_vnode end end - assign cnode_fifo__iread = ctrl__oread; + // + // only RAMB version use look ahead reading to get 2 cycle read latency + // + generate + if (pUSE_SRL_FIFO) begin + assign cnode_fifo__iread = ctrl__oread; + end + else begin + assign cnode_fifo__iread = ctrl__oread | ctrl__irdy; // look ahead reading + end + endgenerate //------------------------------------------------------------------------------------------------------ // vnode restore ctrl @@ -344,11 +394,22 @@ module ldpc_dvb_dec_vnode .oread_idx ( ) ); - assign ctrl__irdy = sum__ovnode_pre_val [0]; - assign ctrl__inum_m1 = sum__ovnode_pre_num_m1 [0]; + // + // only RAMB version use look ahead reading to get 2 cycle read latency + // + generate + if (pUSE_SRL_FIFO) begin + assign ctrl__irdy = sum__ovnode_pre_val [0]; + assign ctrl__inum_m1 = sum__ovnode_pre_num_m1 [0]; + end + else begin + assign ctrl__irdy = sum__ovnode_pre_val [0]; + assign ctrl__inum_m1 = sum__ovnode_num_m1 [0]; //use look ahead reading (-1):: see ldpc_dvb_dec_vnode_sum.ovnode_pre_num_m1 signal generation + end + endgenerate //------------------------------------------------------------------------------------------------------ - // vnode restore unut + // vnode restore unit (2 tick delay) //------------------------------------------------------------------------------------------------------ generate @@ -381,23 +442,48 @@ module ldpc_dvb_dec_vnode .ovnode_state ( restore__ovnode_state [g] ) ); - always_ff @(posedge iclk) begin - if (iclkena) begin - restore__ival [g] <= ctrl__oread ; - // need hold decision for all cycle - if (sum__ovnode_val [g]) begin - restore__ivnode_sum [g] <= sum__ovnode_sum[g]; - restore__ivnode_hd [g] <= sum__ovnode_hd [g]; + // + // only RAMB version use look ahead reading to get 2 cycle read latency + // + if (pUSE_SRL_FIFO) begin + + assign restore__ival [g] = cnode_fifo__orval ; + + always_ff @(posedge iclk) begin + if (iclkena) begin + // need hold decision for all cycle + if (sum__ovnode_val [0]) begin + restore__ivnode_sum [g] <= sum__ovnode_sum[g]; + restore__ivnode_hd [g] <= sum__ovnode_hd [g]; + end end end - end + // + // srl fifo has 1 tick delay + assign restore__ivnode_addr [g] = cnode_fifo__ordat[cCNODE_FIFO_DAT_W-1 -: cNODE_TAG_W]; + assign restore__ivnode_state [g] = '0; + assign restore__icnode [g] = cnode_fifo__ordat[g*pNODE_W +: pNODE_W]; - // - // srl fifo has 1 tick delay - assign restore__ivnode_addr [g] = cnode_fifo__ordat[cCNODE_FIFO_DAT_W-1 -: cNODE_TAG_W]; - assign restore__ivnode_state [g] = '0; - assign restore__icnode [g] = cnode_fifo__ordat[g*pNODE_W +: pNODE_W]; + end + else begin + + always_ff @(posedge iclk) begin + if (iclkena) begin + restore__ival [g] <= cnode_fifo__orval; + // need hold decision for all cycle + if (sum__ovnode_val [0]) begin + restore__ivnode_sum [g] <= sum__ovnode_sum[g]; + restore__ivnode_hd [g] <= sum__ovnode_hd [g]; + end + // + // add + 1 tick delay to FIFO + restore__ivnode_addr [g] <= cnode_fifo__ordat[cCNODE_FIFO_DAT_W-1 -: cNODE_TAG_W]; + restore__icnode [g] <= cnode_fifo__ordat[g*pNODE_W +: pNODE_W]; + end + end + assign restore__ivnode_state [g] = '0; + end end endgenerate @@ -411,6 +497,26 @@ module ldpc_dvb_dec_vnode assign ovnode_hd = restore__ovnode_hd; assign ovnode_state = restore__ovnode_state; + //------------------------------------------------------------------------------------------------------ + // obusy is look ahead signal for control + // there is 4 tick betwen write/read to node ram + // this logic save 2 tick for each iteration + //------------------------------------------------------------------------------------------------------ + + always_ff @(posedge iclk or posedge ireset) begin + if (ireset) begin + obusy <= 1'b0; + end + else if (iclkena) begin + if (pUSE_SRL_FIFO) begin + obusy <= ctrl__oread | !cnode_fifo__oempty; + end + else begin + obusy <= cnode_fifo__orval | !cnode_fifo__oempty; // fifo_empty use because there can be holes in oval flow (!!!) + end + end + end + //------------------------------------------------------------------------------------------------------ // bit interface output (register must be here) //------------------------------------------------------------------------------------------------------ diff --git a/rtl/ldpc_dvb/dec/ldpc_dvb_dec_vnode_restore.sv b/rtl/ldpc_dvb/dec/ldpc_dvb_dec_vnode_restore.sv index 438647f..fd8883f 100644 --- a/rtl/ldpc_dvb/dec/ldpc_dvb_dec_vnode_restore.sv +++ b/rtl/ldpc_dvb/dec/ldpc_dvb_dec_vnode_restore.sv @@ -127,8 +127,7 @@ module ldpc_dvb_dec_vnode_restore logic [1 : 0] val; - node_t cnode; - node_sum_t vnode_sum; + node_sum_t vnode; logic vnode_hd; cycle_idx_t vnode_addr; @@ -149,13 +148,11 @@ module ldpc_dvb_dec_vnode_restore always_ff @(posedge iclk) begin if (iclkena) begin - // pipeline to increase timings after RAM - cnode <= icnode; - vnode_sum <= ivnode_sum; + vnode <= ivnode_sum - icnode; vnode_hd <= ivnode_hd; vnode_addr <= ivnode_addr; // - ovnode <= saturate(vnode_sum - cnode); + ovnode <= saturate(vnode); ovnode_hd <= vnode_hd; ovnode_addr <= vnode_addr; end diff --git a/rtl/ldpc_dvb/enc/ldpc_dvb_enc_engine.sv b/rtl/ldpc_dvb/enc/ldpc_dvb_enc_engine.sv index 75f4835..cd3c435 100644 --- a/rtl/ldpc_dvb/enc/ldpc_dvb_enc_engine.sv +++ b/rtl/ldpc_dvb/enc/ldpc_dvb_enc_engine.sv @@ -4,7 +4,10 @@ parameter int pRADDR_W = 8 ; parameter int pWADDR_W = 8 ; + // parameter int pTAG_W = 4 ; + // + parameter int pCODEGR = 1 ; parameter bit pFIX_MODE = 1 ; @@ -40,7 +43,10 @@ #( .pRADDR_W ( pRADDR_W ) , .pWADDR_W ( pWADDR_W ) , + // .pTAG_W ( pTAG_W ) , + // + .pCODEGR ( pCODEGR ) , .pFIX_MODE ( pFIX_MODE ) ) ldpc_dvb_enc_engine @@ -99,7 +105,8 @@ module ldpc_dvb_enc_engine // parameter int pTAG_W = 4 , // - parameter bit pFIX_MODE = 1 // use fixed mode encoder or not + parameter bit pCODEGR = 1, // maximum used graph short(0)/large(1) + parameter bit pFIX_MODE = 0 // use fixed mode encoder or not ) ( iclk , @@ -169,93 +176,102 @@ module ldpc_dvb_enc_engine localparam [cLOG2_ZC_MAX-1 : 0] cBS_PIPE_LINE = 9'b1_0010_0100; // 3 pipeline stage localparam int cBS_DELAY = 3 + cRDAT_DELAY; // barrel shifter delay + // parity bit RAM settings + localparam int cPRAM_ADDR_W = pCODEGR ? cLOG2_ROW_MAX : cLOG2_ROW_SHORT_MAX; + localparam int cPRAM_DAT_W = cZC_MAX; + //------------------------------------------------------------------------------------------------------ // //------------------------------------------------------------------------------------------------------ // // Hs gen - code_ctx_t hs_gen__icode_ctx ; + code_ctx_t hs_gen__icode_ctx ; // - col_t hs_gen__oused_col ; - col_t hs_gen__oused_data_col ; - row_t hs_gen__oused_row ; - cycle_idx_t hs_gen__ocycle_max_num ; + col_t hs_gen__oused_col ; + col_t hs_gen__oused_data_col ; + row_t hs_gen__oused_row ; + cycle_idx_t hs_gen__ocycle_max_num ; // - logic hs_gen__icycle_read ; - cycle_idx_t hs_gen__icycle_idx ; + logic hs_gen__icycle_read ; + cycle_idx_t hs_gen__icycle_idx ; // - logic hs_gen__ocycle_read ; - strb_t hs_gen__ocycle_strb ; - col_t hs_gen__ocycle_col_idx ; - shift_t hs_gen__ocycle_shift ; + logic hs_gen__ocycle_read ; + strb_t hs_gen__ocycle_strb ; + col_t hs_gen__ocycle_col_idx ; + shift_t hs_gen__ocycle_shift ; // // ctrl - logic ctrl__ibuf_full ; - logic ctrl__obuf_empty ; - logic ctrl__iobuf_empty ; + logic ctrl__ibuf_full ; + logic ctrl__obuf_empty ; + logic ctrl__iobuf_empty ; // - col_t ctrl__iused_col ; - col_t ctrl__iused_data_col ; - row_t ctrl__iused_row ; + col_t ctrl__iused_col ; + col_t ctrl__iused_data_col ; + row_t ctrl__iused_row ; // - cycle_idx_t ctrl__icycle_max_num ; + cycle_idx_t ctrl__icycle_max_num ; // - logic ctrl__ostart ; + logic ctrl__ostart ; // - logic ctrl__ip_busy ; - logic ctrl__ocycle_read ; - cycle_idx_t ctrl__ocycle_idx ; + logic ctrl__ip_busy ; + logic ctrl__ocycle_read ; + cycle_idx_t ctrl__ocycle_idx ; // - logic ctrl__op_read ; - strb_t ctrl__op_strb ; - row_t ctrl__op_row_idx ; + logic ctrl__op_read ; + strb_t ctrl__op_strb ; + row_t ctrl__op_row_idx ; // // barrel shifter // - logic bs__ival ; - zdat_t bs__idat ; - shift_t bs__ishift ; + logic bs__ival ; + zdat_t bs__idat ; + shift_t bs__ishift ; // - logic bs__oval ; - zdat_t bs__odat ; + logic bs__oval ; + zdat_t bs__odat ; // // plogic - logic plogic__istart ; + logic plogic__istart ; // - logic plogic__ival ; - strb_t plogic__istrb ; - zdat_t plogic__idat ; + logic plogic__ival ; + strb_t plogic__istrb ; + zdat_t plogic__idat ; // - logic plogic__oval ; - row_t plogic__opacc_row_idx ; - zdat_t plogic__opacc_word ; - zdat_t plogic__opacc ; + logic plogic__oval ; + row_t plogic__opacc_row_idx ; + zdat_t plogic__opacc_word ; + zdat_t plogic__opacc ; // // pram - logic pram__iwrite ; - row_t pram__iwaddr ; - zdat_t pram__iwdat ; + logic pram__iwrite ; + logic [cPRAM_ADDR_W-1 : 0] pram__iwaddr ; + logic [cPRAM_DAT_W-1 : 0] pram__iwdat ; - row_t pram__iraddr ; - zdat_t pram__ordat ; + logic [cPRAM_ADDR_W-1 : 0] pram__iraddr ; + logic [cPRAM_DAT_W-1 : 0] pram__ordat ; // // output mux - col_t mux__iused_data_col ; + col_t mux__iused_data_col ; + // + logic mux__ival ; + col_t mux__icol ; + zdat_t mux__idat ; // - logic mux__ival ; - col_t mux__icol ; - zdat_t mux__idat ; + logic mux__ipval ; + strb_t mux__ipstrb ; + zdat_t mux__ipacc ; + zdat_t mux__ipline ; // - logic mux__ipval ; - strb_t mux__ipstrb ; - zdat_t mux__ipacc ; - zdat_t mux__ipline ; + logic mux__owfull ; + logic mux__owrite ; + col_t mux__owaddr ; + zdat_t mux__owdat ; //------------------------------------------------------------------------------------------------------ // Hs "generator" @@ -474,8 +490,8 @@ module ldpc_dvb_enc_engine codec_mem_block #( - .pADDR_W ( cLOG2_ROW_MAX ) , - .pDAT_W ( cZC_MAX ) , + .pADDR_W ( cPRAM_ADDR_W ) , + .pDAT_W ( cPRAM_DAT_W ) , .pPIPE ( 1 ) ) pram @@ -492,11 +508,11 @@ module ldpc_dvb_enc_engine .ordat ( pram__ordat ) ); - assign pram__iwrite = plogic__oval ; - assign pram__iwaddr = plogic__opacc_row_idx ; - assign pram__iwdat = plogic__opacc_word ; + assign pram__iwrite = plogic__oval; + assign pram__iwaddr = plogic__opacc_row_idx[cPRAM_ADDR_W-1 : 0]; + assign pram__iwdat = plogic__opacc_word; // - assign pram__iraddr = ctrl__op_row_idx ; + assign pram__iraddr = ctrl__op_row_idx[cPRAM_ADDR_W-1 : 0]; //------------------------------------------------------------------------------------------------------ // allign parity block ram delay @@ -542,10 +558,10 @@ module ldpc_dvb_enc_engine .ipacc ( mux__ipacc ) , .ipline ( mux__ipline ) , // - .owfull ( owfull ) , - .owrite ( owrite ) , - .owaddr ( owaddr ) , - .owdat ( owdat ) + .owfull ( mux__owfull ) , + .owrite ( mux__owrite ) , + .owaddr ( mux__owaddr ) , + .owdat ( mux__owdat ) ); always_ff @(posedge iclk) begin @@ -569,6 +585,11 @@ module ldpc_dvb_enc_engine // output data mapping //------------------------------------------------------------------------------------------------------ + assign owfull = mux__owfull; + assign owrite = mux__owrite; + assign owaddr = mux__owaddr[pWADDR_W-1 : 0]; + assign owdat = mux__owdat; + always_ff @(posedge iclk) begin if (iclkena) begin if (ctrl__ostart) begin diff --git a/rtl/ldpc_dvb/enc/ldpc_dvb_enc_fix.sv b/rtl/ldpc_dvb/enc/ldpc_dvb_enc_fix.sv index 1fff4c1..ac09f1a 100644 --- a/rtl/ldpc_dvb/enc/ldpc_dvb_enc_fix.sv +++ b/rtl/ldpc_dvb/enc/ldpc_dvb_enc_fix.sv @@ -418,7 +418,10 @@ module ldpc_dvb_enc_fix #( .pRADDR_W ( cIB_RADDR_W ) , .pWADDR_W ( cOB_ADDR_W ) , + // .pTAG_W ( pTAG_W ) , + // + .pCODEGR ( pCODEGR ) , .pFIX_MODE ( 1 ) ) engine diff --git a/rtl/ldpc_dvb/ldpc_dvb_constants.svh b/rtl/ldpc_dvb/ldpc_dvb_constants.svh index 69627bf..d79f6a0 100644 --- a/rtl/ldpc_dvb/ldpc_dvb_constants.svh +++ b/rtl/ldpc_dvb/ldpc_dvb_constants.svh @@ -51,12 +51,24 @@ localparam int cZC_MAX = 360; localparam int cLOG2_ZC_MAX = $clog2(cZC_MAX); - localparam int cHS_NON_ZERO_MAX = 1024; // maximimum non zero coe in Hs matrix + localparam int cHS_NON_ZERO_MAX = 1024; // maximimum non zero coe in large Hs matrix localparam int cHS_CYCLE_W = $clog2(cHS_NON_ZERO_MAX); localparam int cHS_NON_ZERO_ROW_PER_COL_MAX = 16; // maximim non zero coe in HS col + LLR localparam int cHS_NON_ZERO_COL_PER_ROW_MAX = 32; // maximim non zero coe in HS row + //------------------------------------------------------------------------------------------------------ + // settings to save resourses for short codeword + //------------------------------------------------------------------------------------------------------ + + localparam int cCOL_SHORT_MAX = 45; + localparam int cLOG2_COL_SHORT_MAX = $clog2(cCOL_SHORT_MAX); + + localparam int cLOG2_ROW_SHORT_MAX = cLOG2_COL_SHORT_MAX; //~can make so, its near the same + + localparam int cHS_SHORT_NON_ZERO_MAX = 256; // maximimum non zero coe in short Hs matrix + localparam int cHS_SHORT_CYCLE_W = $clog2(cHS_SHORT_NON_ZERO_MAX); + //------------------------------------------------------------------------------------------------------ // matrix based types //------------------------------------------------------------------------------------------------------ @@ -69,7 +81,7 @@ typedef logic [cHS_CYCLE_W-1 : 0] cycle_idx_t; - typedef int Hs_t [cROW_MAX][cCOL_MAX][2]; + typedef int Hs_t [cROW_MAX][cCOL_MAX][2]; //------------------------------------------------------------------------------------------------------ // usefull functions