├── LICENSE ├── README.md ├── do ├── do_bch.do ├── do_bch_erasure.do ├── do_btc.do ├── do_ccsds_turbo.do ├── do_dvb_pls.do ├── do_g709.do ├── do_golay24.do ├── do_gsfc_ldpc.do ├── do_hamming.do ├── do_ldpc.do ├── do_ldpc_3gpp.do ├── do_ldpc_dvb.do ├── do_ldpc_dvb_x.do ├── do_llr.do ├── do_pc_3gpp_beh.do ├── do_pc_3gpp_rtl.do ├── do_rs.do ├── do_rs_erasure.do ├── do_rsc.do ├── do_rsc2.do ├── do_super_i3.do ├── do_tcm.do ├── do_vit.do └── do_vit_3by4.do ├── include ├── awgn_class.svh ├── bch_define.vh ├── bch_functions.svh ├── bch_parameters.svh ├── define.vh ├── gf_functions.svh ├── gf_functions.vh ├── pkt_class.svh ├── rs_functions.svh └── rs_parameters.svh ├── rtl ├── TCM_4D_8PSK │ ├── README.md │ ├── dec │ │ ├── tcm_dec.sv │ │ ├── tcm_dec_acsu.sv │ │ ├── tcm_dec_beh.sv │ │ ├── tcm_dec_demapper.sv │ │ ├── tcm_dec_dfd.sv │ │ ├── tcm_dec_rp.sv │ │ ├── tcm_dec_symb_m_asm.sv │ │ ├── tcm_dec_symb_mc.sv │ │ ├── tcm_dec_tmu.sv │ │ ├── tcm_dec_tmu_hd.sv │ │ ├── tcm_dec_tmu_tree16.sv │ │ ├── tcm_dec_tmu_tree2.sv │ │ ├── tcm_dec_tmu_tree4.sv │ │ ├── tcm_dec_tmu_tree8.sv │ │ ├── tcm_dec_trb.sv │ │ ├── tcm_dec_trb_ctrl.sv │ │ ├── tcm_dec_trb_decision.sv │ │ ├── tcm_dec_trb_engine.sv │ │ ├── tcm_dec_types.svh │ │ ├── tcm_symb_m_group_tab.svh │ │ └── tcm_trellis.svh │ └── enc │ │ ├── tcm_enc.sv │ │ ├── tcm_enc_conv.sv │ │ ├── tcm_enc_dfc.sv │ │ └── tcm_enc_mapper.sv ├── bch │ ├── README.md │ ├── bch_berlekamp.sv │ ├── bch_berlekamp_ibm_2t.sv │ ├── bch_berlekamp_ibm_2t_by_t.sv │ ├── bch_berlekamp_ibm_4t.sv │ ├── bch_berlekamp_ribm_1t.sv │ ├── bch_berlekamp_ribm_2t.sv │ ├── bch_berlekamp_ribm_t_by_t.sv │ ├── bch_buffer.sv │ ├── bch_chieny_search.sv │ ├── bch_dec.sv │ ├── bch_dec_dp.sv │ ├── bch_decision.sv │ ├── bch_enc.sv │ ├── bch_enc_ext.sv │ ├── bch_syndrome_count.sv │ ├── dvb │ │ ├── README.md │ │ ├── bch_dvb_dec_fix.sv │ │ ├── bch_dvb_enc_fix.sv │ │ └── bch_dvb_fix_parameters.svh │ ├── erasure │ │ ├── bch_eras_berlekamp.sv │ │ ├── bch_eras_berlekamp_ribm_1t.sv │ │ ├── bch_eras_berlekamp_ribm_2t.sv │ │ ├── bch_eras_berlekamp_ribm_t_by_t.sv │ │ ├── bch_eras_chieny_search.sv │ │ ├── bch_eras_dec.sv │ │ ├── bch_eras_decision.sv │ │ └── bch_eras_syndrome_count.sv │ └── gf │ │ ├── gf_alpha.sv │ │ ├── gf_chieny_alpha_start.sv │ │ ├── gf_chieny_engine.sv │ │ ├── gf_mult.sv │ │ ├── gf_mult_const.sv │ │ ├── gf_parameters.svh │ │ └── gf_syndrome_engine.sv ├── biterr_cnt │ ├── codec_biterr_adder.sv │ ├── codec_biterr_cnt.sv │ └── codec_biterr_sum_36.sv ├── btc │ ├── README.md │ ├── btc_parameters.svh │ ├── dec │ │ ├── btc_dec.sv │ │ ├── btc_dec_comp_code.sv │ │ ├── btc_dec_comp_code_asm.sv │ │ ├── btc_dec_comp_code_engine.sv │ │ ├── btc_dec_comp_code_ser.sv │ │ ├── btc_dec_comp_code_sink.sv │ │ ├── btc_dec_comp_code_source.sv │ │ ├── btc_dec_ctrl.sv │ │ ├── btc_dec_eham_decision.sv │ │ ├── btc_dec_eham_fchase.sv │ │ ├── btc_dec_engine.sv │ │ ├── btc_dec_mem.sv │ │ ├── btc_dec_sink.sv │ │ ├── btc_dec_source.sv │ │ ├── btc_dec_spc_decode.sv │ │ ├── btc_dec_spc_eham_init.sv │ │ └── btc_dec_types.svh │ └── enc │ │ ├── btc_enc.sv │ │ ├── btc_enc_col_code.sv │ │ ├── btc_enc_ctrl.sv │ │ ├── btc_enc_engine.sv │ │ ├── btc_enc_row_code.sv │ │ ├── btc_enc_sink.sv │ │ └── btc_enc_source.sv ├── buffer │ ├── codec_abuffer.sv │ ├── codec_abuffer_dwc.sv │ ├── codec_buffer.sv │ ├── codec_buffer_dwc.sv │ ├── codec_buffer_nD_alogic.sv │ ├── codec_buffer_nD_slogic.sv │ ├── codec_map_dec_extr_ram.sv │ ├── codec_map_dec_input_ram.sv │ ├── codec_map_dec_mm.sv │ ├── codec_map_dec_output_ram.sv │ ├── codec_mem_ablock.sv │ ├── codec_mem_block.sv │ ├── codec_mem_dwc_ablock.sv │ └── codec_mem_dwc_block.sv ├── ccsds_turbo │ ├── README.md │ ├── ccsds_turbo_parameters.svh │ ├── ccsds_turbo_ptable.sv │ ├── ccsds_turbo_trellis.svh │ ├── dec │ │ ├── ccsds_turbo_dec.sv │ │ ├── ccsds_turbo_dec_Lapo.sv │ │ ├── ccsds_turbo_dec_Lextr.sv │ │ ├── ccsds_turbo_dec_addr_gen.sv │ │ ├── ccsds_turbo_dec_bmc.sv │ │ ├── ccsds_turbo_dec_ctrl.sv │ │ ├── ccsds_turbo_dec_engine.sv │ │ ├── ccsds_turbo_dec_input_buffer.sv │ │ ├── ccsds_turbo_dec_output_buffer.sv │ │ ├── ccsds_turbo_dec_rp.sv │ │ ├── ccsds_turbo_dec_sink.sv │ │ ├── ccsds_turbo_dec_source.sv │ │ ├── ccsds_turbo_dec_types.svh │ │ └── ccsds_turbo_mmax.svh │ └── enc │ │ ├── ccsds_turbo_enc.sv │ │ ├── ccsds_turbo_enc_buffer.sv │ │ ├── ccsds_turbo_enc_ctrl.sv │ │ ├── ccsds_turbo_enc_engine.sv │ │ ├── ccsds_turbo_enc_paddr_gen.sv │ │ └── ccsds_turbo_enc_punct.sv ├── codec_pulse_synchronizer.sv ├── codec_reset_synchronizer.sv ├── dvb_pls │ ├── README.md │ ├── dvb_pi_by_2_bpsk_demapper.sv │ ├── dvb_pi_by_2_bpsk_mapper.sv │ ├── dvb_pls_constants.svh │ ├── dvb_pls_dec.sv │ ├── dvb_pls_dec_bit6_dec.sv │ ├── dvb_pls_dec_ctrl.sv │ ├── dvb_pls_dec_rm_dec.sv │ ├── dvb_pls_dec_symb_metric.sv │ ├── dvb_pls_dec_types.svh │ └── dvb_pls_enc.sv ├── fifo │ ├── codec_fifo.sv │ └── codec_srl_fifo.sv ├── g709 │ ├── README.md │ ├── g709_dec.sv │ ├── g709_enc.sv │ └── g709_types.svh ├── golay24 │ ├── README.md │ ├── dec │ │ ├── golay24_dec.sv │ │ ├── golay24_dec_candidate_gen.sv │ │ ├── golay24_dec_decision.sv │ │ ├── golay24_dec_engine.sv │ │ ├── golay24_dec_metric_calc.sv │ │ ├── golay24_dec_processing.sv │ │ ├── golay24_dec_sort_list.sv │ │ ├── golay24_dec_sort_list_cell.sv │ │ ├── golay24_dec_source.sv │ │ └── golay24_dec_types.svh │ ├── golay24_enc.sv │ └── golay24_functions.svh ├── gsfc_ldpc │ ├── README.md │ ├── dec │ │ ├── gsfc_ldpc_dec.sv │ │ ├── gsfc_ldpc_dec_addr_gen.sv │ │ ├── gsfc_ldpc_dec_addr_gen_tab.svh │ │ ├── gsfc_ldpc_dec_cnode.sv │ │ ├── gsfc_ldpc_dec_cnode_engine.sv │ │ ├── gsfc_ldpc_dec_cnode_pre_engine.sv │ │ ├── gsfc_ldpc_dec_ctrl.sv │ │ ├── gsfc_ldpc_dec_engine.sv │ │ ├── gsfc_ldpc_dec_functions.svh │ │ ├── gsfc_ldpc_dec_mem.sv │ │ ├── gsfc_ldpc_dec_parameters.svh │ │ ├── gsfc_ldpc_dec_vnode.sv │ │ └── gsfc_ldpc_dec_vnode_engine.sv │ ├── gsfc_ldpc_enc.sv │ ├── gsfc_ldpc_enc_fbsrl.sv │ └── gsfc_ldpc_parameters.svh ├── hamming │ ├── README.md │ ├── hamming_dec.sv │ ├── hamming_enc.sv │ └── hamming_parameters.svh ├── ldpc │ ├── README.md │ ├── dec │ │ ├── ldpc_dec.sv │ │ ├── ldpc_dec_addr_gen.sv │ │ ├── ldpc_dec_addr_gen_tab.svh │ │ ├── ldpc_dec_cnode.sv │ │ ├── ldpc_dec_cnode_engine.sv │ │ ├── ldpc_dec_ctrl.sv │ │ ├── ldpc_dec_engine.sv │ │ ├── ldpc_dec_engine_sink.sv │ │ ├── ldpc_dec_functions.svh │ │ ├── ldpc_dec_ibuffer.sv │ │ ├── ldpc_dec_ibuffer_dwc.sv │ │ ├── ldpc_dec_mem.sv │ │ ├── ldpc_dec_parameters.svh │ │ ├── ldpc_dec_source.sv │ │ ├── ldpc_dec_vnode.sv │ │ └── ldpc_dec_vnode_engine.sv │ ├── enc │ │ ├── ldpc_enc.sv │ │ └── ldpc_enc_addr_gen.sv │ └── ldpc_parameters.svh ├── ldpc_3gpp │ ├── README.md │ ├── dec │ │ ├── ldpc_3gpp_dec.sv │ │ ├── ldpc_3gpp_dec_LLR_addr_gen.sv │ │ ├── ldpc_3gpp_dec_biterr_cnt.sv │ │ ├── ldpc_3gpp_dec_biterr_sum_36.sv │ │ ├── ldpc_3gpp_dec_cnode.sv │ │ ├── ldpc_3gpp_dec_cnode_p_2way_engine.sv │ │ ├── ldpc_3gpp_dec_cnode_p_engine.sv │ │ ├── ldpc_3gpp_dec_ctrl.sv │ │ ├── ldpc_3gpp_dec_engine.sv │ │ ├── ldpc_3gpp_dec_hb.sv │ │ ├── ldpc_3gpp_dec_hc.svh │ │ ├── ldpc_3gpp_dec_ibuffer.sv │ │ ├── ldpc_3gpp_dec_mem.sv │ │ ├── ldpc_3gpp_dec_mms_dpram.sv │ │ ├── ldpc_3gpp_dec_obuffer.sv │ │ ├── ldpc_3gpp_dec_sink.sv │ │ ├── ldpc_3gpp_dec_source.sv │ │ ├── ldpc_3gpp_dec_types.svh │ │ ├── ldpc_3gpp_dec_vnode.sv │ │ └── ldpc_3gpp_dec_vnode_engine.sv │ ├── enc │ │ ├── ldpc_3gpp_enc.sv │ │ ├── ldpc_3gpp_enc_acu.sv │ │ ├── ldpc_3gpp_enc_ctrl.sv │ │ ├── ldpc_3gpp_enc_engine.sv │ │ ├── ldpc_3gpp_enc_hb.sv │ │ ├── ldpc_3gpp_enc_mm_spram.sv │ │ ├── ldpc_3gpp_enc_muxout.sv │ │ ├── ldpc_3gpp_enc_p1.sv │ │ ├── ldpc_3gpp_enc_p2.sv │ │ ├── ldpc_3gpp_enc_p3.sv │ │ ├── ldpc_3gpp_enc_raddr_gen.sv │ │ ├── ldpc_3gpp_enc_reg_spram.sv │ │ ├── ldpc_3gpp_enc_sink.sv │ │ ├── ldpc_3gpp_enc_source.sv │ │ └── ldpc_3gpp_enc_types.svh │ ├── ldpc_3gpp_constants.svh │ ├── ldpc_3gpp_dec_wrp.sv │ ├── ldpc_3gpp_enc_wrp.sv │ └── ldpc_3gpp_hc.svh ├── ldpc_dvb │ ├── README.md │ ├── dec │ │ ├── ldpc_dvb_dec_2d_ctrl.sv │ │ ├── ldpc_dvb_dec_2d_engine.sv │ │ ├── ldpc_dvb_dec_barrel_shifter.sv │ │ ├── ldpc_dvb_dec_cnode.sv │ │ ├── ldpc_dvb_dec_cnode_restore.sv │ │ ├── ldpc_dvb_dec_decfail_cnt.sv │ │ ├── ldpc_dvb_dec_fifo.sv │ │ ├── ldpc_dvb_dec_fix.sv │ │ ├── ldpc_dvb_dec_hs.sv │ │ ├── ldpc_dvb_dec_hs_large_packed.svh │ │ ├── ldpc_dvb_dec_hs_short_packed.svh │ │ ├── ldpc_dvb_dec_ibuffer.sv │ │ ├── ldpc_dvb_dec_node_restore_ctrl.sv │ │ ├── ldpc_dvb_dec_sink.sv │ │ ├── ldpc_dvb_dec_sort_engine.sv │ │ ├── ldpc_dvb_dec_source.sv │ │ ├── ldpc_dvb_dec_srl_fifo.sv │ │ ├── ldpc_dvb_dec_syndrome_count.sv │ │ ├── ldpc_dvb_dec_types.svh │ │ ├── ldpc_dvb_dec_vnode.sv │ │ ├── ldpc_dvb_dec_vnode_restore.sv │ │ ├── ldpc_dvb_dec_vnode_sum.sv │ │ ├── ldpc_dvb_x_dec_hs_large_packed.svh │ │ ├── ldpc_dvb_x_dec_hs_medium_packed.svh │ │ └── ldpc_dvb_x_dec_hs_short_packed.svh │ ├── enc │ │ ├── ldpc_dvb_enc_ctrl.sv │ │ ├── ldpc_dvb_enc_engine_fix.sv │ │ ├── ldpc_dvb_enc_fix.sv │ │ ├── ldpc_dvb_enc_hs.sv │ │ ├── ldpc_dvb_enc_hs_large_packed.svh │ │ ├── ldpc_dvb_enc_hs_short_packed.svh │ │ ├── ldpc_dvb_enc_ibuffer.sv │ │ ├── ldpc_dvb_enc_mux.sv │ │ ├── ldpc_dvb_enc_pblock_logic.sv │ │ ├── ldpc_dvb_enc_sink.sv │ │ ├── ldpc_dvb_enc_source.sv │ │ ├── ldpc_dvb_enc_transponse.sv │ │ ├── ldpc_dvb_enc_transponse_acc.sv │ │ ├── ldpc_dvb_enc_transponse_ctrl.sv │ │ ├── ldpc_dvb_enc_types.svh │ │ ├── ldpc_dvb_x_enc_hs_large_packed.svh │ │ ├── ldpc_dvb_x_enc_hs_medium_packed.svh │ │ └── ldpc_dvb_x_enc_hs_short_packed.svh │ ├── ldpc_dvb_barrel_shifter.sv │ ├── ldpc_dvb_constants.svh │ └── ldpc_dvb_wide_shifter.sv ├── llr │ ├── README.md │ ├── gray_bit_mapper.sv │ ├── llr_bpsk_8psk_demapper.sv │ ├── llr_even_qam_demapper.sv │ ├── llr_even_qam_demapper_core.sv │ ├── llr_odd_qam_demapper.sv │ ├── llr_qam128_demapper.sv │ ├── llr_qam2048_demapper.sv │ ├── llr_qam2048_tab_full.svh │ ├── llr_qam2048_tab_part.svh │ ├── llr_qam32_demapper.sv │ └── llr_qam512_demapper.sv ├── pc_3gpp │ ├── README.md │ ├── beh │ │ ├── pc_3gpp_dec_fssc4_mo_beh2rtl.sv │ │ ├── pc_3gpp_dec_sc_beh.sv │ │ ├── pc_3gpp_enc_beh.sv │ │ └── pc_3gpp_enc_opt_beh2rtl.sv │ ├── dec │ │ ├── _start_psm.bat │ │ ├── pc_3gpp_dec.sv │ │ ├── pc_3gpp_dec_alu.sv │ │ ├── pc_3gpp_dec_alu_8x8.sv │ │ ├── pc_3gpp_dec_functions.svh │ │ ├── pc_3gpp_dec_ibuf.sv │ │ ├── pc_3gpp_dec_sc_ctrl.sv │ │ ├── pc_3gpp_dec_sc_ctrl_state.psm │ │ ├── pc_3gpp_dec_sc_ctrl_state.sv │ │ ├── pc_3gpp_dec_sc_engine.sv │ │ ├── pc_3gpp_dec_sink.sv │ │ ├── pc_3gpp_dec_source.sv │ │ └── pc_3gpp_dec_types.svh │ ├── enc │ │ ├── _start_psm.bat │ │ ├── pc_3gpp_enc.sv │ │ ├── pc_3gpp_enc_alu.sv │ │ ├── pc_3gpp_enc_ctrl.sv │ │ ├── pc_3gpp_enc_ctrl_state.psm │ │ ├── pc_3gpp_enc_ctrl_state.sv │ │ ├── pc_3gpp_enc_engine.sv │ │ ├── pc_3gpp_enc_sink.sv │ │ ├── pc_3gpp_enc_source.sv │ │ └── pc_3gpp_enc_types.svh │ ├── pc_3gpp_alpha_ram.sv │ ├── pc_3gpp_beta_ram.sv │ ├── pc_3gpp_functions.svh │ └── pc_3gpp_ts_38_212_tab.svh ├── rs │ ├── README.md │ ├── erasure │ │ ├── rs_eras_berlekamp.sv │ │ ├── rs_eras_berlekamp_ribm_2check.sv │ │ ├── rs_eras_berlekamp_ribm_2check_by_check.sv │ │ ├── rs_eras_chieny_search.sv │ │ ├── rs_eras_dec.sv │ │ ├── rs_eras_syndrome_count_poly.sv │ │ └── rs_eras_syndrome_count_root.sv │ ├── rs_berlekamp.sv │ ├── rs_berlekamp_ribm_1check.sv │ ├── rs_berlekamp_ribm_1p5check_by_check.sv │ ├── rs_berlekamp_ribm_3check.sv │ ├── rs_berlekamp_ribm_6check.sv │ ├── rs_chieny_search.sv │ ├── rs_dec.sv │ ├── rs_enc.sv │ ├── rs_gf_div.sv │ └── rs_syndrome_count.sv ├── rsc │ ├── README.md │ ├── dec │ │ ├── rsc_dec.sv │ │ ├── rsc_dec_Lapo.sv │ │ ├── rsc_dec_Lextr.sv │ │ ├── rsc_dec_addr_gen.sv │ │ ├── rsc_dec_bmc.sv │ │ ├── rsc_dec_ctrl.sv │ │ ├── rsc_dec_engine.sv │ │ ├── rsc_dec_input_buffer.sv │ │ ├── rsc_dec_map_engine.sv │ │ ├── rsc_dec_output_buffer.sv │ │ ├── rsc_dec_rp_mod.sv │ │ ├── rsc_dec_sink.sv │ │ ├── rsc_dec_source.sv │ │ ├── rsc_dec_types.svh │ │ ├── rsc_mmax.svh │ │ └── rsc_trellis.svh │ ├── enc │ │ ├── rsc_enc.sv │ │ ├── rsc_enc_conv_engine.sv │ │ ├── rsc_enc_ctrl.sv │ │ ├── rsc_enc_engine.sv │ │ ├── rsc_enc_ibuffer.sv │ │ ├── rsc_enc_paddr_gen.sv │ │ ├── rsc_enc_punct.sv │ │ ├── rsc_enc_sink.sv │ │ └── rsc_enc_source.sv │ ├── rsc_constants.svh │ ├── rsc_dec_wrp.sv │ ├── rsc_enc_wrp.sv │ ├── rsc_ptable.sv │ └── rsc_sctable.sv ├── rsc2 │ ├── README.md │ ├── dec │ │ ├── rsc2_dec.sv │ │ ├── rsc2_dec_Lapo.sv │ │ ├── rsc2_dec_Lextr.sv │ │ ├── rsc2_dec_bmc.sv │ │ ├── rsc2_dec_engine.sv │ │ ├── rsc2_dec_map_engine.sv │ │ ├── rsc2_dec_rp_mod.sv │ │ ├── rsc2_dec_source.sv │ │ ├── rsc2_dec_types.svh │ │ ├── rsc2_mmax.svh │ │ └── rsc2_trellis.svh │ ├── enc │ │ ├── rsc2_enc.sv │ │ ├── rsc2_enc_conv_engine.sv │ │ ├── rsc2_enc_engine.sv │ │ └── rsc2_enc_punct.sv │ ├── rsc2_constants.svh │ ├── rsc2_dvb_ptable.svh │ ├── rsc2_ntable.sv │ ├── rsc2_ptable.sv │ └── rsc2_sctable.sv ├── super_fec │ ├── README.md │ └── i3 │ │ ├── super_i3_bch_inner_chieny_search.sv │ │ ├── super_i3_bch_inner_dec.sv │ │ ├── super_i3_bch_inner_decision.sv │ │ ├── super_i3_bch_inner_enc.sv │ │ ├── super_i3_bch_inner_syndrome_count.sv │ │ ├── super_i3_bch_inner_types.svh │ │ ├── super_i3_bch_outer_chieny_search.sv │ │ ├── super_i3_bch_outer_dec.sv │ │ ├── super_i3_bch_outer_decision.sv │ │ ├── super_i3_bch_outer_enc.sv │ │ ├── super_i3_bch_outer_syndrome_count.sv │ │ ├── super_i3_bch_outer_types.svh │ │ ├── super_i3_dec.sv │ │ ├── super_i3_enc.sv │ │ └── super_i3_interleave.sv └── viterbi │ ├── README.md │ ├── vit_1byN │ ├── vit_dec.sv │ ├── vit_dec_acsu.sv │ ├── vit_dec_acsu_la.sv │ ├── vit_dec_bmc.sv │ ├── vit_dec_rp.sv │ ├── vit_dec_types.svh │ ├── vit_enc.sv │ ├── vit_trb.sv │ ├── vit_trb_ctrl.sv │ ├── vit_trb_decision.sv │ ├── vit_trb_engine.sv │ └── vit_trellis.svh │ ├── vit_3by4 │ ├── vit_3by4_dec.sv │ ├── vit_3by4_dec_acsu.sv │ ├── vit_3by4_dec_bmc.sv │ ├── vit_3by4_dec_rp.sv │ ├── vit_3by4_dec_trb.sv │ ├── vit_3by4_dec_trb_ctrl.sv │ ├── vit_3by4_dec_trb_decision.sv │ ├── vit_3by4_dec_trb_engine.sv │ ├── vit_3by4_dec_types.svh │ ├── vit_3by4_enc.sv │ └── vit_3by4_trellis.svh │ ├── vit_trb_lifo.sv │ └── vit_trb_ram.sv └── testbench ├── TCM_4D_8PSK ├── bertest.sv └── tcm_pkt_class.svh ├── bch ├── bch_enc_dec_tb.sv └── bch_eras_enc_dec_tb.sv ├── btc └── bertest.sv ├── ccsds_turbo └── bertest.sv ├── dvb_pls └── bertest.sv ├── g709 └── bertest.sv ├── golay24 └── bertest.sv ├── gsfc_ldpc └── bertest.sv ├── hamming └── hamming_tb.sv ├── ldpc └── bertest.sv ├── ldpc_3gpp └── bertest.sv ├── ldpc_dvb ├── bertest.sv └── bertest_x.sv ├── llr └── tb_qam_demapper.sv ├── pc_3gpp ├── bertest.sv └── bertest_rtl.sv ├── rs ├── rs_enc_dec_tb.sv └── rs_eras_enc_dec_tb.sv ├── rsc └── bertest.sv ├── rsc2 └── bertest.sv ├── super_fec └── i3 │ └── bertest.sv └── viterbi ├── vit_1byN ├── bertest.sv └── vit_pkt_class.svh └── vit_3by4 └── bertest.sv /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 dshekhalev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FEC 2 | FEC Codec IP core library for some famous codes (BCH, RS, LDPC, Turbo, Polar and etc) 3 | 4 | FEC IP cores are synthesable and self-documented RTL code (System Verilog) with limited functionality and performance to explore or using for any applications. 5 | 6 | The library contain: 7 | 1. BCH code with optional erasures 8 | 2. RS code with optional erasures 9 | 3. Viterby code for soft-decoding 10 | 4. DVB/Wimax RSC duo-binary turbo code 11 | 5. NASA GSFC LDPC code 12 | 6. Wimax LDPC code 13 | 7. 3GPP LDPC code 14 | 8. 3GPP Polar code 15 | 9. Soft decision Golay code 16 | 10. DVB-S2/S2X LDPC code 17 | 11. CCSDS Turbo code 18 | 12. 4D-8PSK TCM code 19 | 13. Hamming code 20 | 14. QAM LLR demappers 21 | 15. DVB-S2 PLS code 22 | 16. DVB-S2/S2X BCH code 23 | 17. Wimax BTC (TPC) turbo code 24 | 18. Super FEC (G.975.1) I.3 Concatenated BCH code 25 | 19. G.709 16-byte interleaved RS(255,239) code 26 | 27 | All FEC IP Cores has static configuration and constrained performance. Call me if you need any IP core extension 28 | -------------------------------------------------------------------------------- /do/do_bch.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/bch/*.sv 11 | 12 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/bch $tbdir/bch/bch_enc_dec_tb.sv 13 | 14 | set seed [clock seconds] 15 | 16 | vsim -sv_seed $seed bch_enc_dec_tb -lib $workdir 17 | run -all 18 | -------------------------------------------------------------------------------- /do/do_bch_erasure.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/bch/*.sv 11 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/bch/erasure/*.sv 12 | 13 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/bch $tbdir/bch/bch_eras_enc_dec_tb.sv 14 | 15 | set seed [clock seconds] 16 | 17 | vsim -sv_seed $seed bch_eras_enc_dec_tb -lib $workdir 18 | run -all 19 | -------------------------------------------------------------------------------- /do/do_btc.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/*.sv 11 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/buffer/*.sv 12 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/fifo/*.sv 13 | # 14 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/btc/enc $rtldir/btc/enc/*.sv 15 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/btc/dec $rtldir/btc/dec/*.sv 16 | 17 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/btc $tbdir/btc/bertest.sv 18 | 19 | set seed [clock seconds] 20 | 21 | vsim -sv_seed $seed bertest -lib $workdir 22 | run -all 23 | -------------------------------------------------------------------------------- /do/do_ccsds_turbo.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/buffer/*.sv 11 | 12 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/ccsds_turbo $rtldir/ccsds_turbo/*.sv 13 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/ccsds_turbo/enc $rtldir/ccsds_turbo/enc/*.sv 14 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/ccsds_turbo/dec $rtldir/ccsds_turbo/dec/*.sv 15 | 16 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/bch $tbdir/ccsds_turbo/bertest.sv 17 | 18 | set seed [clock seconds] 19 | 20 | vsim -sv_seed $seed bertest -lib $workdir +nowarn+3813 21 | run -all 22 | -------------------------------------------------------------------------------- /do/do_dvb_pls.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/dvb_pls $rtldir/dvb_pls/*.sv 11 | 12 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/dvb_pls $tbdir/dvb_pls/bertest.sv 13 | 14 | set seed [clock seconds] 15 | 16 | vsim -sv_seed $seed bertest -lib $workdir 17 | run -all 18 | -------------------------------------------------------------------------------- /do/do_g709.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/bch/*.sv 11 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/rs/*.sv 12 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/g709 $rtldir/g709/*.sv 13 | 14 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/g709 $tbdir/g709/bertest.sv 15 | 16 | set seed [clock seconds] 17 | 18 | vsim -sv_seed $seed bertest -lib $workdir 19 | run -all 20 | -------------------------------------------------------------------------------- /do/do_golay24.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/golay24 $rtldir/golay24/*.sv 11 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/golay24/dec $rtldir/golay24/dec/*.sv 12 | 13 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/golay24 $tbdir/golay24/bertest.sv 14 | 15 | set seed [clock seconds] 16 | 17 | vsim -sv_seed $seed bertest -lib $workdir 18 | run -all 19 | -------------------------------------------------------------------------------- /do/do_gsfc_ldpc.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/*.sv 11 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/buffer/*.sv 12 | # 13 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/ldpc/dec $rtldir/ldpc/dec/*.sv 14 | # 15 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/gsfc_ldpc $rtldir/gsfc_ldpc/*.sv 16 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/gsfc_ldpc/dec $rtldir/gsfc_ldpc/dec/*.sv 17 | 18 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/gsfc_ldpc $tbdir/gsfc_ldpc/bertest.sv 19 | 20 | set seed [clock seconds] 21 | 22 | vsim -sv_seed $seed bertest -lib $workdir 23 | run -all 24 | -------------------------------------------------------------------------------- /do/do_hamming.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir +incdir+$incdir+$rtldir/hamming $rtldir/hamming/*.sv 11 | 12 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir $tbdir/hamming/hamming_tb.sv 13 | 14 | set seed [clock seconds] 15 | 16 | vsim -sv_seed $seed hamming_tb -lib $workdir 17 | run -all 18 | -------------------------------------------------------------------------------- /do/do_ldpc.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/*.sv 11 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/buffer/*.sv 12 | # 13 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/ldpc/enc $rtldir/ldpc/enc/*.sv 14 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/ldpc/dec $rtldir/ldpc/dec/*.sv 15 | 16 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/ldpc $tbdir/ldpc/bertest.sv 17 | 18 | set seed [clock seconds] 19 | 20 | vsim -sv_seed $seed bertest -lib $workdir 21 | run -all 22 | -------------------------------------------------------------------------------- /do/do_ldpc_3gpp.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/*.sv 11 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/buffer/*.sv 12 | # 13 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/ldpc_3gpp $rtldir/ldpc_3gpp/*.sv 14 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/ldpc_3gpp/enc $rtldir/ldpc_3gpp/enc/*.sv 15 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/ldpc_3gpp/dec $rtldir/ldpc_3gpp/dec/*.sv 16 | 17 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/ldpc $tbdir/ldpc_3gpp/bertest.sv 18 | 19 | set seed [clock seconds] 20 | 21 | vsim -sv_seed $seed bertest -lib $workdir 22 | run -all 23 | -------------------------------------------------------------------------------- /do/do_ldpc_dvb.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/*.sv 11 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/buffer/*.sv 12 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/biterr_cnt/*.sv 13 | # 14 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/ldpc_dvb $rtldir/ldpc_dvb/*.sv 15 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/ldpc_dvb/enc $rtldir/ldpc_dvb/enc/*.sv 16 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/ldpc_dvb/dec $rtldir/ldpc_dvb/dec/*.sv 17 | 18 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/ldpc_dvb $tbdir/ldpc_dvb/bertest.sv 19 | 20 | set seed [clock seconds] 21 | 22 | vsim -sv_seed $seed bertest -lib $workdir 23 | run -all 24 | -------------------------------------------------------------------------------- /do/do_ldpc_dvb_x.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/*.sv 11 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/buffer/*.sv 12 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/biterr_cnt/*.sv 13 | # 14 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/ldpc_dvb $rtldir/ldpc_dvb/*.sv 15 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/ldpc_dvb/enc $rtldir/ldpc_dvb/enc/*.sv 16 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/ldpc_dvb/dec $rtldir/ldpc_dvb/dec/*.sv 17 | 18 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/ldpc_dvb $tbdir/ldpc_dvb/bertest_x.sv 19 | 20 | set seed [clock seconds] 21 | 22 | vsim -sv_seed $seed bertest_x -lib $workdir 23 | run -all 24 | -------------------------------------------------------------------------------- /do/do_llr.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/llr $rtldir/llr/*.sv 11 | 12 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/bch $tbdir/llr/tb_qam_demapper.sv 13 | 14 | set seed [clock seconds] 15 | 16 | vsim -sv_seed $seed tb_qam_demapper -lib $workdir +nowarn+8233 17 | run -all 18 | -------------------------------------------------------------------------------- /do/do_pc_3gpp_beh.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/pc_3gpp/beh $rtldir/pc_3gpp/beh/*.sv 11 | 12 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/pc_3gpp $tbdir/pc_3gpp/bertest.sv 13 | 14 | set seed [clock seconds] 15 | 16 | vsim -sv_seed $seed bertest -lib $workdir 17 | run -all 18 | -------------------------------------------------------------------------------- /do/do_pc_3gpp_rtl.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/buffer/*.sv 11 | 12 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/pc_3gpp $rtldir/pc_3gpp/*.sv 13 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/pc_3gpp/enc $rtldir/pc_3gpp/enc/*.sv 14 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/pc_3gpp/dec $rtldir/pc_3gpp/dec/*.sv 15 | 16 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/pc_3gpp $tbdir/pc_3gpp/bertest_rtl.sv 17 | 18 | set seed [clock seconds] 19 | 20 | vsim -sv_seed $seed bertest_rtl -lib $workdir 21 | run -all 22 | -------------------------------------------------------------------------------- /do/do_rs.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/bch/*.sv 11 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/rs/*.sv 12 | 13 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/bch $tbdir/rs/rs_enc_dec_tb.sv 14 | 15 | set seed [clock seconds] 16 | 17 | vsim -sv_seed $seed rs_enc_dec_tb -lib $workdir 18 | run -all 19 | -------------------------------------------------------------------------------- /do/do_rs_erasure.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/bch/*.sv 11 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/rs/*.sv 12 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/rs/erasure/*.sv 13 | 14 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/bch $tbdir/rs/rs_eras_enc_dec_tb.sv 15 | 16 | set seed [clock seconds] 17 | 18 | vsim -sv_seed $seed rs_enc_dec_tb -lib $workdir 19 | run -all 20 | -------------------------------------------------------------------------------- /do/do_rsc.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/*.sv 11 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/buffer/*.sv 12 | # 13 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/rsc $rtldir/rsc/*.sv 14 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/rsc/enc $rtldir/rsc/enc/*.sv 15 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/rsc/dec $rtldir/rsc/dec/*.sv 16 | 17 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/rsc $tbdir/rsc/bertest.sv 18 | 19 | set seed [clock seconds] 20 | 21 | vsim -sv_seed $seed bertest -lib $workdir +nowarn+3015+3813 22 | run -all 23 | -------------------------------------------------------------------------------- /do/do_rsc2.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/*.sv 11 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/buffer/*.sv 12 | # 13 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/rsc $rtldir/rsc/*.sv 14 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/rsc/enc $rtldir/rsc/enc/*.sv 15 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/rsc/dec $rtldir/rsc/dec/*.sv 16 | # 17 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/rsc2 $rtldir/rsc2/*.sv 18 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/rsc2/enc $rtldir/rsc2/enc/*.sv 19 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/rsc2/dec $rtldir/rsc2/dec/*.sv 20 | 21 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/rsc $tbdir/rsc2/bertest.sv 22 | 23 | set seed [clock seconds] 24 | 25 | vsim -sv_seed $seed bertest -lib $workdir +nowarn+3015+3813+2241 26 | run -all 27 | -------------------------------------------------------------------------------- /do/do_super_i3.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/bch/*.sv 11 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/bch/gf $rtldir/bch/gf/*.sv 12 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/super_fec/i3 $rtldir/super_fec/i3/*.sv 13 | 14 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/super_fec/i3 $tbdir/super_fec/i3/bertest.sv 15 | 16 | set seed [clock seconds] 17 | 18 | vsim -sv_seed $seed bertest -lib $workdir 19 | run -all 20 | -------------------------------------------------------------------------------- /do/do_tcm.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir -incr -sv +incdir+$incdir $rtldir/viterbi/*.sv 11 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/TCM_4D_8PSK/enc $rtldir/TCM_4D_8PSK/enc/*.sv 12 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/TCM_4D_8PSK/dec $rtldir/TCM_4D_8PSK/dec/*.sv 13 | 14 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/TCM_4D_8PSK $tbdir/TCM_4D_8PSK/bertest.sv 15 | 16 | set seed [clock seconds] 17 | 18 | vsim -sv_seed $seed bertest -lib $workdir 19 | run -all 20 | -------------------------------------------------------------------------------- /do/do_vit.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/viterbi/*.sv 11 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/viterbi/vit_1byN $rtldir/viterbi/vit_1byN/*.sv 12 | 13 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/viterbi/vit_1byN $tbdir/viterbi/vit_1byN/bertest.sv 14 | 15 | set seed [clock seconds] 16 | 17 | vsim -sv_seed $seed bertest -lib $workdir 18 | run -all 19 | -------------------------------------------------------------------------------- /do/do_vit_3by4.do: -------------------------------------------------------------------------------- 1 | onerror {resume} 2 | 3 | set incdir ../include 4 | set rtldir ../rtl 5 | set tbdir ../testbench 6 | set workdir ../work 7 | # 8 | vlib $workdir 9 | # 10 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir $rtldir/viterbi/*.sv 11 | vlog -work $workdir -incr -sv +incdir+$incdir+$rtldir/viterbi/vit_3by4 $rtldir/viterbi/vit_3by4/*.sv 12 | 13 | vlog -work $workdir +initreg+0 -sv +incdir+$incdir+$tbdir/viterbi/vit_3by4 $tbdir/viterbi/vit_3by4/bertest.sv 14 | 15 | set seed [clock seconds] 16 | 17 | vsim -sv_seed $seed bertest -lib $workdir 18 | run -all 19 | -------------------------------------------------------------------------------- /include/awgn_class.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : coding library 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : awgn.vh 5 | // Description : AWGN noise generator class 6 | // 7 | 8 | typedef struct { 9 | real re; 10 | real im; 11 | } cmplx_real_dat_t; 12 | 13 | class awgn_class ; 14 | // 15 | // awgn paramters 16 | real EbNo; 17 | real bps; 18 | real coderate; 19 | real SNR; 20 | real sigma; 21 | int seed; 22 | 23 | // 24 | // function to init awgn parameter's based upon EbNo 25 | // EbNo - EbNo in db 26 | // bps - bit per symbol 27 | // coderate - coderate for used coder 28 | // Ps - signal power 29 | // seed - initial generator seed 30 | // 31 | function automatic void init_EbNo (real EbNo = 1, bps = 2, coderate = 1, Ps = 1, int seed = 0); 32 | this.EbNo = EbNo; 33 | this.bps = bps; 34 | this.coderate = coderate; 35 | this.seed = seed; 36 | this.SNR = get_snr(EbNo, bps, coderate); 37 | this.sigma = get_sigma(SNR, Ps); 38 | endfunction 39 | 40 | // 41 | // function to init awgn parameter's based upon SNR 42 | // SNR - SNR in db 43 | // Ps - signal power 44 | // seed - initial generator seed 45 | // 46 | function automatic void init_SNR (real SNR = 0, Ps = 1, int seed = 0); 47 | this.EbNo = 1000; 48 | this.seed = seed; 49 | this.SNR = SNR; 50 | this.sigma = get_sigma(SNR, Ps); 51 | endfunction 52 | 53 | // 54 | // function to count used SNR 55 | // EbNo - EbNo in db 56 | // bps - bit per symbol 57 | // coderate - coderate for used coder 58 | // 59 | function real get_snr (real EbNo = 1, bps = 2, coderate = 1); 60 | return (EbNo + 10*$log10(bps) + 10*$log10(coderate)); 61 | endfunction 62 | 63 | // 64 | // function to count sigma for complex normal distortion generator 65 | // SNR - signal to noise ration 66 | // Ps - signal power 67 | // 68 | function real get_sigma(real SNR = 1, Ps = 1); 69 | return $sqrt(Ps/(10.0**(SNR/10.0))/2.0); 70 | endfunction 71 | 72 | // 73 | // get complex noise function 74 | // 75 | 76 | function automatic cmplx_real_dat_t get_noise (bit bypass = 0); 77 | begin 78 | if (bypass) return '{0, 0}; 79 | // 80 | get_noise.re = sigma * $dist_normal(seed, 0, 2**24)/2**24; 81 | // 82 | get_noise.im = sigma * $dist_normal(seed, 0, 2**24)/2**24; 83 | // 84 | // $display("noise sigma %0f (re/im)/sigma = {%0f, %0f}", sigma, get_noise.re, get_noise.im); 85 | end 86 | endfunction 87 | 88 | // 89 | // add complex noise function 90 | // 91 | 92 | function automatic cmplx_real_dat_t add (cmplx_real_dat_t dat, bit bypass = 0); 93 | real tmp_re; 94 | real tmp_im; 95 | begin 96 | if (bypass) return dat; 97 | // 98 | tmp_re = sigma * $dist_normal(seed, 0, 2**24)/2**24; 99 | add.re = dat.re + tmp_re; 100 | // 101 | tmp_im = sigma * $dist_normal(seed, 0, 2**24)/2**24; 102 | add.im = dat.im + tmp_im; 103 | // 104 | // $display("noise sigma %0f (re/im)/sigma = {%0f, %0f}", sigma, tmp_re/sigma, tmp_im/sigma); 105 | end 106 | endfunction 107 | 108 | // 109 | // count power of complex signal 110 | // 111 | 112 | function automatic real pow (cmplx_real_dat_t dat); 113 | return ((dat.re * dat.re) + (dat.im * dat.im)); 114 | endfunction 115 | 116 | // 117 | // add complex noise function 118 | // 119 | 120 | function void log (); 121 | if (EbNo == 1000) 122 | $display("EbNo = unknown, SNR = %0f, sigma = %0f", SNR, sigma); 123 | else begin 124 | $display("EbNo = %0f, bps = %0f, coderate = %0f", EbNo, bps, coderate); 125 | $display("SNR = %0f, sigma = %0f", SNR, sigma); 126 | end 127 | endfunction 128 | 129 | endclass 130 | -------------------------------------------------------------------------------- /include/bch_define.vh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : bch 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : bch_define.vh 5 | // Description : bch modules macros file 6 | // 7 | 8 | //`define __BCH_BERLEKAMP_DEBUG_LOG__ // uncomment to get log about berlekamp algorithm 9 | //`define __BCH_CHIENY_DEBUG_LOG__ 10 | 11 | //`define __BCH_GEN_POLY_DEBUG_LOG__ 12 | `define __BCH_GEN_POLY_CYCLE_SET_MAX_NUM__ 1000 // maximum number of GF cycle sets 13 | `define __BCH_GEN_POLY_CYCLE_SET_MAX_SIZE__ 50 // maximum number of single cycle set entries 14 | `define __BCH_USING_GEN_POLY_TAB__ // uncomment to use bch generator poly from table 15 | -------------------------------------------------------------------------------- /include/define.vh: -------------------------------------------------------------------------------- 1 | `ifndef __DEFINE_VH__ 2 | 3 | `define __DEFINE_VH__ 4 | 5 | //------------------------------------------------------------------------------------------------------ 6 | // useful function's 7 | //------------------------------------------------------------------------------------------------------ 8 | 9 | // 10 | // function to count logarithm for parameters 11 | // 12 | 13 | function automatic int clogb2 (input int data); 14 | int i; 15 | clogb2 = 0; 16 | if (data > 0) begin 17 | for (i = 0; 2**i < data; i++) begin 18 | clogb2 = i + 1; 19 | end 20 | end 21 | endfunction 22 | 23 | 24 | function automatic int clog2 (input int data); 25 | int i; 26 | clog2 = 0; 27 | if (data > 0) begin 28 | for (i = 0; 2**i < data; i++) begin 29 | clog2 = i + 1; 30 | end 31 | end 32 | endfunction 33 | 34 | 35 | function automatic int max (input int a,b); 36 | max = (a >= b) ? a : b; 37 | endfunction 38 | 39 | 40 | function automatic int min (input int a,b); 41 | min = (a <= b) ? a : b; 42 | endfunction 43 | 44 | 45 | // 46 | // function to count ceil(num/div) == floor(num/div) + ((num % div != 0) ? 1 : 0) 47 | // 48 | 49 | function automatic int ceil (input int num, div); 50 | ceil = (num/div) + (((num % div) != 0) ? 1 : 0); 51 | endfunction 52 | 53 | `endif 54 | -------------------------------------------------------------------------------- /include/pkt_class.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : coding library 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : pkt_class.vh 5 | // Description : base codec data packet class 6 | // 7 | 8 | class pkt_class #(parameter int m = 1); 9 | rand bit [m-1 : 0] dat []; 10 | 11 | function new (int n); 12 | dat = new [n]; 13 | endfunction : new 14 | 15 | function int do_compare (pkt_class #(m) rdat); 16 | int err; 17 | begin 18 | assert (rdat.dat.size() == dat.size()) else begin 19 | $error("data array size compare mismatch"); 20 | return dat.size(); 21 | end 22 | err = 0; 23 | for (int i = 0; i < $size(dat); i++) begin 24 | err += sum_err(dat[i] ^ rdat.dat[i]); 25 | end 26 | return err; 27 | end 28 | endfunction 29 | 30 | function int sum_err (input bit [m-1 : 0] biterr); 31 | sum_err = 0; 32 | for (int i = 0; i < m; i++) begin 33 | sum_err += biterr[i]; 34 | end 35 | endfunction 36 | 37 | endclass 38 | 39 | -------------------------------------------------------------------------------- /include/rs_functions.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : RS 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : rs_functions.svh 5 | // Description : RS code generation function 6 | // 7 | 8 | `include "gf_functions.svh" 9 | 10 | //------------------------------------------------------------------------------------------------------ 11 | // code generator poly 12 | // NOTE :: generation poly order is inverted, that is [check..0] = x^0..x^check. 13 | // Take it into account at encoder architecture 14 | //------------------------------------------------------------------------------------------------------ 15 | 16 | function automatic gpoly_t generate_pol_coeficients (input uint_t genstart, rootspace, lcheck, input rom_t index_of, alpha_to); 17 | uint_t tcheck; 18 | data_t gg [0 : check]; 19 | data_t ggmul [0 : check]; 20 | uint_t alpha; 21 | uint_t alpha_step; 22 | begin 23 | tcheck = (lcheck < 2) ? 2 : lcheck; 24 | // initialization 25 | alpha_step = alpha_to[rootspace]; 26 | 27 | gg[0] = 1; 28 | gg[1] = alpha_to[(genstart*rootspace) % gf_n_max]; 29 | for (int i = 2; i <= check; i++) gg [i] = 0; 30 | 31 | alpha = alpha_to[((genstart + 1)*rootspace) % gf_n_max]; 32 | 33 | for (int j = 0; j <= tcheck-2; j++) begin 34 | for (int p = 1; p <= j+2; p++) begin 35 | //ggmul[p] = gf_mul(gg[p-1], alpha, index_of, alpha_to); 36 | ggmul[p] = gf_mult_a_by_b(gg[p-1], alpha); 37 | end 38 | 39 | for (int p = 1; p <= j+2; p++) begin 40 | //gg[p] = gf_add(gg[p], ggmul[p]); 41 | gg[p] = gg[p] ^ ggmul[p]; 42 | end 43 | 44 | //alpha = gf_mul(alpha, alpha_step, index_of, alpha_to); 45 | alpha = gf_mult_a_by_b(alpha, alpha_step); 46 | end 47 | generate_pol_coeficients = gg; 48 | end 49 | endfunction 50 | 51 | function automatic gpoly_t clear_gpoly (input data_t val = 0); 52 | for (int i = 0; i < $size(clear_gpoly); i++) begin 53 | clear_gpoly[i] = val; 54 | end 55 | endfunction 56 | 57 | 58 | -------------------------------------------------------------------------------- /include/rs_parameters.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : RS 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : rs_parameters.svh 5 | // Description : RS parameters 6 | // 7 | 8 | //------------------------------------------------------------------------------------------------------ 9 | // GF parameters 10 | //------------------------------------------------------------------------------------------------------ 11 | 12 | parameter int m = 8; // GF (2^m) 13 | parameter int irrpol = 285; // irrectible poly 14 | 15 | localparam int gf_n_max = 2**m - 1; // maximum block size 16 | 17 | //------------------------------------------------------------------------------------------------------ 18 | // RS parameters 19 | //------------------------------------------------------------------------------------------------------ 20 | 21 | parameter int n = 240; // block size 22 | parameter int check = 30; // check symbols 23 | parameter int genstart = 0; // first root index 24 | parameter int rootspace = 1; // root space 25 | 26 | parameter int sym_err_w = m ; // clogb2(check/2 + 1); 27 | parameter int bit_err_w = m ; // clogb2((check/2 + 1)*m); 28 | 29 | localparam int errs = check/2; 30 | 31 | //------------------------------------------------------------------------------------------------------ 32 | // used types 33 | //------------------------------------------------------------------------------------------------------ 34 | 35 | typedef int unsigned uint_t; 36 | 37 | typedef logic [m-1 : 0] data_t; 38 | typedef logic [1 : 0] ptr_t ; // used 4D buffer for data saving 39 | 40 | typedef data_t rom_t [0 : gf_n_max]; // alpha_to/index_of/inv_alpha_to table type 41 | typedef data_t gpoly_t [0 : check]; // generator poly type 42 | 43 | typedef logic [sym_err_w-1 : 0] sym_err_t; 44 | typedef logic [bit_err_w-1 : 0] bit_err_t; 45 | -------------------------------------------------------------------------------- /rtl/TCM_4D_8PSK/README.md: -------------------------------------------------------------------------------- 1 | 4D-TCM-8PSK from Green Boook CCSDS 413.0-G-2 2 | 3 | Variable coderate configuration convolution encoder and Viterbi decoder 4 | 5 | vivado 2019.1 Artix 7 - 2 Constraint Length = 7 6 | 7 | Encoder : LUT/REG 84/48 >250MHz (500...687.5Mbps -> 750Mbps) 8 | 9 | Decoder : LUT/REG/RAMB ~21k/~10k/4.5 ~100MHz (300Mbps -> 200...275Mbps) 10 | 11 | 12 | Viterbi decoders use module arithmetic for state registers and ram based traceback 13 | 14 | -------------------------------------------------------------------------------- /rtl/TCM_4D_8PSK/dec/tcm_dec_tmu_hd.sv: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | parameter int pSYMB_M_W = 8; 5 | 6 | 7 | logic tcm_dec_tmu_hd__iclk ; 8 | logic tcm_dec_tmu_hd__ireset ; 9 | logic tcm_dec_tmu_hd__iclkena ; 10 | logic tcm_dec_tmu_hd__ival ; 11 | symb_m_t tcm_dec_tmu_hd__isymb_m [4] ; 12 | logic tcm_dec_tmu_hd__oval ; 13 | symb_hd_t tcm_dec_tmu_hd__ohd ; 14 | 15 | 16 | 17 | 18 | tcm_dec_tmu_hd 19 | #( 20 | .pSYMB_M_W ( pSYMB_M_W ) 21 | ) 22 | tcm_dec_tmu_hd 23 | ( 24 | .iclk ( tcm_dec_tmu_hd__iclk ) , 25 | .ireset ( tcm_dec_tmu_hd__ireset ) , 26 | .iclkena ( tcm_dec_tmu_hd__iclkena ) , 27 | .ival ( tcm_dec_tmu_hd__ival ) , 28 | .isymb_m ( tcm_dec_tmu_hd__isymb_m ) , 29 | .oval ( tcm_dec_tmu_hd__oval ) , 30 | .ohd ( tcm_dec_tmu_hd__ohd ) 31 | ); 32 | 33 | 34 | assign tcm_dec_tmu_hd__iclk = '0 ; 35 | assign tcm_dec_tmu_hd__ireset = '0 ; 36 | assign tcm_dec_tmu_hd__iclkena = '0 ; 37 | assign tcm_dec_tmu_hd__ival = '0 ; 38 | assign tcm_dec_tmu_hd__isymb_m = '0 ; 39 | 40 | 41 | 42 | */ 43 | 44 | // 45 | // Project : 4D-8PSK TCM 46 | // Author : Shekhalev Denis (des00) 47 | // Workfile : tcm_dec_tmu_hd.sv 48 | // Description : get hard decision for 4D symbol : compare and seelct maximum metric for each symbol inside 4D 49 | // 50 | 51 | `include "define.vh" 52 | 53 | module tcm_dec_tmu_hd 54 | ( 55 | iclk , 56 | ireset , 57 | iclkena , 58 | // 59 | ival , 60 | isymb_m , 61 | // 62 | oval , 63 | ohd 64 | ); 65 | 66 | `include "tcm_trellis.svh" 67 | `include "tcm_dec_types.svh" 68 | 69 | //------------------------------------------------------------------------------------------------------ 70 | // 71 | //------------------------------------------------------------------------------------------------------ 72 | 73 | input logic iclk ; 74 | input logic ireset ; 75 | input logic iclkena ; 76 | // 77 | input logic ival ; 78 | input symb_m_t isymb_m [4] ; 79 | // 80 | output logic oval ; 81 | output symb_hd_t ohd ; 82 | 83 | //------------------------------------------------------------------------------------------------------ 84 | // 85 | //------------------------------------------------------------------------------------------------------ 86 | 87 | logic [1 : 0] val; 88 | 89 | symb_m_value_t symb_m [4][2]; 90 | logic [1 : 0] symb_idx [4][2]; 91 | 92 | //------------------------------------------------------------------------------------------------------ 93 | // 94 | //------------------------------------------------------------------------------------------------------ 95 | 96 | always_ff @(posedge iclk or posedge ireset) begin 97 | if (ireset) begin 98 | val <= '0; 99 | end 100 | else if (iclkena) begin 101 | val <= (val << 1) | ival; 102 | end 103 | end 104 | 105 | always_ff @(posedge iclk) begin 106 | bit decision2; 107 | // 108 | if (iclkena) begin 109 | if (ival) begin 110 | for (int i = 0; i < 4; i++) begin 111 | for (int j = 0; j < 2; j++) begin 112 | decision2 = max2(isymb_m[i][2*j+0], isymb_m[i][2*j+1]); 113 | // 114 | symb_m [i][j] <= isymb_m[i][2*j + decision2]; 115 | symb_idx[i][j] <= 2*j + decision2; 116 | end 117 | end 118 | end 119 | // 120 | if (val[0]) begin 121 | for (int i = 0; i < 4; i++) begin 122 | decision2 = max2(symb_m[i][0], symb_m[i][1]); 123 | // 124 | ohd[i] <= symb_idx[i][decision2]; 125 | end 126 | end 127 | end 128 | end 129 | 130 | assign oval = val[1]; 131 | 132 | //------------------------------------------------------------------------------------------------------ 133 | // used functions 134 | //------------------------------------------------------------------------------------------------------ 135 | 136 | function automatic bit max2 (input symb_m_value_t a0, a1); 137 | max2 = (a1 > a0); 138 | endfunction 139 | 140 | endmodule 141 | -------------------------------------------------------------------------------- /rtl/TCM_4D_8PSK/dec/tcm_dec_types.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : 4D-8PSK TCM 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : tcm_dec_types.svh 5 | // Description : tcm viterbi decoder parameters and types 6 | // 7 | 8 | //------------------------------------------------------------------------------------------------------ 9 | // used parameters 10 | //------------------------------------------------------------------------------------------------------ 11 | 12 | parameter int pERR_CNT_W = 16; // error counter width 13 | 14 | // traceback parameters 15 | parameter int pTRB_LENGTH = 64; 16 | 17 | localparam int cTRB_RAM_ADDR_W = $clog2(pTRB_LENGTH) + 2; // 4D buffer 18 | localparam int cTRB_LIFO_ADDR_W = $clog2(pTRB_LENGTH); 19 | 20 | // symbol metric 21 | parameter int pSYMB_M_W = 4; 22 | 23 | // trellis branch metric == sum of 4 metric 24 | localparam int cBM_W = pSYMB_M_W + 2; 25 | localparam int cBM_NUM = 16; 26 | 27 | // trellis state path metric (search minumum, metric is positive) 28 | localparam int cSTATEM_W = cBM_W + 1; // BM + 1 bits for module arithmetic (!!!) 29 | 30 | //------------------------------------------------------------------------------------------------------ 31 | // used types 32 | //------------------------------------------------------------------------------------------------------ 33 | 34 | // error bit counter 35 | typedef logic [pERR_CNT_W-1 : 0] errcnt_t; 36 | 37 | // symbol metric value 38 | typedef logic [pSYMB_M_W-1 : 0] symb_m_value_t; // unsigned (absolute value) 39 | 40 | // symbol metric {C0, C1, C2, C3) with context 41 | typedef symb_m_value_t symb_m_t [4]; 42 | typedef logic [3 : 0] symb_m_idx_t; 43 | typedef logic [3 : 0] symb_m_sign_t; 44 | typedef logic [1 : 0] symb_hd_t [4]; 45 | 46 | // trellis metrics 47 | typedef logic [3 : 0] trel_bm_idx_t ; 48 | typedef logic [cBM_W-1 : 0] trel_bm_t ; // unsigned (sum of absolute value) 49 | typedef logic signed [cSTATEM_W-1 : 0] trel_statem_t ; 50 | typedef logic [2 : 0] trel_decision_t ; 51 | 52 | // trellis array metrics 53 | typedef trel_bm_t bm_t [cBM_NUM]; 54 | typedef trel_statem_t statem_t [cSTATE_NUM]; 55 | typedef trel_decision_t decision_t [cSTATE_NUM]; 56 | 57 | // ram control types 58 | typedef struct packed { 59 | logic [1 : 0] bidx; // use 4D architecture 60 | logic [cTRB_RAM_ADDR_W-3 : 0] addr; // 61 | } trb_ram_addr_t; 62 | 63 | typedef logic [cTRB_LIFO_ADDR_W-1 : 0] trb_lifo_addr_t; 64 | 65 | //------------------------------------------------------------------------------------------------------ 66 | // function for decision at module arithmetic 67 | //------------------------------------------------------------------------------------------------------ 68 | 69 | function logic statem_a_max (input trel_statem_t a, b); 70 | trel_statem_t tmp; 71 | begin 72 | tmp = a - b; 73 | statem_a_max = !tmp[cSTATEM_W-1]; 74 | end 75 | endfunction 76 | 77 | -------------------------------------------------------------------------------- /rtl/TCM_4D_8PSK/dec/tcm_trellis.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : 4D-8PSK TCM 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : tcm_trellis.svh 5 | // Description : tcm viterbi codec trellis defines and used functions 6 | // 7 | 8 | //------------------------------------------------------------------------------------------------------ 9 | // trellis base parameters 10 | //------------------------------------------------------------------------------------------------------ 11 | 12 | localparam int pCONSTR_LENGTH = 7; 13 | 14 | //------------------------------------------------------------------------------------------------------ 15 | // trellis constants 16 | //------------------------------------------------------------------------------------------------------ 17 | 18 | localparam int cSTATE_NUM = 2**(pCONSTR_LENGTH-1); 19 | localparam int cSTATE_W = pCONSTR_LENGTH-1; 20 | 21 | // code state 22 | typedef bit [cSTATE_W-1 : 0] stateb_t; 23 | typedef bit [3 : 0] boutputs_t; 24 | 25 | typedef struct { 26 | stateb_t nextStates [cSTATE_NUM][8]; 27 | stateb_t preStates [cSTATE_NUM][8]; 28 | boutputs_t outputs [cSTATE_NUM][8]; 29 | } trellis_t; 30 | 31 | trellis_t trel; 32 | 33 | always_comb begin 34 | trel = get_trellis (0); 35 | end 36 | 37 | //------------------------------------------------------------------------------------------------------ 38 | // function's to get trellis 39 | //------------------------------------------------------------------------------------------------------ 40 | 41 | function trellis_t get_trellis (input int tmp); 42 | stateb_t nstate; 43 | begin 44 | for (int x3x2x1 = 0; x3x2x1 < 8; x3x2x1++) begin 45 | for (int state = 0; state < cSTATE_NUM; state++) begin 46 | nstate = {state[0], state[cSTATE_W-1 : 2], state[1] ^ state[0]}; 47 | nstate ^= 6'b0_10100 & {6{x3x2x1[2]}}; 48 | nstate ^= 6'b0_01010 & {6{x3x2x1[1]}}; 49 | nstate ^= 6'b0_00011 & {6{x3x2x1[0]}}; 50 | // 51 | get_trellis.nextStates [state][x3x2x1] = nstate; 52 | get_trellis.outputs [state][x3x2x1] = {x3x2x1[2 : 0], state[0]}; 53 | end 54 | end 55 | // 56 | for (int x3x2x1 = 0; x3x2x1 < 8; x3x2x1++) begin 57 | for (int state = 0; state < cSTATE_NUM; state++) begin 58 | nstate = get_trellis.nextStates[state][x3x2x1]; 59 | get_trellis.preStates[nstate][x3x2x1] = state[cSTATE_W-1 : 0]; 60 | end 61 | end 62 | end 63 | endfunction 64 | 65 | -------------------------------------------------------------------------------- /rtl/bch/README.md: -------------------------------------------------------------------------------- 1 | Static configuration BCH decoder based upon Inversion-less & Reformulated Inversion-less Berlekamp algorithm & Chieny Search. 2 | 3 | Generator polynomial can be generated automatically from module settings or used from static tables based upon module settings. 4 | 5 | There is 3 version of RIBM realisation in simple, usual and erasure decoders. The fastest one use "t = d/2" tick only for decoding. 6 | 7 | There is 3 verion of IBM realization in simple and usual decoder. The fastest one use "2*t = d" tick only for decoding. 8 | 9 | Decoders has no any FIFO and use strong external synchronisation inside. It should be reliable completely) 10 | 11 | 12 | vivado 2019.1 Artix 7 - 2 13 | 14 | BCH (255, 223, 4/9), RIBM take 4*(2*4+1)+1 = 37 ticks for decoding 15 | 16 | Encoder : LUT/REG 23/37 ~400MHz (350Mbps -> 400Mbps) 17 | 18 | Decoder simple : LUT/REG/RAMB 285/357/0.5 ~250MHz (250Mbps -> 220Mbps) 19 | 20 | Decoder : LUT/REG/RAMB 312/402/1.0 ~250MHz (250Mbps -> 220Mbps) 21 | 22 | Decoder erasure : LUT/REG/RAMB 486/703/1.0 ~250MHz (250Mbps -> 220Mbps) 23 | 24 | Attention: Simple decoder don't revert back symbol errors if "decoder fail" occurred. The erasure and usual decoder will revert back symbols to input channel state in that case 25 | 26 | -------------------------------------------------------------------------------- /rtl/bch/dvb/README.md: -------------------------------------------------------------------------------- 1 | Simple wrapper for BCH encoder and decoder modules to support DVB-S2/S2X bch modes. There is no any testbench -------------------------------------------------------------------------------- /rtl/bch/gf/gf_alpha.sv: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | 5 | parameter int m = 1 ; 6 | parameter int irrpol = 1 ; 7 | parameter int n = 1 ; 8 | 9 | 10 | 11 | logic [m-1 : 0] gf_alpha__odat [n] ; 12 | 13 | 14 | 15 | gf_alpha 16 | #( 17 | .m ( m ) , 18 | .irrpol ( irrpol ) , 19 | .n ( n ) 20 | ) 21 | gf_alpha 22 | ( 23 | .odat ( gf_alpha__odat ) 24 | ); 25 | 26 | 27 | 28 | 29 | 30 | */ 31 | 32 | // 33 | // Project : galua fields 34 | // Author : Shekhalev Denis (des00) 35 | // Workfile : gf_alpha.sv 36 | // Description : gf alpha table generation unit to use it independed from other project 37 | // 38 | 39 | module gf_alpha 40 | ( 41 | odat 42 | ); 43 | 44 | parameter int n = 2; 45 | 46 | `include "gf_parameters.svh" 47 | `include "gf_functions.svh" 48 | 49 | //------------------------------------------------------------------------------------------------------ 50 | // 51 | //------------------------------------------------------------------------------------------------------ 52 | 53 | output logic [m-1 : 0] odat [n] ; 54 | 55 | //------------------------------------------------------------------------------------------------------ 56 | // 57 | //------------------------------------------------------------------------------------------------------ 58 | 59 | rom_t ALPHA_TO; 60 | 61 | //------------------------------------------------------------------------------------------------------ 62 | // 63 | //------------------------------------------------------------------------------------------------------ 64 | 65 | always_comb begin 66 | ALPHA_TO = generate_gf_alpha_to_power(irrpol); 67 | // 68 | for (int i = 0; i < n; i++) begin 69 | odat[i] = ALPHA_TO[i]; 70 | end 71 | end 72 | 73 | endmodule 74 | -------------------------------------------------------------------------------- /rtl/bch/gf/gf_chieny_alpha_start.sv: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | 5 | parameter int m = 1 ; 6 | parameter int irrpol = 1 ; 7 | parameter int t = 2 ; 8 | parameter int n = 1 ; 9 | 10 | 11 | 12 | logic [m-1 : 0] gf_chieny_alpha_start__odat [1 : t] ; 13 | 14 | 15 | 16 | gf_chieny_alpha_start 17 | #( 18 | .m ( m ) , 19 | .irrpol ( irrpol ) , 20 | .t ( t ) , 21 | .start ( start ) , 22 | .n ( n ) 23 | ) 24 | gf_chieny_alpha_start 25 | ( 26 | .odat ( gf_alpha__odat ) 27 | ); 28 | 29 | 30 | 31 | 32 | 33 | */ 34 | 35 | // 36 | // Project : galua fields 37 | // Author : Shekhalev Denis (des00) 38 | // Workfile : gf_chieny_alpha_start.sv 39 | // Description : gf alpha start values for shortend codes 40 | // 41 | 42 | module gf_chieny_alpha_start 43 | ( 44 | odat 45 | ); 46 | 47 | parameter int t = 2; // number of corrected errors 48 | parameter int step = 1; // step between roots 49 | parameter int n = 2; // shortened block size 50 | 51 | `include "gf_parameters.svh" 52 | `include "gf_functions.svh" 53 | 54 | //------------------------------------------------------------------------------------------------------ 55 | // 56 | //------------------------------------------------------------------------------------------------------ 57 | 58 | output logic [m-1 : 0] odat [1 : t] ; 59 | 60 | //------------------------------------------------------------------------------------------------------ 61 | // 62 | //------------------------------------------------------------------------------------------------------ 63 | 64 | rom_t ALPHA_TO; 65 | 66 | //------------------------------------------------------------------------------------------------------ 67 | // 68 | //------------------------------------------------------------------------------------------------------ 69 | 70 | always_comb begin 71 | ALPHA_TO = generate_gf_alpha_to_power(irrpol); 72 | // 73 | for (int i = 1; i <= t; i++) begin 74 | odat[i] = ALPHA_TO[start_root_index(i, n, 2**m-1)]; 75 | end 76 | end 77 | 78 | //------------------------------------------------------------------------------------------------------ 79 | // 80 | //------------------------------------------------------------------------------------------------------ 81 | 82 | function automatic int start_root_index(input int step, n, gf_n_max); 83 | start_root_index = (step*(gf_n_max - n + 1)) % gf_n_max; 84 | endfunction 85 | 86 | endmodule 87 | -------------------------------------------------------------------------------- /rtl/bch/gf/gf_chieny_engine.sv: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | 5 | parameter int m = 1 ; 6 | parameter int irrpol = 1 ; 7 | parameter int n = 1 ; 8 | parameter int t = 1 ; 9 | // 10 | parameter int pDAT_W = 1 ; 11 | 12 | 13 | 14 | logic gf_chieny_engine__isop ; 15 | logic [m-1 : 0] gf_chieny_engine__iloc_poly [t] ; 16 | logic [m-1 : 0] gf_chieny_engine__ialpha_start [t] ; 17 | // 18 | logic [m-1 : 0] gf_chieny_engine__iloc_mult [t] ; 19 | logic [m-1 : 0] gf_chieny_engine__ialpha [t] ; 20 | // 21 | logic [m-1 : 0] gf_chieny_engine__oloc_mult [t] ; 22 | 23 | 24 | 25 | gf_chieny_engine 26 | #( 27 | .m ( m ) , 28 | .irrpol ( irrpol ) , 29 | .n ( n ) , 30 | .t ( t ) , 31 | // 32 | .pDAT_W ( pDAT_W ) 33 | ) 34 | gf_chieny_engine 35 | ( 36 | .isop ( gf_chieny_engine__isop ) , 37 | .iloc_poly ( gf_chieny_engine__iloc_poly ) , 38 | .ialpha_start ( gf_chieny_engine__ialpha_start ) , 39 | // 40 | .iloc_mult ( gf_chieny_engine__iloc_mult ) , 41 | .ialpha ( gf_chieny_engine__ialpha ) , 42 | // 43 | .oloc_mult ( gf_chieny_engine__oloc_mult ) 44 | ); 45 | 46 | 47 | assign gf_chieny_engine__isop = '0 ; 48 | assign gf_chieny_engine__iloc_poly = '0 ; 49 | assign gf_chieny_engine__ialpha_start = '0 ; 50 | assign gf_chieny_engine__iloc_mult = '0 ; 51 | assign gf_chieny_engine__ialpha = '0 ; 52 | 53 | 54 | 55 | */ 56 | 57 | // 58 | // Project : galua fields 59 | // Author : Shekhalev Denis (des00) 60 | // Workfile : gf_chieny_engine.sv 61 | // Description : Galua field cnieny locator counters logic for multibit words (!!! LSB first !!!) to use it independed from other project 62 | // 63 | 64 | module gf_chieny_engine 65 | ( 66 | isop , 67 | iloc_poly , 68 | ialpha_start , 69 | // 70 | iloc_mult , 71 | ialpha , 72 | // 73 | oloc_mult 74 | ); 75 | 76 | parameter int pDAT_W = 8; 77 | parameter int t = 2; 78 | 79 | `include "gf_parameters.svh" 80 | `include "gf_functions.svh" 81 | 82 | //------------------------------------------------------------------------------------------------------ 83 | // 84 | //------------------------------------------------------------------------------------------------------ 85 | 86 | input logic isop ; 87 | input logic [m-1 : 0] iloc_poly [0 : t] ; 88 | input logic [m-1 : 0] ialpha_start [1 : t] ; 89 | // 90 | input logic [m-1 : 0] iloc_mult [0 : t][pDAT_W] ; 91 | input logic [m-1 : 0] ialpha [1 : t] ; 92 | // 93 | output logic [m-1 : 0] oloc_mult [0 : t][pDAT_W] ; 94 | 95 | //------------------------------------------------------------------------------------------------------ 96 | // 97 | //------------------------------------------------------------------------------------------------------ 98 | 99 | logic [m-1 : 0] tmp_loc_mult [pDAT_W]; 100 | 101 | //------------------------------------------------------------------------------------------------------ 102 | // 103 | //------------------------------------------------------------------------------------------------------ 104 | 105 | always_comb begin 106 | if (isop) begin 107 | oloc_mult [0] = '{default : iloc_poly[0]}; 108 | end 109 | else begin 110 | oloc_mult [0] = iloc_mult[0]; // comb loop 111 | end 112 | // 113 | for (int i = 1; i <= t; i++) begin 114 | if (isop) begin 115 | tmp_loc_mult[0] = gf_mult_a_by_b(iloc_poly[i], ialpha_start[i]); 116 | end 117 | else begin 118 | tmp_loc_mult[0] = gf_mult_a_by_b_const(iloc_mult[i][pDAT_W-1], ialpha[i]); 119 | end 120 | // 121 | for (int b = 1; b < pDAT_W; b++) begin 122 | tmp_loc_mult[b] = gf_mult_a_by_b_const(tmp_loc_mult[b-1], ialpha[i]); 123 | end 124 | // 125 | oloc_mult[i] = tmp_loc_mult; 126 | end 127 | end 128 | 129 | endmodule 130 | -------------------------------------------------------------------------------- /rtl/bch/gf/gf_mult.sv: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | 5 | parameter int m = 1 ; 6 | parameter int irrpol = 1 ; 7 | 8 | 9 | 10 | logic [m-1 : 0] gf_mult__idat_a ; 11 | logic [m-1 : 0] gf_mult__idat_b ; 12 | // 13 | logic [m-1 : 0] gf_mult__odat ; 14 | 15 | 16 | 17 | gf_mult 18 | #( 19 | .m ( m ) , 20 | .irrpol ( irrpol ) 21 | ) 22 | gf_mult 23 | ( 24 | .idat_a ( gf_mult__idat_a ) , 25 | .idat_b ( gf_mult__idat_b ) , 26 | // 27 | .odat ( gf_mult__odat ) 28 | ); 29 | 30 | 31 | assign gf_mult__idat_a = '0 ; 32 | assign gf_mult__idat_b = '0 ; 33 | 34 | 35 | 36 | */ 37 | 38 | // 39 | // Project : galua fields 40 | // Author : Shekhalev Denis (des00) 41 | // Workfile : gf_mult.sv 42 | // Description : gf multiplier to use it independed from other project 43 | // 44 | 45 | module gf_mult 46 | ( 47 | idat_a , 48 | idat_b , 49 | // 50 | odat 51 | ); 52 | 53 | `include "gf_parameters.svh" 54 | `include "gf_functions.svh" 55 | 56 | //------------------------------------------------------------------------------------------------------ 57 | // 58 | //------------------------------------------------------------------------------------------------------ 59 | 60 | input logic [m-1 : 0] idat_a ; 61 | input logic [m-1 : 0] idat_b ; 62 | // 63 | output logic [m-1 : 0] odat ; 64 | 65 | //------------------------------------------------------------------------------------------------------ 66 | // 67 | //------------------------------------------------------------------------------------------------------ 68 | 69 | assign odat = gf_mult_a_by_b(idat_a, idat_b, irrpol); 70 | 71 | endmodule 72 | -------------------------------------------------------------------------------- /rtl/bch/gf/gf_mult_const.sv: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | 5 | parameter int m = 1 ; 6 | parameter int irrpol = 1 ; 7 | 8 | 9 | 10 | logic [m-1 : 0] gf_mult_const__idat_a ; 11 | logic [m-1 : 0] gf_mult_const__iconst ; 12 | // 13 | logic [m-1 : 0] gf_mult_const__odat ; 14 | 15 | 16 | 17 | gf_mult_const 18 | #( 19 | .m ( m ) , 20 | .irrpol ( irrpol ) 21 | ) 22 | gf_mult_const 23 | ( 24 | .idat_a ( gf_mult_const__idat_a ) , 25 | .iconst ( gf_mult_const__iconst ) , 26 | // 27 | .odat ( gf_mult_const__odat ) 28 | ); 29 | 30 | 31 | assign gf_mult_const__idat_a = '0 ; 32 | assign gf_mult_const__iconst = '0 ; 33 | 34 | 35 | 36 | */ 37 | 38 | // 39 | // Project : galua fields 40 | // Author : Shekhalev Denis (des00) 41 | // Workfile : gf_mult_const.sv 42 | // Description : gf constant multiplier to use it independed from other project 43 | // 44 | 45 | module gf_mult_const 46 | ( 47 | idat_a , 48 | iconst , 49 | // 50 | odat 51 | ); 52 | 53 | `include "gf_parameters.svh" 54 | `include "gf_functions.svh" 55 | 56 | //------------------------------------------------------------------------------------------------------ 57 | // 58 | //------------------------------------------------------------------------------------------------------ 59 | 60 | input logic [m-1 : 0] idat_a ; 61 | input logic [m-1 : 0] iconst ; 62 | // 63 | output logic [m-1 : 0] odat ; 64 | 65 | //------------------------------------------------------------------------------------------------------ 66 | // 67 | //------------------------------------------------------------------------------------------------------ 68 | 69 | assign odat = gf_mult_a_by_b_const(idat_a, iconst, irrpol); 70 | 71 | endmodule 72 | -------------------------------------------------------------------------------- /rtl/bch/gf/gf_parameters.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : galua fields 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : gf_parameters.svh 5 | // Description : Galua field parameters to use inside special units 6 | // 7 | 8 | //------------------------------------------------------------------------------------------------------ 9 | // base irrectible polynomes table (base polynomes from matlab) 10 | //------------------------------------------------------------------------------------------------------ 11 | 12 | localparam int IRRPOL_TABLE [1 : 20] = '{3, 7, 11, 19, 37, 67, 131, 369, 529, 1033, 13 | 2053, 4249, 8219, 16427/*17475*/, 32771, 65581, 131081, 262273, 524387, 1048585}; 14 | 15 | //------------------------------------------------------------------------------------------------------ 16 | // GF parameters 17 | //------------------------------------------------------------------------------------------------------ 18 | 19 | parameter int m = 4; // GF (2^m) 20 | parameter int irrpol = IRRPOL_TABLE[m]; // GF (2^m) irrectible poly 21 | 22 | localparam int gf_n_max = 2**m - 1; // GF maximum size 23 | 24 | //------------------------------------------------------------------------------------------------------ 25 | // used types 26 | //------------------------------------------------------------------------------------------------------ 27 | 28 | typedef int unsigned uint_t; 29 | 30 | typedef logic [m-1 : 0] data_t; 31 | 32 | typedef data_t rom_t [0 : gf_n_max]; 33 | 34 | -------------------------------------------------------------------------------- /rtl/bch/gf/gf_syndrome_engine.sv: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | 5 | parameter int m = 1 ; 6 | parameter int irrpol = 1 ; 7 | // 8 | parameter int pDAT_W = 8 ; 9 | 10 | 11 | 12 | logic gf_syndrome_engine__isop ; 13 | logic [pDAT_W-1 : 0] gf_syndrome_engine__idat ; 14 | logic [pDAT_W-1 : 0] gf_syndrome_engine__idat_mask ; 15 | logic [m-1 : 0] gf_syndrome_engine__ialpha ; 16 | logic [m-1 : 0] gf_syndrome_engine__isyndrome ; 17 | logic [m-1 : 0] gf_syndrome_engine__osyndrome ; 18 | 19 | 20 | 21 | gf_syndrome_engine 22 | #( 23 | .m ( m ) , 24 | .irrpol ( irrpol ) , 25 | // 26 | .pDAT_W ( pDAT_W ) 27 | ) 28 | gf_syndrome_engine 29 | ( 30 | .isop ( gf_syndrome_engine__isop ) , 31 | .idat ( gf_syndrome_engine__idat ) , 32 | .idat_mask ( gf_syndrome_engine__idat_mask ) , 33 | .ialpha ( gf_syndrome_engine__ialpha ) , 34 | .isyndrome ( gf_syndrome_engine__isyndrome ) , 35 | .osyndrome ( gf_syndrome_engine__osyndrome ) 36 | ); 37 | 38 | 39 | assign gf_syndrome_engine__isop = '0 ; 40 | assign gf_syndrome_engine__idat = '0 ; 41 | assign gf_syndrome_engine__idat_mask = '0 ; 42 | assign gf_syndrome_engine__ialpha = '0 ; 43 | assign gf_syndrome_engine__isyndrome = '0 ; 44 | 45 | 46 | 47 | */ 48 | 49 | // 50 | // Project : galua fields 51 | // Author : Shekhalev Denis (des00) 52 | // Workfile : gf_syndrome_engine.sv 53 | // Description : Galua field syndrome counter logic for multibit words (!!! LSB first !!!) to use it independed from other project 54 | // 55 | 56 | module gf_syndrome_engine 57 | ( 58 | isop , 59 | idat , 60 | idat_mask , 61 | ialpha , 62 | isyndrome , 63 | osyndrome 64 | ); 65 | 66 | parameter int pDAT_W = 8; 67 | 68 | `include "gf_parameters.svh" 69 | `include "gf_functions.svh" 70 | 71 | //------------------------------------------------------------------------------------------------------ 72 | // 73 | //------------------------------------------------------------------------------------------------------ 74 | 75 | input logic isop ; 76 | input logic [pDAT_W-1 : 0] idat ; 77 | input logic [pDAT_W-1 : 0] idat_mask ; 78 | input logic [m-1 : 0] ialpha ; 79 | input logic [m-1 : 0] isyndrome ; 80 | output logic [m-1 : 0] osyndrome ; 81 | 82 | //------------------------------------------------------------------------------------------------------ 83 | // 84 | //------------------------------------------------------------------------------------------------------ 85 | 86 | always_comb begin 87 | osyndrome = isyndrome; 88 | for (int b = 0; b < pDAT_W; b++) begin 89 | if ((b == 0) & isop) begin 90 | osyndrome = {{{m-1}{1'b0}}, idat[b]}; 91 | end 92 | else begin 93 | if (idat_mask[b]) begin // for codes with fractional part 94 | osyndrome = {{{m-1}{1'b0}}, idat[b]} ^ gf_mult_a_by_b_const(osyndrome, ialpha); 95 | end 96 | end 97 | end 98 | end 99 | 100 | endmodule 101 | -------------------------------------------------------------------------------- /rtl/btc/README.md: -------------------------------------------------------------------------------- 1 | Wimax 802.16-2012 BTC code based upon Turbo Product Code (TPC). 2 | 3 | Coder/Decoder architecture base upon least RAMB resources using. Decoder use soft decision engines for SPC and Extended Hamming code. 4 | 5 | This units can switch component code modes SPC/eHAM and size 8/16/32/64 each block independetly. 6 | 7 | Decoder input/core/output work in different clock domains. Decoder can use up to 8 engines to increase throughput 8 | 9 | vivado 2020.2 Kintex 7 - 2 10 | 11 | Encoder : LUT/REG/RAMB ~310/~300/1.5 >250MHz (up to 250Mbps) 12 | 13 | Decoder settings : pLLR_W = 4 bits, 4 iterations 14 | 15 | Decoder : LUT/REG/RAMB 5.5k/6k/2.5 >250MHz (~100-200Mbps for single engine decoder) 16 | 17 | Decoder performance for 4 iteration: 18 | 19 | (57, 64)x(57, 64) = 4889 tick 20 | 21 | (26, 32)x(26, 32) = 1561 tick 22 | 23 | (11, 16)x(11, 16) = 665 tick 24 | 25 | (4, 8)x(4, 8) = 345 tick 26 | 27 | (63, 64)x(63, 64) = 4743 tick 28 | 29 | (31, 32)x(31, 32) = 1417 tick 30 | 31 | (15, 16)x(15, 16) = 521 tick 32 | 33 | (7, 8)x(7, 8) = 256 tick 34 | 35 | Attention: There is no any code shortening(!!!). The coder and decoder correspond each other but can have different bit order with standard codes. 36 | -------------------------------------------------------------------------------- /rtl/btc/dec/btc_dec_mem.sv: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | 5 | parameter int pADDR_W = 256 ; 6 | parameter int pDAT_W = 8 ; 7 | parameter bit pNO_REG = 0 ; 8 | 9 | 10 | logic codec_mem__iclk ; 11 | logic codec_mem__ireset ; 12 | logic codec_mem__iclkena ; 13 | // 14 | logic codec_mem__iwrite ; 15 | logic [pADDR_W-1 : 0] codec_mem__iwaddr ; 16 | logic [pDAT_W-1 : 0] codec_mem__iwdat ; 17 | // 18 | logic [pADDR_W-1 : 0] codec_mem__iraddr ; 19 | logic [pDAT_W-1 : 0] codec_mem__ordat ; 20 | 21 | 22 | 23 | btc_dec_mem 24 | #( 25 | .pADDR_W ( pADDR_W ) , 26 | .pDAT_W ( pDAT_W ) , 27 | .pNO_REG ( pNO_REG ) 28 | ) 29 | btc_dec_mem 30 | ( 31 | .iclk ( codec_mem__iclk ) , 32 | .ireset ( codec_mem__ireset ) , 33 | .iclkena ( codec_mem__iclkena ) , 34 | // 35 | .iwrite ( codec_mem__iwrite ) , 36 | .iwaddr ( codec_mem__iwaddr ) , 37 | .iwdat ( codec_mem__iwdat ) , 38 | // 39 | .iraddr ( codec_mem__iraddr ) , 40 | .ordat ( codec_mem__ordat ) 41 | ); 42 | 43 | 44 | assign codec_mem__iclk = '0 ; 45 | assign codec_mem__ireset = '0 ; 46 | assign codec_mem__iclkena = '0 ; 47 | // 48 | assign codec_mem__iwrite = '0 ; 49 | assign codec_mem__iwaddr = '0 ; 50 | assign codec_mem__iwdat = '0 ; 51 | // 52 | assign codec_mem__iraddr = '0 ; 53 | 54 | 55 | 56 | */ 57 | 58 | // 59 | // Project : wimax BTC 60 | // Author : Shekhalev Denis (des00) 61 | // Workfile : btc_dec_mem.sv 62 | // Description : simple small sized ram with output delay 0/1 tick 63 | 64 | 65 | module btc_dec_mem 66 | #( 67 | parameter int pADDR_W = 8 , 68 | parameter int pDAT_W = 8 , 69 | parameter bit pNO_REG = 0 70 | ) 71 | ( 72 | iclk , 73 | ireset , 74 | iclkena , 75 | // 76 | iwrite , 77 | iwaddr , 78 | iwdat , 79 | // 80 | iraddr , 81 | ordat 82 | ); 83 | 84 | //------------------------------------------------------------------------------------------------------ 85 | // 86 | //------------------------------------------------------------------------------------------------------ 87 | 88 | input logic iclk ; 89 | input logic ireset ; 90 | input logic iclkena ; 91 | // 92 | input logic iwrite ; 93 | input logic [pADDR_W-1 : 0] iwaddr ; 94 | input logic [pDAT_W-1 : 0] iwdat ; 95 | // 96 | input logic [pADDR_W-1 : 0] iraddr ; 97 | output logic [pDAT_W-1 : 0] ordat ; 98 | 99 | //------------------------------------------------------------------------------------------------------ 100 | // 101 | //------------------------------------------------------------------------------------------------------ 102 | 103 | bit [pDAT_W-1 : 0] mem [2**pADDR_W] /* synthesis ramstyle = "no_rw_check" */; 104 | 105 | //------------------------------------------------------------------------------------------------------ 106 | // 107 | //------------------------------------------------------------------------------------------------------ 108 | 109 | always_ff @(posedge iclk) begin 110 | if (iclkena) begin 111 | if (iwrite) begin 112 | mem[iwaddr] <= iwdat; 113 | end 114 | end 115 | end 116 | 117 | generate 118 | if (pNO_REG) begin 119 | assign ordat = mem[iraddr]; 120 | end 121 | else begin 122 | always_ff @(posedge iclk) begin 123 | if (iclkena) begin 124 | ordat <= mem[iraddr]; 125 | end 126 | end 127 | end 128 | endgenerate 129 | 130 | endmodule 131 | -------------------------------------------------------------------------------- /rtl/btc/dec/btc_dec_types.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : wimax BTC 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : btc_dec_types.svh 5 | // Description : decoder parameters/types & etc 6 | // 7 | 8 | //------------------------------------------------------------------------------------------------------ 9 | // decoder parameters 10 | //------------------------------------------------------------------------------------------------------ 11 | 12 | parameter int pLLR_W = 4; 13 | parameter int pEXTR_W = pLLR_W + 1; // +1 bit at least 14 | 15 | parameter int pMETRIC_W = pEXTR_W + 3; // * 4 times for fast chase + 1 for decision 16 | 17 | //------------------------------------------------------------------------------------------------------ 18 | // used data types 19 | //------------------------------------------------------------------------------------------------------ 20 | 21 | // control strobes type 22 | typedef struct packed { 23 | logic sof; 24 | logic sop; 25 | logic eop; 26 | logic eof; 27 | } strb_t; 28 | 29 | //------------------------------------------------------------------------------------------------------ 30 | // soft decoders types 31 | //------------------------------------------------------------------------------------------------------ 32 | 33 | typedef logic signed [pLLR_W-1 : 0] llr_t; 34 | typedef logic signed [pEXTR_W-1 : 0] extr_t; 35 | typedef logic signed [pEXTR_W : 0] extr_p1_t; // +1 for add functions 36 | typedef logic signed [pMETRIC_W-1 : 0] metric_t; 37 | 38 | typedef logic [pEXTR_W-1 : 0] uextr_t; // unsigned for search 39 | 40 | //------------------------------------------------------------------------------------------------------ 41 | // extrinsic scale types 42 | //------------------------------------------------------------------------------------------------------ 43 | 44 | typedef logic [2 : 0] alpha_t; 45 | 46 | localparam alpha_t cALPHA_0 = 0; // 3'b000; 47 | localparam alpha_t cALPHA_0p125 = 1; // 3'b001; 48 | localparam alpha_t cALPHA_0p25 = 2; // 3'b010; 49 | localparam alpha_t cALPHA_0p5 = 3; // 3'b011; 50 | localparam alpha_t cALPHA_1 = 4; // 3'b100; 51 | 52 | //------------------------------------------------------------------------------------------------------ 53 | // usefull functions 54 | //------------------------------------------------------------------------------------------------------ 55 | 56 | function extr_t do_scale (input extr_t data, alpha_t alpha); 57 | bit mask; 58 | begin 59 | do_scale = '0; 60 | case (alpha) 61 | cALPHA_1 : do_scale = data; 62 | cALPHA_0p5 : begin 63 | mask = data[0] & data[$high(data)]; 64 | do_scale = ((data <<< 2) + (mask ? 0 : 4)) >>> 3; 65 | end 66 | cALPHA_0p25 : begin 67 | mask = !data[0] & data[$high(data)]; 68 | do_scale = ((data <<< 1) + (mask ? 0 : 4)) >>> 3; 69 | end 70 | cALPHA_0p125 : begin; 71 | mask = (data[1:0] == 0) & data[$high(data)]; 72 | do_scale = (data + (mask ? 0 : 4)) >>> 3; 73 | end 74 | endcase 75 | end 76 | endfunction 77 | 78 | -------------------------------------------------------------------------------- /rtl/buffer/codec_mem_ablock.sv: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | 5 | parameter int pADDR_W = 256 ; 6 | parameter int pDAT_W = 8 ; 7 | parameter bit pPIPE = 1 ; 8 | 9 | 10 | 11 | logic codec_mem_ablock__ireset ; 12 | // 13 | logic codec_mem_ablock__iwclk ; 14 | logic codec_mem_ablock__iwclkena ; 15 | logic codec_mem_ablock__iwrite ; 16 | logic [pADDR_W-1 : 0] codec_mem_ablock__iwaddr ; 17 | logic [pDAT_W-1 : 0] codec_mem_ablock__iwdat ; 18 | // 19 | logic codec_mem_ablock__irclk ; 20 | logic codec_mem_ablock__irclkena ; 21 | logic [pADDR_W-1 : 0] codec_mem_ablock__iraddr ; 22 | logic [pDAT_W-1 : 0] codec_mem_ablock__ordat ; 23 | 24 | 25 | 26 | codec_mem_ablock 27 | #( 28 | .pADDR_W ( pADDR_W ) , 29 | .pDAT_W ( pDAT_W ) , 30 | .pPIPE ( pPIPE ) 31 | ) 32 | codec_mem_ablock 33 | ( 34 | .ireset ( codec_mem_ablock__ireset ) , 35 | // 36 | .iwclk ( codec_mem_ablock__iwclk ) , 37 | .iwclkena ( codec_mem_ablock__iwclkena ) , 38 | .iwrite ( codec_mem_ablock__iwrite ) , 39 | .iwaddr ( codec_mem_ablock__iwaddr ) , 40 | .iwdat ( codec_mem_ablock__iwdat ) , 41 | // 42 | .irclk ( codec_mem_ablock__irclk ) , 43 | .irclkena ( codec_mem_ablock__irclkena ) , 44 | .iraddr ( codec_mem_ablock__iraddr ) , 45 | .ordat ( codec_mem_ablock__ordat ) 46 | ); 47 | 48 | 49 | assign codec_mem_ablock__ireset = '0 ; 50 | // 51 | assign codec_mem_ablock__iwclk = '0 ; 52 | assign codec_mem_ablock__iwclkena = '0 ; 53 | assign codec_mem_ablock__iwrite = '0 ; 54 | assign codec_mem_ablock__iwaddr = '0 ; 55 | assign codec_mem_ablock__iwdat = '0 ; 56 | // 57 | assign codec_mem_ablock__irclk = '0 ; 58 | assign codec_mem_ablock__irclkena = '0 ; 59 | assign codec_mem_ablock__iraddr = '0 ; 60 | 61 | 62 | 63 | */ 64 | 65 | // 66 | // Project : coding library 67 | // Author : Shekhalev Denis (des00) 68 | // Workfile : codec_mem_ablock.sv 69 | // Description : Simple dual clock (asynchronus) dual port ram with optional pipeline register 70 | // 71 | 72 | 73 | module codec_mem_ablock 74 | #( 75 | parameter int pADDR_W = 256 , 76 | parameter int pDAT_W = 8 , 77 | parameter bit pPIPE = 1 78 | ) 79 | ( 80 | ireset , 81 | // 82 | iwclk , 83 | iwclkena , 84 | iwrite , 85 | iwaddr , 86 | iwdat , 87 | // 88 | irclk , 89 | irclkena , 90 | iraddr , 91 | ordat 92 | ); 93 | 94 | //------------------------------------------------------------------------------------------------------ 95 | // 96 | //------------------------------------------------------------------------------------------------------ 97 | 98 | input logic ireset ; 99 | // 100 | input logic iwclk ; 101 | input logic iwclkena ; 102 | input logic iwrite ; 103 | input logic [pADDR_W-1 : 0] iwaddr ; 104 | input logic [pDAT_W-1 : 0] iwdat ; 105 | // 106 | input logic irclk ; 107 | input logic irclkena ; 108 | input logic [pADDR_W-1 : 0] iraddr ; 109 | output logic [pDAT_W-1 : 0] ordat ; 110 | 111 | //------------------------------------------------------------------------------------------------------ 112 | // 113 | //------------------------------------------------------------------------------------------------------ 114 | 115 | bit [pDAT_W-1 : 0] mem [2**pADDR_W] /* synthesis ramstyle = "no_rw_check" */; 116 | logic [pDAT_W-1 : 0] rdat [2]; 117 | 118 | //------------------------------------------------------------------------------------------------------ 119 | // 120 | //------------------------------------------------------------------------------------------------------ 121 | 122 | always_ff @(posedge irclk) begin 123 | if (irclkena) begin 124 | rdat[0] <= mem[iraddr]; 125 | rdat[1] <= rdat[0]; 126 | end 127 | end 128 | 129 | assign ordat = rdat[pPIPE]; 130 | 131 | always_ff @(posedge iwclk) begin 132 | if (iwclkena) begin 133 | if (iwrite) begin 134 | mem[iwaddr] <= iwdat; 135 | end 136 | end 137 | end 138 | 139 | endmodule 140 | -------------------------------------------------------------------------------- /rtl/buffer/codec_mem_block.sv: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | 5 | parameter int pADDR_W = 256 ; 6 | parameter int pDAT_W = 8 ; 7 | parameter bit pPIPE = 1 ; 8 | 9 | 10 | 11 | logic codec_mem_block__iclk ; 12 | logic codec_mem_block__ireset ; 13 | logic codec_mem_block__iclkena ; 14 | // 15 | logic codec_mem_block__iwrite ; 16 | logic [pADDR_W-1 : 0] codec_mem_block__iwaddr ; 17 | logic [pDAT_W-1 : 0] codec_mem_block__iwdat ; 18 | // 19 | logic [pADDR_W-1 : 0] codec_mem_block__iraddr ; 20 | logic [pDAT_W-1 : 0] codec_mem_block__ordat ; 21 | 22 | 23 | 24 | codec_mem_block 25 | #( 26 | .pADDR_W ( pADDR_W ) , 27 | .pDAT_W ( pDAT_W ) , 28 | .pPIPE ( pPIPE ) 29 | ) 30 | codec_mem_block 31 | ( 32 | .iclk ( codec_mem_block__iclk ) , 33 | .ireset ( codec_mem_block__ireset ) , 34 | .iclkena ( codec_mem_block__iclkena ) , 35 | // 36 | .iwrite ( codec_mem_block__iwrite ) , 37 | .iwaddr ( codec_mem_block__iwaddr ) , 38 | .iwdat ( codec_mem_block__iwdat ) , 39 | // 40 | .iraddr ( codec_mem_block__iraddr ) , 41 | .ordat ( codec_mem_block__ordat ) 42 | ); 43 | 44 | 45 | assign codec_mem_block__iclk = '0 ; 46 | assign codec_mem_block__ireset = '0 ; 47 | assign codec_mem_block__iclkena = '0 ; 48 | // 49 | assign codec_mem_block__iwrite = '0 ; 50 | assign codec_mem_block__iwaddr = '0 ; 51 | assign codec_mem_block__iwdat = '0 ; 52 | // 53 | assign codec_mem_block__iraddr = '0 ; 54 | 55 | 56 | 57 | */ 58 | 59 | // 60 | // Project : coding library 61 | // Author : Shekhalev Denis (des00) 62 | // Workfile : codec_mem_block.sv 63 | // Description : Simple dual port ram with optional pipeline register 64 | // 65 | 66 | 67 | module codec_mem_block 68 | #( 69 | parameter int pADDR_W = 8 , 70 | parameter int pDAT_W = 8 , 71 | parameter bit pPIPE = 1 72 | ) 73 | ( 74 | iclk , 75 | ireset , 76 | iclkena , 77 | // 78 | iwrite , 79 | iwaddr , 80 | iwdat , 81 | // 82 | iraddr , 83 | ordat 84 | ); 85 | 86 | //------------------------------------------------------------------------------------------------------ 87 | // 88 | //------------------------------------------------------------------------------------------------------ 89 | 90 | input logic iclk ; 91 | input logic ireset ; 92 | input logic iclkena ; 93 | // 94 | input logic iwrite ; 95 | input logic [pADDR_W-1 : 0] iwaddr ; 96 | input logic [pDAT_W-1 : 0] iwdat ; 97 | // 98 | input logic [pADDR_W-1 : 0] iraddr ; 99 | output logic [pDAT_W-1 : 0] ordat ; 100 | 101 | //------------------------------------------------------------------------------------------------------ 102 | // 103 | //------------------------------------------------------------------------------------------------------ 104 | 105 | bit [pDAT_W-1 : 0] mem [2**pADDR_W] /* synthesis ramstyle = "no_rw_check" */; 106 | logic [pDAT_W-1 : 0] rdat [2]; 107 | 108 | //------------------------------------------------------------------------------------------------------ 109 | // 110 | //------------------------------------------------------------------------------------------------------ 111 | 112 | always_ff @(posedge iclk) begin 113 | if (iclkena) begin 114 | rdat[0] <= mem[iraddr]; 115 | rdat[1] <= rdat[0]; 116 | // 117 | if (iwrite) begin 118 | mem[iwaddr] <= iwdat; 119 | end 120 | end 121 | end 122 | 123 | assign ordat = rdat[pPIPE]; 124 | 125 | endmodule 126 | -------------------------------------------------------------------------------- /rtl/ccsds_turbo/README.md: -------------------------------------------------------------------------------- 1 | Convolution turbocode from Green Boook CCSDS 130.1-G-2. 2 | 3 | Decoder use MAX-Log Map algorithm and module arithmetic for state registers with extrinsic metric self-corrected algorithm. 4 | Special Extrinsic Memory Architecture give 1 bit per tick decoding speed. 5 | 6 | 7 | vivado 2019.1 Artix 7 - 2 8 | 9 | data size 1784*5 = 8920 bit, coderate 1/6, decoder iteration = 10 10 | 11 | Encoder : LUT/REG/RAMB 175/187/2.0 ~200MHz (33Mbps -> 200Mbps) 12 | 13 | Decoder : LUT/REG/RAMB 4k/4.2K/125.0 ~160MHz (48Mbps -> 8Mbps) 14 | -------------------------------------------------------------------------------- /rtl/ccsds_turbo/ccsds_turbo_parameters.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : ccsds turbo 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : ccsds_parameters.svh 5 | // Description : 6 | // 7 | 8 | localparam int cN_TAB [4] = '{223*8*1, 223*8*2, 223*8*4, 223*8*5}; 9 | 10 | //------------------------------------------------------------------------------------------------------ 11 | // permutation address logic base data width 12 | //------------------------------------------------------------------------------------------------------ 13 | 14 | parameter int cW = 14; // don't change 15 | 16 | typedef logic [cW-1 : 0] ptab_dat_t; 17 | 18 | //------------------------------------------------------------------------------------------------------ 19 | // 20 | //------------------------------------------------------------------------------------------------------ 21 | 22 | // 23 | // code constants to use instead of digits 24 | typedef enum bit [1 : 0] { 25 | cCODE_1by2 = 2'h0, 26 | cCODE_1by3 = 2'h1, 27 | cCODE_1by4 = 2'h2, 28 | cCODE_1by6 = 2'h3 29 | } ccsds_turbo_code_t; 30 | 31 | //------------------------------------------------------------------------------------------------------ 32 | // 33 | //------------------------------------------------------------------------------------------------------ 34 | -------------------------------------------------------------------------------- /rtl/ccsds_turbo/ccsds_turbo_ptable.sv: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | 5 | 6 | logic ccsds_turbo_ptable__iclk 7 | logic ccsds_turbo_ptable__ireset ; 8 | logic ccsds_turbo_ptable__iclkena ; 9 | logic [1 : 0] ccsds_turbo_ptable__icode ; 10 | logic [1 : 0] ccsds_turbo_ptable__inidx ; 11 | ptab_dat_t ccsds_turbo_ptable__oN ; 12 | ptab_dat_t ccsds_turbo_ptable__oNp3 ; 13 | ptab_dat_t ccsds_turbo_ptable__oK2 ; 14 | ptab_dat_t ccsds_turbo_ptable__oP [4] ; 15 | ptab_dat_t ccsds_turbo_ptable__oPcomp [4] ; 16 | 17 | 18 | 19 | 20 | ccsds_turbo_ptable 21 | ccsds_turbo_ptable 22 | ( 23 | .iclk ( ccsds_turbo_ptable__iclk ) , 24 | .ireset ( ccsds_turbo_ptable__ireset ) , 25 | .iclkena ( ccsds_turbo_ptable__iclkena ) , 26 | .icode ( ccsds_turbo_ptable__icode ) , 27 | .inidx ( ccsds_turbo_ptable__inidx ) , 28 | .oN ( ccsds_turbo_ptable__oN ) , 29 | .oNp3 ( ccsds_turbo_ptable__oNp3 ) , 30 | .oK2 ( ccsds_turbo_ptable__oK2 ) , 31 | .oP ( ccsds_turbo_ptable__oP ) , 32 | .oPcomp ( ccsds_turbo_ptable__oPcomp ) 33 | ); 34 | 35 | 36 | assign ccsds_turbo_ptable__iclk = '0 ; 37 | assign ccsds_turbo_ptable__ireset = '0 ; 38 | assign ccsds_turbo_ptable__iclkena = '0 ; 39 | assign ccsds_turbo_ptable__icode = '0 ; 40 | assign ccsds_turbo_ptable__inidx = '0 ; 41 | 42 | 43 | 44 | */ 45 | 46 | // 47 | // Project : ccsds_turbo 48 | // Author : Shekhalev Denis (des00) 49 | // Workfile : ccsds_turbo_ptable.sv 50 | // Description : Permutation parameters table. It takes 1 clock cycles to apply new parameters 51 | // 52 | 53 | module ccsds_turbo_ptable 54 | ( 55 | iclk , 56 | ireset , 57 | iclkena , 58 | // 59 | icode , 60 | inidx , 61 | // 62 | oN , 63 | oNp3 , 64 | // 65 | oK2 , 66 | oP , 67 | oPcomp 68 | ); 69 | 70 | `include "ccsds_turbo_parameters.svh" 71 | 72 | //------------------------------------------------------------------------------------------------------ 73 | // 74 | //------------------------------------------------------------------------------------------------------ 75 | 76 | input logic iclk ; 77 | input logic ireset ; 78 | input logic iclkena ; 79 | // 80 | input logic [1 : 0] icode ; 81 | input logic [1 : 0] inidx ; 82 | // 83 | output ptab_dat_t oN ; 84 | output ptab_dat_t oNp3 ; 85 | output ptab_dat_t oK2 ; 86 | // 87 | output ptab_dat_t oP [4] ; 88 | output ptab_dat_t oPcomp [4] ; // complement oP for backward recursion address process 89 | 90 | //------------------------------------------------------------------------------------------------------ 91 | // 92 | //------------------------------------------------------------------------------------------------------ 93 | 94 | localparam int cK2_TAB [4] = '{223*1, 223*2, 223*4, 223*5}; 95 | 96 | localparam int cP_TAB [4] = '{31, 37, 43, 47}; 97 | 98 | localparam int cPCOMP_TAB [4][4] = '{ 99 | '{ 192, 186, 180, 176} , 100 | '{ 415, 409, 403, 399} , 101 | '{ 861, 855, 849, 845} , 102 | '{1084, 1078, 1072, 1068}}; 103 | 104 | //------------------------------------------------------------------------------------------------------ 105 | // 106 | //------------------------------------------------------------------------------------------------------ 107 | 108 | always_ff @(posedge iclk) begin 109 | if (iclkena) begin 110 | oN <= cN_TAB [inidx]; 111 | oNp3 <= cN_TAB [inidx] + 4 - 1; 112 | oK2 <= cK2_TAB[inidx]; 113 | // 114 | for (int i = 0; i < 4; i++) begin 115 | oP [i] <= cP_TAB [i]; 116 | oPcomp[i] <= cPCOMP_TAB [inidx][i]; 117 | end 118 | end 119 | end 120 | 121 | endmodule 122 | -------------------------------------------------------------------------------- /rtl/ccsds_turbo/ccsds_turbo_trellis.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : ccsds turbo 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : ccsds_turbo_trellis.svh 5 | // Description : file with trellis generate functions 6 | // 7 | 8 | //------------------------------------------------------------------------------------------------------ 9 | // define types and functions to get trellis 10 | //------------------------------------------------------------------------------------------------------ 11 | 12 | typedef struct { 13 | bit [3 : 0] nextStates [16][2]; 14 | bit [3 : 0] preStates [16][2]; 15 | bit [2 : 0] outputs [16][2]; 16 | bit outputsa1 [16][2]; 17 | bit outputsa2 [16][2]; 18 | bit outputsa3 [16][2]; 19 | } trellis_t; 20 | 21 | localparam trellis_t trel = get_trellis (0); 22 | 23 | //------------------------------------------------------------------------------------------------------ 24 | // function's to get rsc trellis 25 | //------------------------------------------------------------------------------------------------------ 26 | 27 | function trellis_t get_trellis (input int tmp); 28 | trellis_t trel; 29 | bit [3 : 0] nstate; 30 | bit a1, a2, a3; 31 | begin 32 | for (int a0 = 0; a0 < 2; a0++) begin 33 | for (int state = 0; state < 16; state++) begin 34 | nstate = {a0[0] ^ state[1] ^ state[0], state[3:1]}; // feedback [1 0 0 1 1] G0 35 | 36 | a1 = nstate[3] ^ state[3] ^ state[1] ^ state[0]; // [1 1 0 1 1] G1 37 | a2 = nstate[3] ^ state[2] ^ state[0]; // [1 0 1 0 1] G2 38 | a3 = nstate[3] ^ state[3] ^ state[2] ^ state[1] ^ state[0]; // [1 1 1 1 1] G3 39 | 40 | // 41 | trel.nextStates[state][a0] = nstate; 42 | trel.outputsa1 [state][a0] = a1; 43 | trel.outputsa2 [state][a0] = a2; 44 | trel.outputsa3 [state][a0] = a3; 45 | trel.outputs [state][a0] = {a3, a2, a1}; 46 | end 47 | end 48 | // 49 | for (int a0 = 0; a0 < 2; a0++) begin 50 | for (int state = 0; state < 16; state++) begin 51 | nstate = trel.nextStates[state][a0]; 52 | trel.preStates[nstate][a0] = state[3 : 0]; 53 | end 54 | end 55 | // 56 | get_trellis = trel; 57 | end 58 | endfunction 59 | 60 | // synthesis translate_off 61 | function automatic void log_trellis (input int do_print = 1); 62 | int fp; 63 | begin 64 | if (do_print) begin 65 | fp = $fopen("ccsdc_trellis.log", "w"); 66 | // 67 | for (int state = 0; state < 16; state++) begin 68 | for (int b = 0; b < 2; b++) begin 69 | $fdisplay(fp, "trel[%0d][%b] -> %0d (state) %b(output) %0d (pre_state)", state[3 : 0], b[0], trel.nextStates[state][b], trel.outputs[state][b], trel.preStates[state][b]); 70 | end 71 | $fdisplay(fp,""); 72 | end 73 | // 74 | $fclose(fp); 75 | end 76 | else begin 77 | for (int state = 0; state < 16; state++) begin 78 | for (int b = 0; b < 2; b++) begin 79 | $display("trel[%0d][%b] -> %0d (state) %b(output) %0d (pre_state)", state[3 : 0], b[0], trel.nextStates[state][b], trel.outputs[state][b], trel.preStates[state][b]); 80 | end 81 | $display(""); 82 | end 83 | end 84 | end 85 | endfunction 86 | // synthesis translate_on 87 | 88 | function logic [8 : 0] do_encode (input logic a0, input logic [3 : 0] state); 89 | logic [3 : 0] nstate; 90 | logic a1, a2, a3; 91 | logic term; 92 | begin 93 | nstate = {a0 ^ state[1] ^ state[0], state[3:1]}; // feedback [1 0 0 1 1] G0 94 | 95 | a1 = nstate[3] ^ state[3] ^ state[1] ^ state[0]; // [1 1 0 1 1] G1 96 | a2 = nstate[3] ^ state[2] ^ state[0]; // [1 0 1 0 1] G2 97 | a3 = nstate[3] ^ state[3] ^ state[2] ^ state[1] ^ state[0]; // [1 1 1 1 1] G3 98 | 99 | term = nstate[1] ^ nstate[0]; 100 | 101 | do_encode = {term, a3, a2, a1, a0, nstate}; 102 | end 103 | endfunction 104 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /rtl/ccsds_turbo/dec/ccsds_turbo_dec_types.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : ccsds_turbo 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : ccsds_turbo_dec_types.sv 5 | // Description : file with all decoder used types 6 | // 7 | 8 | localparam int cSTATE_NUM = 16; 9 | localparam int cBIT_NUM = 2; 10 | 11 | localparam int cBLLR_W = pLLR_W + 2; // +2 bit parity metric is b0 + b1 + b2 12 | localparam int cL_EXT_W = pLLR_W + 3; // Lextrinsic ~= 8*pLLR_W 13 | 14 | localparam int cSTATE_W = cL_EXT_W + 3; // state(k) ~= Lextrinsic + gamma + state(k) 15 | localparam int cGAMMA_W = cSTATE_W + 1; // Lextrinsic + gammaL + alpha(k) + beta(k+1) 16 | 17 | // 18 | // single word type 19 | typedef logic signed [pLLR_W-1 : 0] bit_llr_t; 20 | typedef logic signed [cBLLR_W-1 : 0] pbit_llr_t; 21 | typedef logic signed [cL_EXT_W-1 : 0] extr_llr_t; 22 | 23 | typedef logic signed [cSTATE_W-1 : 0] trel_state_t; 24 | 25 | typedef logic signed [cGAMMA_W-1 : 0] trel_branch_t; 26 | typedef logic signed [cGAMMA_W : 0] trel_branch_p1_t; 27 | 28 | // complex types 29 | typedef trel_state_t Lapri_t ; 30 | typedef trel_branch_t Lapo_t ; 31 | 32 | typedef struct packed { 33 | logic pre_sign; 34 | logic pre_zero; 35 | extr_llr_t value; 36 | } Lextr_t; 37 | 38 | // 39 | // arrays type 40 | typedef pbit_llr_t pbit_allr_t [1:7]; 41 | 42 | typedef trel_state_t state_t [cSTATE_NUM]; 43 | typedef trel_state_t gamma_t [cSTATE_NUM][cBIT_NUM]; 44 | 45 | typedef trel_branch_t bm_t [cSTATE_NUM][cBIT_NUM]; 46 | 47 | -------------------------------------------------------------------------------- /rtl/ccsds_turbo/dec/ccsds_turbo_mmax.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : ccsds_turbo 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : ccsds_turbo_mmax.sv 5 | // Description : file with MAX* function realisation for different decoder data types 6 | // 7 | 8 | //------------------------------------------------------------------------------------------------------ 9 | // define used MAX* functions 10 | //------------------------------------------------------------------------------------------------------ 11 | 12 | function trel_state_t st_mmax (input trel_state_t a, b); 13 | st_mmax = (a > b) ? a : b; 14 | endfunction 15 | 16 | // 17 | // module based max for state processor 18 | function trel_state_t st_m_mmax (input trel_state_t a, b); 19 | trel_state_t tmp; 20 | begin 21 | tmp = a - b; 22 | st_m_mmax = tmp[cSTATE_W-1] ? b : a; 23 | end 24 | endfunction 25 | 26 | function trel_branch_t bm_mmax (input trel_branch_t a, b); 27 | bm_mmax = (a > b) ? a : b; 28 | endfunction 29 | 30 | function trel_branch_t bm_mmax1 (input trel_branch_t a, b); 31 | trel_branch_p1_t tmp; 32 | begin 33 | tmp = a - b; 34 | bm_mmax1 = (tmp[cGAMMA_W] ? b : a) + (~|tmp[cGAMMA_W : pLLR_FP+1] | &tmp[cGAMMA_W : pLLR_FP+1]); 35 | end 36 | endfunction 37 | -------------------------------------------------------------------------------- /rtl/codec_reset_synchronizer.sv: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | 5 | parameter int pLENGTH = 4; 6 | 7 | 8 | 9 | logic codec_reset_synchronizer__clk ; 10 | logic codec_reset_synchronizer__reset_carry_in ; 11 | logic codec_reset_synchronizer__reset_in ; 12 | logic codec_reset_synchronizer__reset_out ; 13 | 14 | 15 | 16 | codec_reset_synchronizer 17 | #( 18 | .pLENGTH ( pLENGTH ) 19 | ) 20 | codec_reset_synchronizer 21 | ( 22 | .clk ( codec_reset_synchronizer__clk ) , 23 | .reset_carry_in ( codec_reset_synchronizer__reset_carry_in ) , 24 | .reset_in ( codec_reset_synchronizer__reset_in ) , 25 | .reset_out ( codec_reset_synchronizer__reset_out ) 26 | ); 27 | 28 | 29 | assign codec_reset_synchronizer__clk = '0 ; 30 | assign codec_reset_synchronizer__reset_carry_in = '0 ; 31 | assign codec_reset_synchronizer__reset_in = '0 ; 32 | 33 | 34 | 35 | */ 36 | 37 | // 38 | // Project : coding library 39 | // Author : Shekhalev Denis (des00) 40 | // Workfile : codec_reset_synchronizer.sv 41 | // Description : reset synchronizer with reset carry in to use in asynchronus codecs 42 | // 43 | 44 | module codec_reset_synchronizer 45 | #( 46 | parameter int pLENGTH = 4 47 | ) 48 | ( 49 | clk , 50 | reset_carry_in , 51 | reset_in , 52 | reset_out 53 | ); 54 | 55 | //------------------------------------------------------------------------------------------------------ 56 | // 57 | //------------------------------------------------------------------------------------------------------ 58 | 59 | input logic clk ; 60 | input logic reset_in ; 61 | input logic reset_carry_in; 62 | output logic reset_out ; 63 | 64 | //------------------------------------------------------------------------------------------------------ 65 | // 66 | //------------------------------------------------------------------------------------------------------ 67 | 68 | logic [pLENGTH-1:0] reset_srl; 69 | 70 | //------------------------------------------------------------------------------------------------------ 71 | // 72 | //------------------------------------------------------------------------------------------------------ 73 | 74 | always_ff @(posedge clk or posedge reset_in) begin : reset_shift_register 75 | if (reset_in) begin 76 | reset_srl <= '1; 77 | end 78 | else begin 79 | reset_srl <= (reset_srl << 1) | reset_carry_in; 80 | end 81 | end 82 | 83 | assign reset_out = reset_srl[$high(reset_srl)]; 84 | 85 | endmodule 86 | -------------------------------------------------------------------------------- /rtl/dvb_pls/README.md: -------------------------------------------------------------------------------- 1 | DVB-S2 PSL code with scrambler and pi/2 BPSK modulation ETSI EN 302 307 V1.2.1 (2009-08) 2 | 3 | Decoder use Hadamard32 transform with maximum likelihood decoding 4 | 5 | vivado 2019.1 Kintex 7 - 2 (artix worked but has timings routing problem) 6 | 7 | Encoder : LUT/REG 74/74 >250MHz 8 | 9 | Decoder : LUT/REG 1.5k/1.3k >250MHz -------------------------------------------------------------------------------- /rtl/dvb_pls/dvb_pls_constants.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : PLS DVB-S2 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : dvb_pls_dec_constants.svh 5 | // Description : DVB PLS decoder constants 6 | // 7 | 8 | //------------------------------------------------------------------------------------------------------ 9 | // Gmatrix define 10 | //------------------------------------------------------------------------------------------------------ 11 | 12 | // matrix in reverse form & reverse row order 13 | localparam bit [0 : 31] cGMATRIX [6] = '{ 14 | 32'b11111111111111111111111111111111, 15 | 32'b00000000000000001111111111111111, 16 | 32'b00000000111111110000000011111111, 17 | 32'b00001111000011110000111100001111, 18 | 32'b00110011001100110011001100110011, 19 | 32'b01010101010101010101010101010101 20 | }; 21 | 22 | //------------------------------------------------------------------------------------------------------ 23 | // PLS scrambler 24 | //------------------------------------------------------------------------------------------------------ 25 | 26 | localparam bit [0 : 63] cSCRAMBLE_WORD = 64'b0111000110011101100000111100100101010011010000100010110111111010; 27 | 28 | //------------------------------------------------------------------------------------------------------ 29 | // Hadamard 32 matrix 30 | //------------------------------------------------------------------------------------------------------ 31 | 32 | localparam bit [31 : 0] cHADAMARD32 [32] = '{ 33 | 32'b11111111111111111111111111111111, 34 | 32'b10101010101010101010101010101010, 35 | 32'b11001100110011001100110011001100, 36 | 32'b10011001100110011001100110011001, 37 | 32'b11110000111100001111000011110000, 38 | 32'b10100101101001011010010110100101, 39 | 32'b11000011110000111100001111000011, 40 | 32'b10010110100101101001011010010110, 41 | 32'b11111111000000001111111100000000, 42 | 32'b10101010010101011010101001010101, 43 | 32'b11001100001100111100110000110011, 44 | 32'b10011001011001101001100101100110, 45 | 32'b11110000000011111111000000001111, 46 | 32'b10100101010110101010010101011010, 47 | 32'b11000011001111001100001100111100, 48 | 32'b10010110011010011001011001101001, 49 | 32'b11111111111111110000000000000000, 50 | 32'b10101010101010100101010101010101, 51 | 32'b11001100110011000011001100110011, 52 | 32'b10011001100110010110011001100110, 53 | 32'b11110000111100000000111100001111, 54 | 32'b10100101101001010101101001011010, 55 | 32'b11000011110000110011110000111100, 56 | 32'b10010110100101100110100101101001, 57 | 32'b11111111000000000000000011111111, 58 | 32'b10101010010101010101010110101010, 59 | 32'b11001100001100110011001111001100, 60 | 32'b10011001011001100110011010011001, 61 | 32'b11110000000011110000111111110000, 62 | 32'b10100101010110100101101010100101, 63 | 32'b11000011001111000011110011000011, 64 | 32'b10010110011010010110100110010110 65 | }; 66 | 67 | -------------------------------------------------------------------------------- /rtl/dvb_pls/dvb_pls_dec_types.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : PLS DVB-S2 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : dvb_pls_dec_types.svh 5 | // Description : DVB PLS decoder types 6 | // 7 | 8 | parameter int pDAT_W = 8 ; 9 | 10 | localparam int cMETRIC_W = pDAT_W + 1; // pair sum 11 | 12 | localparam int cMETRIC_SUM_W = cMETRIC_W + 5; // hadamard32 sum 13 | 14 | localparam int cMETRIX_IDX_W = $clog2(32); 15 | 16 | //------------------------------------------------------------------------------------------------------ 17 | // simple types 18 | //------------------------------------------------------------------------------------------------------ 19 | 20 | typedef logic signed [pDAT_W-1 : 0] dat_t; 21 | typedef logic signed [cMETRIC_W-1 : 0] metric_t; 22 | typedef logic signed [cMETRIC_SUM_W-1 : 0] metric_sum_t; 23 | 24 | typedef logic [cMETRIX_IDX_W-1 : 0] metric_idx_t; 25 | 26 | //------------------------------------------------------------------------------------------------------ 27 | // abs functions, remember there is saturation at input: value -2^(N-1) is immposible 28 | //------------------------------------------------------------------------------------------------------ 29 | 30 | function automatic metric_t abs_metric (input metric_t dat); 31 | begin 32 | abs_metric = (dat ^ {cMETRIC_W{dat[cMETRIC_W-1]}}) + dat[cMETRIC_W-1]; 33 | end 34 | endfunction 35 | 36 | function automatic metric_sum_t abs_metric_sum (input metric_sum_t dat); 37 | begin 38 | abs_metric_sum = (dat ^ {cMETRIC_SUM_W{dat[cMETRIC_SUM_W-1]}}) + dat[cMETRIC_SUM_W-1]; 39 | end 40 | endfunction 41 | -------------------------------------------------------------------------------- /rtl/g709/README.md: -------------------------------------------------------------------------------- 1 | ITU-T G.709 FEC realization 2 | 3 | vivado 2020.2 Kintex 7 - 2 4 | 5 | Encoder: 6 | 7 | LUT/REG ~2.4k/~2.3k > 250MHz ( > 32Gbps) 8 | 9 | Decoder: 10 | 11 | LUT/REG/RAM ~18.8K/~15.1K/10 > 250MHz ( > 32Gbps) 12 | 13 | Attention: The coder and decoder correspond each other but can have different bit order with standard codes. 14 | 15 | Decoder don't use RS code decfail decision. If decfail occured it sends incorrect bit fix to output. Change it if needed. 16 | 17 | 18 | -------------------------------------------------------------------------------- /rtl/g709/g709_types.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : fec (G.709) 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : g709_enc.sv 5 | // Description : RS(255,239) parameters top level 6 | // 7 | 8 | //------------------------------------------------------------------------------------------------------ 9 | // GF parameters 10 | //------------------------------------------------------------------------------------------------------ 11 | 12 | localparam int cM = 8; // GF (2^m) 13 | localparam int cIRRPOL = 285; // irrectible poly 14 | 15 | //------------------------------------------------------------------------------------------------------ 16 | // RS parameters 17 | //------------------------------------------------------------------------------------------------------ 18 | 19 | localparam int cN = 255; // block size 20 | localparam int cCHECK = 16; // check symbols 21 | localparam int cGENSTART = 0; // first root index 22 | localparam int cROOTSPACE = 1; // root space 23 | 24 | localparam int cERRS = cCHECK/2; 25 | 26 | //------------------------------------------------------------------------------------------------------ 27 | // used types 28 | //------------------------------------------------------------------------------------------------------ 29 | 30 | typedef logic [cM-1 : 0] dat_t; 31 | typedef logic [1 : 0] ptr_t ; // used 4D buffer for data saving 32 | 33 | typedef logic [4 : 0] symerr_t; // 8 max 34 | typedef logic [6 : 0] biterr_t; // 64 max 35 | 36 | typedef logic [7 : 0] ram_addr_t; 37 | typedef logic [127 : 0] ram_dat_t; 38 | -------------------------------------------------------------------------------- /rtl/golay24/README.md: -------------------------------------------------------------------------------- 1 | Extended Gollay (24,12,8) soft decoder. Generator polynome is g(x) = x^11 + x^10 + x^6 + x^5 + x^4 + x^2 + 1 (12'hC75) 2 | 3 | Encoder use syndrome coding. 4 | Decoder use Chase II algorithm with 16 candidates and syndrome decoding. 5 | 6 | vivado 2019.1 Artix 7 - 2 7 | 8 | Encoder : LUT/REG 18/52 >250MHz (3Gbps) 9 | 10 | Decoder : LUT/REG/RAMB 652/936/2 >250MHz (250Mbps) 11 | -------------------------------------------------------------------------------- /rtl/golay24/dec/golay24_dec_types.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : golay24 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : golay24_dec_types.svh 5 | // Description : file with all decoder used types 6 | // 7 | 8 | //------------------------------------------------------------------------------------------------------ 9 | // used types for decoder 10 | //------------------------------------------------------------------------------------------------------ 11 | 12 | parameter pLLR_W = 4; 13 | parameter pTAG_W = 4; 14 | 15 | localparam int cMETRIC_W = $clog2(24) + pLLR_W; 16 | 17 | typedef logic signed [pLLR_W-1 : 0] llr_t; 18 | typedef logic signed [pTAG_W-1 : 0] tag_t; 19 | 20 | typedef logic signed [cMETRIC_W-1 : 0] metric_t; 21 | 22 | typedef logic [4 : 0] idx_t; 23 | 24 | typedef logic [23 : 0] dat_t; 25 | typedef logic [11 : 0] syndrome_t; 26 | 27 | -------------------------------------------------------------------------------- /rtl/golay24/golay24_enc.sv: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | 5 | parameter int pTAG_W = 1 ; 6 | 7 | 8 | 9 | logic golay24_enc__iclk ; 10 | logic golay24_enc__ireset ; 11 | logic golay24_enc__iclkena ; 12 | logic golay24_enc__ival ; 13 | logic [pTAG_W-1 : 0] golay24_enc__itag ; 14 | logic [11 : 0] golay24_enc__idat ; 15 | logic golay24_enc__oval ; 16 | logic [pTAG_W-1 : 0] golay24_enc__otag ; 17 | logic [23 : 0] golay24_enc__odat ; 18 | 19 | 20 | 21 | golay24_enc 22 | #( 23 | .pTAG_W ( pTAG_W ) 24 | ) 25 | golay24_enc 26 | ( 27 | .iclk ( golay24_enc__iclk ) , 28 | .ireset ( golay24_enc__ireset ) , 29 | .iclkena ( golay24_enc__iclkena ) , 30 | .ival ( golay24_enc__ival ) , 31 | .itag ( golay24_enc__itag ) , 32 | .idat ( golay24_enc__idat ) , 33 | .oval ( golay24_enc__oval ) , 34 | .otag ( golay24_enc__otag ) , 35 | .odat ( golay24_enc__odat ) 36 | ); 37 | 38 | 39 | assign golay24_enc__iclk = '0 ; 40 | assign golay24_enc__ireset = '0 ; 41 | assign golay24_enc__iclkena = '0 ; 42 | assign golay24_enc__ival = '0 ; 43 | assign golay24_enc__itag = '0 ; 44 | assign golay24_enc__idat = '0 ; 45 | 46 | 47 | 48 | */ 49 | 50 | // 51 | // Project : golay24 52 | // Author : Shekhalev Denis (des00) 53 | // Revision : $Revision$ 54 | // Date : $Date$ 55 | // Workfile : golay24_enc.sv 56 | // Description : golay extened code {24, 12, 8} encoder. g(x) = x^11 + x^10 + x^6 + x^5 + x^4 + x^2 + 1 (12'hC75) 57 | // 58 | 59 | 60 | module golay24_enc 61 | #( 62 | parameter int pTAG_W = 1 63 | ) 64 | ( 65 | iclk , 66 | ireset , 67 | iclkena , 68 | // 69 | ival , 70 | itag , 71 | idat , 72 | // 73 | oval , 74 | otag , 75 | odat 76 | ); 77 | 78 | //------------------------------------------------------------------------------------------------------ 79 | // 80 | //------------------------------------------------------------------------------------------------------ 81 | 82 | input logic iclk ; 83 | input logic ireset ; 84 | input logic iclkena ; 85 | // 86 | input logic ival ; 87 | input logic [pTAG_W-1 : 0] itag ; 88 | input logic [11 : 0] idat ; 89 | // 90 | output logic oval ; 91 | output logic [pTAG_W-1 : 0] otag ; 92 | output logic [23 : 0] odat ; 93 | 94 | //------------------------------------------------------------------------------------------------------ 95 | // 96 | //------------------------------------------------------------------------------------------------------ 97 | 98 | `include "golay24_functions.svh" 99 | 100 | //------------------------------------------------------------------------------------------------------ 101 | // 102 | //------------------------------------------------------------------------------------------------------ 103 | 104 | logic val; 105 | logic [pTAG_W-1 : 0] tag; 106 | logic [23 : 0] dat; 107 | 108 | //------------------------------------------------------------------------------------------------------ 109 | // 110 | //------------------------------------------------------------------------------------------------------ 111 | 112 | always_ff @(posedge iclk or posedge ireset) begin 113 | if (ireset) begin 114 | {oval, val} <= 2'b00; 115 | end 116 | else if (iclkena) begin 117 | {oval, val} <= {val, ival}; 118 | end 119 | end 120 | 121 | always_ff @(posedge iclk) begin 122 | if (iclkena) begin 123 | dat <= {get_syndrome({idat, 12'h0}), idat}; 124 | tag <= itag; 125 | // 126 | odat <= dat; 127 | otag <= tag; 128 | end 129 | end 130 | 131 | endmodule 132 | -------------------------------------------------------------------------------- /rtl/golay24/golay24_functions.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : golay24 3 | // Author : Shekhalev Denis (des00) 4 | // Revision : $Revision$ 5 | // Date : $Date$ 6 | // Workfile : golay24_functions.svh 7 | // Description : forward and backward table generation. g(x) = x^11 + x^10 + x^6 + x^5 + x^4 + x^2 + 1 (12'hC75). See Marelos-Saragosa 8 | // 9 | 10 | // data (systematic) bits part of check marix 11 | localparam bit [11 : 0] cD_TAB[12] = '{12'h800, 12'h400, 12'h200, 12'h100, 12 | 12'h080, 12'h040, 12'h020, 12'h010, 13 | 12'h008, 12'h004, 12'h002, 12'h001}; 14 | 15 | // parity bits part of check marix 16 | localparam bit [11 : 0] cB_TAB[12] = '{12'h7FF, 12'hEE2, 12'hDC5, 12'hB8B, 17 | 12'hF16, 12'hE2D, 12'hC5B, 12'h8B7, 18 | 12'h96E, 12'hADC, 12'hDB8, 12'hB71}; 19 | 20 | bit [23 : 0] cFORWARD_ENCODER_TAB [4096]; 21 | bit [23 : 0] cBACKWARD_ENCODER_TAB [4096]; 22 | 23 | always_comb begin 24 | int code; 25 | // 26 | cFORWARD_ENCODER_TAB = '{default : '0}; 27 | cBACKWARD_ENCODER_TAB = '{default : '0}; 28 | // 29 | for (int data = 0; data < 4096; data++) begin 30 | code = '0; 31 | for (int i = 0; i < 12; i++) begin 32 | code[11 - i] = ^(data & cB_TAB[i]); 33 | end 34 | cFORWARD_ENCODER_TAB [data[11 : 0]] = {code[11 : 0], data[11 : 0]}; // lsb first 35 | cBACKWARD_ENCODER_TAB[code[11 : 0]] = {code[11 : 0], data[11 : 0]}; 36 | end 37 | end 38 | 39 | bit [24 : 0] cSYNDROME_TAB [4096]; // + 1 bit for missing error pattern {filed, error_vector} 40 | bit [15 : 0] cS_SYNDROME_TAB [4096]; // + 1 bit for missing error pattern {failed, error_idx[0:2]} 41 | 42 | always_comb begin 43 | bit [23 : 0] biterr; 44 | bit [11 : 0] syndrome; 45 | // 46 | cSYNDROME_TAB = '{0 : 0, default : 25'h1_000000}; 47 | cS_SYNDROME_TAB = '{0 : 16'h7FFF, default : 16'hFFFF}; 48 | // single weigth error 49 | for (int i = 0; i < 24; i++) begin 50 | biterr = (1 << i); 51 | syndrome = get_syndrome(biterr); 52 | // 53 | cSYNDROME_TAB [syndrome] = {1'b0, biterr}; 54 | cS_SYNDROME_TAB [syndrome] = {1'b0, i[4:0], 5'h1F, 5'h1F}; 55 | end 56 | // double weigth error 57 | for (int i = 0; i < 24; i++) begin 58 | for (int j = i + 1; j < 24; j++) begin 59 | biterr = (1 << i) | (1 << j); 60 | syndrome = get_syndrome(biterr); 61 | // 62 | cSYNDROME_TAB [syndrome] = {1'b0, biterr}; 63 | cS_SYNDROME_TAB [syndrome] = {1'b0, i[4:0], j[4:0], 5'h1F}; 64 | end 65 | end 66 | // tripple weigth error 67 | for (int i = 0; i < 24; i++) begin 68 | for (int j = i + 1; j < 24; j++) begin 69 | for (int k = j + 1; k < 24; k++) begin 70 | biterr = (1 << i) | (1 << j) | (1 << k); 71 | syndrome = get_syndrome(biterr); 72 | // 73 | cSYNDROME_TAB [syndrome] = {1'b0, biterr}; 74 | cS_SYNDROME_TAB [syndrome] = {1'b0, i[4:0], j[4:0], k[4:0]}; 75 | end 76 | end 77 | end 78 | end 79 | 80 | function bit [23 : 0] encode (input bit [11 : 0] data); 81 | bit [11 : 0] code; 82 | begin 83 | for (int i = 0; i < 12; i++) begin 84 | code[11-i] = ^(data[11 : 0] & cB_TAB[i]); 85 | end 86 | encode = {code, data}; 87 | end 88 | endfunction 89 | 90 | function bit [11 : 0] get_syndrome (input bit [23 : 0] data); 91 | for (int i = 0; i < 12; i++) begin 92 | get_syndrome[11-i] = ^({cB_TAB[i], cD_TAB[i]} & data); 93 | // get_syndrome[11-i] = ^(cB_TAB[i] & data[23 : 12]) ^ data[11-i]; 94 | end 95 | endfunction 96 | 97 | function bit [3 : 0] weight (input bit [11 : 0] data); 98 | weight = 0; 99 | for (int i = 0; i < 12; i++) begin 100 | weight += data[i]; 101 | end 102 | endfunction 103 | 104 | -------------------------------------------------------------------------------- /rtl/gsfc_ldpc/README.md: -------------------------------------------------------------------------------- 1 | NASA GSFC LDPC code (7154, 8176) from Blue book CCSDS 131.0-B-2 2 | 3 | 4 | Decoder use 2D normalized Min-Sum algorithm with optional metric self-corrected feature 5 | 6 | Only decoder with least performance include in repo!!! 7 | 8 | vivado 2019.1 Artix 7 - 2 9 | 10 | Encoder speed = 7 bits per tick 11 | 12 | Encoder : LUT/REG 4672/2184 >250MHz (1.5Gbps -> 1.75Gbps) 13 | 14 | Decoder speed 7 metrics per tick, LLR bitwidth = 4bits, 10 iteration 15 | 16 | Decoder simple : LUT/REG/RAMB 4.1k/6.2k/21.0 ~250MHz (80Mbps -> 70Mbps) 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /rtl/gsfc_ldpc/dec/gsfc_ldpc_dec_functions.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : GSFC ldpc (7154, 8176) 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : gsfc_ldpc_dec_functions.v 5 | // Description : decoder functions for address generation tables 6 | // 7 | 8 | function addr_tab_t get_addr_tab (input bit do_print = 0, short_print = 0); 9 | int taddr ; 10 | // 11 | int addr [pLLR_BY_CYCLE]; 12 | int maddr [pLLR_BY_CYCLE]; 13 | int sela [pLLR_BY_CYCLE]; 14 | int invsela [pLLR_BY_CYCLE]; 15 | int offset [pLLR_BY_CYCLE]; 16 | int offsetm [pLLR_BY_CYCLE]; 17 | // 18 | int fp; 19 | begin 20 | // synthesis translate_off 21 | if (do_print) begin 22 | fp = $fopen("../rtl/gsfc_ldpc/dec/gsfc_ldpc_dec_addr_gen_tab.svh"); 23 | $fdisplay(fp, "//"); 24 | if (short_print) 25 | $fdisplay(fp, "// (!!!) IT'S GENERATED short table for %0d/%0d coderate, %0d bits do %0d LLR per cycle(!!!)", pCODE, pCODE+1, pN, pLLR_BY_CYCLE); 26 | else 27 | $fdisplay(fp, "// (!!!) IT'S GENERATED full table for %0d/%0d coderate, %0d bits do %0d LLR per cycle(!!!)", pCODE, pCODE+1, pN, pLLR_BY_CYCLE); 28 | $fdisplay(fp, "//"); 29 | end 30 | // synthesis translate_on 31 | for (int c = 0; c < pC; c++) begin 32 | for (int w = 0; w < pW; w++) begin 33 | for (int t = 0; t < pT; t++) begin 34 | for (int z = 0; z < cZ_MAX; z++) begin 35 | // generate all address 36 | for (int llra = 0; llra < pLLR_BY_CYCLE; llra++) begin 37 | taddr = (Hb[c][t][w] + llra + pZF + z*pLLR_BY_CYCLE) % pZF; 38 | // 39 | addr[llra] = taddr / pLLR_BY_CYCLE; 40 | sela[llra] = taddr % pLLR_BY_CYCLE; 41 | end 42 | // get muxed address 43 | for (int llra = 0; llra < pLLR_BY_CYCLE; llra++) begin 44 | maddr [sela[llra]] = addr[llra]; 45 | invsela [sela[llra]] = llra; 46 | end 47 | // detect offsets and masked offsets 48 | for (int llra = 0; llra < pLLR_BY_CYCLE; llra++) begin 49 | offset [llra] = maddr[llra] - maddr[0]; 50 | offsetm [llra] = (offset [llra] == 0) ? 0 : -1; 51 | end 52 | // 53 | get_addr_tab[c][w][t][z].baddr = maddr[0]; 54 | for (int llra = 0; llra < pLLR_BY_CYCLE; llra++) begin 55 | get_addr_tab[c][w][t][z].offset [llra] = offset [llra]; 56 | get_addr_tab[c][w][t][z].offsetm [llra] = offsetm [llra]; 57 | get_addr_tab[c][w][t][z].sela [llra] = sela [llra]; 58 | get_addr_tab[c][w][t][z].invsela [llra] = invsela [llra]; 59 | end 60 | // synthesis translate_off 61 | if (do_print) begin 62 | if (!short_print) 63 | $fdisplay(fp, " addr_tab[%0d][%0d][%0d][%0d] = %p;", c, w, t, z, get_addr_tab[c][w][t][z]); 64 | else if (z == 0) 65 | $fdisplay(fp, " addr_tab[%0d][%0d][%0d][%0d] = %p;", c, w, t, z, get_addr_tab[c][w][t][z]); 66 | end 67 | // synthesis translate_on 68 | end 69 | end 70 | end 71 | end 72 | // synthesis translate_off 73 | if (do_print) 74 | $fclose(fp); 75 | // synthesis translate_on 76 | end 77 | endfunction 78 | 79 | //------------------------------------------------------------------------------------------------------ 80 | // function to pipeline decoder by pNODE_BY_CYCLE processing 81 | //------------------------------------------------------------------------------------------------------ 82 | 83 | typedef paddr_t maddr_tab_t [pC][pW][pNODE_BY_CYCLE][cT_MAX][cZ_MAX]; // full table 84 | typedef paddr_t maddr_tab_s_t [pC][pW][pNODE_BY_CYCLE][cT_MAX]; // short table 85 | 86 | function maddr_tab_t get_maddr_tab (input addr_tab_t taddr_tab); 87 | for (int c = 0; c < pC; c++) begin 88 | for (int w = 0; w < pW; w++) begin 89 | for (int n = 0; n < pNODE_BY_CYCLE; n++) begin 90 | for (int t = 0; t < cT_MAX; t++) begin 91 | get_maddr_tab[c][w][n][t] = taddr_tab[c][w][n*cT_MAX + t]; 92 | end 93 | end 94 | end 95 | end 96 | endfunction 97 | 98 | -------------------------------------------------------------------------------- /rtl/gsfc_ldpc/gsfc_ldpc_parameters.svh: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Project : GSFC ldpc (7154, 8176) 4 | // Author : Shekhalev Denis (des00) 5 | // Workfile : gsfc_ldpc_parameters.svh 6 | // Description : LDPC codec parameters and needed functions 7 | // 8 | 9 | //------------------------------------------------------------------------------------------------------ 10 | // LDPC code parameters matrix parameters : 11 | // coderate - 7/8 12 | // length - 8176 13 | //------------------------------------------------------------------------------------------------------ 14 | 15 | localparam int pCODE = 7; 16 | localparam int pN = 8176; 17 | 18 | localparam int pZF = 511; // expansion factor 19 | 20 | localparam int pW = 2; // weight of submatrix row/column 21 | localparam int pC = 2; // number of submatrix in column 22 | localparam int pT = 16; // number of submatrix in row 23 | 24 | localparam int cLDPC_NUM = pT * pZF; 25 | localparam int cLDPC_DNUM = (pT - pC) * pZF; 26 | 27 | typedef int H_t [pC][pT][pW]; 28 | 29 | H_t Hb; 30 | 31 | assign Hb = '{ 32 | '{ 33 | '{ 0, 176}, 34 | '{ 12, 239}, 35 | '{ 0, 352}, 36 | '{ 24, 431}, 37 | '{ 0, 392}, 38 | '{151, 409}, 39 | '{ 0, 351}, 40 | '{ 9, 359}, 41 | '{ 0, 307}, 42 | '{ 53, 329}, 43 | '{ 0, 207}, 44 | '{ 18, 281}, 45 | '{ 0, 399}, 46 | '{202, 457}, 47 | '{ 0, 247}, 48 | '{ 36, 261} 49 | }, 50 | '{ 51 | '{ 99, 471}, 52 | '{130, 473}, 53 | '{198, 435}, 54 | '{260, 478}, 55 | '{215, 420}, 56 | '{282, 481}, 57 | '{ 48, 396}, 58 | '{193, 445}, 59 | '{273, 430}, 60 | '{302, 451}, 61 | '{ 96, 379}, 62 | '{191, 386}, 63 | '{244, 467}, 64 | '{364, 470}, 65 | '{ 51, 382}, 66 | '{192, 414} 67 | } 68 | }; 69 | 70 | // 71 | // 2D min-sum normalization factors for all coderates 72 | // v-step/h-step normalization is cNORM_BY_8_FACTOR/8 73 | 74 | localparam int cNORM_FACTOR = 6; 75 | -------------------------------------------------------------------------------- /rtl/hamming/README.md: -------------------------------------------------------------------------------- 1 | Extended systematic Hamming code with automatic check matrix generation. 2 | 3 | Encoder do coding based upon check matrix. 4 | Decoder use simple syndrome decoding. 5 | 6 | vivado 2019.1 Artix 7 - 2 Code (32, 26, 5) 7 | 8 | Encoder : LUT/REG 22/17 >250MHz (250Mbps) 9 | 10 | Decoder : LUT/REG 63/69 >250MHz (250Mbps) 11 | -------------------------------------------------------------------------------- /rtl/hamming/hamming_dec.sv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dshekhalev/FEC/917f5c85e6638c2a38a74f2f8ca0ab928d7dfd98/rtl/hamming/hamming_dec.sv -------------------------------------------------------------------------------- /rtl/hamming/hamming_parameters.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : hamming 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : hamming_parameters.v 5 | // Description : Hamming codec parameters and functions 6 | // 7 | 8 | parameter int pR = 5; // number of check bits 9 | 10 | localparam int cDBITS = 2 ** pR - 1 - pR; // number of data bits 11 | localparam int cCBITS = 2 ** pR - 1; // number of frame bits except even bit for extended code 12 | 13 | typedef bit [cCBITS-1 : 0] M_t [pR]; // check matrix 14 | 15 | typedef int P_t [2 ** pR]; // permutation matrix 16 | 17 | //------------------------------------------------------------------------------------------------------ 18 | // function to generate matrix 19 | //------------------------------------------------------------------------------------------------------ 20 | 21 | function M_t generate_M_matrix (input bit nul); 22 | M_t tmpM; 23 | P_t perm; 24 | begin 25 | // generate H matrix 26 | for (int i = 1; i <= cCBITS; i++) begin 27 | for (int r = 0; r < pR; r++) begin 28 | tmpM[r][i-1] = i[r]; 29 | end 30 | end 31 | // convert matrix to systematic view 32 | perm = generate_permutation(0); 33 | for (int i = 0; i < cCBITS; i++) begin 34 | for (int r = 0; r < pR; r++) begin 35 | generate_M_matrix[r][i] = tmpM[r][perm[i]]; 36 | end 37 | end 38 | end 39 | endfunction 40 | 41 | function P_t generate_permutation (input bit nul); 42 | int j, k; 43 | int check_idx [pR]; 44 | int inside_ok; 45 | begin 46 | for (int r = 0; r < pR; r++) begin 47 | check_idx[r] = 2**r-1; 48 | end 49 | // 50 | j = 0; k = 0; 51 | // 52 | for (int i = 0; i < cCBITS; i++) begin 53 | for (int r = 0; r < pR; r++) begin 54 | inside_ok = (r == 0) ? (i == check_idx[r]) : (inside_ok | (i == check_idx[r])); 55 | end 56 | if (inside_ok) begin 57 | generate_permutation[cDBITS + k++] = i; 58 | end 59 | else begin 60 | generate_permutation[j++] = i; 61 | end 62 | end 63 | end 64 | endfunction 65 | 66 | function P_t generate_inv_permutation (input bit nul); 67 | int j, k; 68 | int check_idx [pR]; 69 | int inside_ok; 70 | begin 71 | for (int r = 0; r < pR; r++) begin 72 | check_idx[r] = 2**r-1; 73 | end 74 | // 75 | j = 0; k = 0; 76 | // 77 | for (int i = 0; i < cCBITS; i++) begin 78 | for (int r = 0; r < pR; r++) begin 79 | inside_ok = (r == 0) ? (i == check_idx[r]) : (inside_ok | (i == check_idx[r])); 80 | end 81 | if (inside_ok) begin 82 | generate_inv_permutation[i+1] = cDBITS + k++; // + 1 offset for syndrome == 0 83 | end 84 | else begin 85 | generate_inv_permutation[i+1] = j++; 86 | end 87 | end 88 | end 89 | endfunction 90 | 91 | -------------------------------------------------------------------------------- /rtl/ldpc/README.md: -------------------------------------------------------------------------------- 1 | Static configuration Wimax QC-LDPC code IEEE 802.16-2012 2 | 3 | Support modes 1/2, 2/3B, 3/4A, 5/6, 2/3A, 3/4B and length from 576 to 2304 bits 4 | 5 | It's my first generation QC-LDPC RTL architecture: 6 | 7 | Coder work on fly and use register architecture 8 | 9 | Decoder use 2D normalized Min-Sum algorithm with optional metric self-corrected feature 10 | 11 | Only decoder with least performance include in repo!!! 12 | 13 | vivado 2019.1 Artix 7 - 2 14 | 15 | Coderate = 5/6, Block length = 2304 bits 16 | 17 | Encoder speed = 8 bits per tick 18 | 19 | Encoder : LUT/REG 755/252 >250MHz (1.65Gbps -> 2Gbps) 20 | 21 | Decoder speed 8 metrics per tick, LLR bitwidth = 4bits, 10 iteration 22 | 23 | Decoder simple : LUT/REG/RAMB 4.6k/7.6k/17.0 ~250MHz (90Mbps -> 75Mbps) 24 | 25 | Attention: to facilitate synthesis, the decoder uses the address file generated during the simulation. The file content depend on the coderate, length & decoder performance settings. Before synthesizing the decoder, run the simulation in the desired mode!!! 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /rtl/ldpc_3gpp/README.md: -------------------------------------------------------------------------------- 1 | Static configuration 3GPP QC-LDPC + SPC code TS 38.212 v15.7.0 2 | 3 | Support Graph1/Graph2 4 | 5 | Support all List sets and List index (interface/codec parameters must correspond to selected expansion factor) 6 | 7 | Support all coderate (puncture is optional) from 22/24 to 22/68 (Graph1) and from 10/12 to 10/52 (Graph2) 8 | 9 | Coder use special QC-LDPC and SPC engine 10 | 11 | Decoder use 2D normalized Min-Sum algorithm with optional metric self-corrected feature 12 | 13 | Attention only decoder with least performance include in repo!!! 14 | 15 | vivado 2019.1 Artix 7 - 2 16 | 17 | Graph1, coderate = 22/24, data length = 5632 bits 18 | 19 | Encoder speed = 8 bits per tick 20 | 21 | Encoder : LUT/REG/RAMB 1.4k/1.7k/1.0 >250MHz (1.25Gbps -> 1.4Gbps) 22 | 23 | Decoder speed 1 metrics in 25 column & 4 row per tick, LLR/Node bitwidth = 4bits, data interface 4bits, self-corrected mode on, 10 iteration 24 | 25 | Decoder : LUT/REG/RAMB 8k/12k/61.0 ~250MHz (270Mbps -> 250Mbps) 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /rtl/ldpc_3gpp/dec/ldpc_3gpp_dec_cnode_p_2way_engine.sv: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | 5 | parameter int pCODE = 1 ; 6 | parameter int pN = 1 ; 7 | parameter int pLLR_W = 4 ; 8 | parameter int pLLR_BY_CYCLE = 1 ; 9 | parameter int pNODE_W = 1 ; 10 | parameter int pNODE_BY_CYCLE = 1 ; 11 | 12 | 13 | logic ldpc_3gpp_dec_cnode_p_2way_engine__iclk ; 14 | logic ldpc_3gpp_dec_cnode_p_2way_engine__ireset ; 15 | logic ldpc_3gpp_dec_cnode_p_2way_engine__iclkena ; 16 | logic ldpc_3gpp_dec_cnode_p_2way_engine__ival ; 17 | vn_min_t ldpc_3gpp_dec_cnode_p_2way_engine__ivn [2] ; 18 | logic ldpc_3gpp_dec_cnode_p_2way_engine__oval ; 19 | vn_min_t ldpc_3gpp_dec_cnode_p_2way_engine__ovn ; 20 | 21 | 22 | 23 | ldpc_3gpp_dec_cnode_p_2way_engine 24 | #( 25 | .pLLR_W ( pLLR_W ) , 26 | .pNODE_W ( pNODE_W ) 27 | ) 28 | ldpc_3gpp_dec_cnode_p_2way_engine 29 | ( 30 | .iclk ( ldpc_3gpp_dec_cnode_p_2way_engine__iclk ) , 31 | .ireset ( ldpc_3gpp_dec_cnode_p_2way_engine__ireset ) , 32 | .iclkena ( ldpc_3gpp_dec_cnode_p_2way_engine__iclkena ) , 33 | .ival ( ldpc_3gpp_dec_cnode_p_2way_engine__ival ) , 34 | .ivn ( ldpc_3gpp_dec_cnode_p_2way_engine__ivn ) 35 | .oval ( ldpc_3gpp_dec_cnode_p_2way_engine__oval ) , 36 | .ovn ( ldpc_3gpp_dec_cnode_p_2way_engine__ovn ) 37 | ); 38 | 39 | 40 | assign ldpc_3gpp_dec_cnode_p_2way_engine__iclk = '0 ; 41 | assign ldpc_3gpp_dec_cnode_p_2way_engine__ireset = '0 ; 42 | assign ldpc_3gpp_dec_cnode_p_2way_engine__iclkena = '0 ; 43 | assign ldpc_3gpp_dec_cnode_p_2way_engine__ival = '0 ; 44 | assign ldpc_3gpp_dec_cnode_p_2way_engine__ivn = '0 ; 45 | 46 | 47 | 48 | */ 49 | 50 | // 51 | // Project : ldpc 3gpp TS 38.212 v15.7.0 52 | // Author : Shekhalev Denis (des00) 53 | // Workfile : ldpc_3gpp_dec_cnode_p_2way_engine.sv 54 | // Description : LDPC decoder check node arithmetic engine for parallel partial search : read 2 vnodes and do simple search 55 | // 56 | 57 | `include "define.vh" 58 | 59 | module ldpc_3gpp_dec_cnode_p_2way_engine 60 | ( 61 | iclk , 62 | ireset , 63 | iclkena , 64 | // 65 | ival , 66 | ivn , 67 | // 68 | oval , 69 | ovn 70 | ); 71 | 72 | `include "../ldpc_3gpp_constants.svh" 73 | `include "ldpc_3gpp_dec_types.svh" 74 | 75 | //------------------------------------------------------------------------------------------------------ 76 | // 77 | //------------------------------------------------------------------------------------------------------ 78 | 79 | input logic iclk ; 80 | input logic ireset ; 81 | input logic iclkena ; 82 | // 83 | input logic ival ; 84 | input vn_min_t ivn [2] ; 85 | // 86 | output logic oval ; 87 | output vn_min_t ovn ; 88 | 89 | //------------------------------------------------------------------------------------------------------ 90 | // prepare data 91 | //------------------------------------------------------------------------------------------------------ 92 | 93 | always_ff @(posedge iclk or posedge ireset) begin 94 | if (ireset) begin 95 | oval <= 1'b0; 96 | end 97 | else if (iclkena) begin 98 | oval <= ival; 99 | end 100 | end 101 | 102 | // {a,b} vs {c, d} 103 | wire check1 = (ivn[1].min1 < ivn[0].min1); // (c < a) ? c : a 104 | wire check2 = (ivn[1].min2 < ivn[0].min1); // c < a ? (d < a) ? d : a 105 | wire check3 = (ivn[1].min1 < ivn[0].min2); // c >= a ? (c < b) ? c : b 106 | 107 | always_ff @(posedge iclk) begin 108 | if (iclkena) begin 109 | if (ival) begin 110 | if (check1) begin 111 | ovn.min1 <= ivn[1].min1; 112 | ovn.min2 <= check2 ? ivn[1].min2 : ivn[0].min1; 113 | ovn.min1_col <= ivn[1].min1_col; 114 | end 115 | else begin 116 | ovn.min1 <= ivn[0].min1; 117 | ovn.min2 <= check3 ? ivn[1].min1 : ivn[0].min2; 118 | ovn.min1_col <= ivn[0].min1_col; 119 | end 120 | end 121 | end 122 | end 123 | 124 | endmodule 125 | -------------------------------------------------------------------------------- /rtl/ldpc_3gpp/dec/ldpc_3gpp_dec_hc.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : ldpc 3gpp TS 38.212 v15.7.0 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : ldpc_3gpp_dec_hc.svh 5 | // Description : decoder check matrix optimization functions 6 | // 7 | 8 | //------------------------------------------------------------------------------------------------------ 9 | // detect unused node ram block for split Hb by pROW_BY_CYCLE. can use any grapth 10 | //------------------------------------------------------------------------------------------------------ 11 | 12 | typedef bit maskHc_t [pROW_BY_CYCLE][cCOL_BY_CYCLE]; // use 26/14 columns for graph1/graph2 13 | 14 | localparam maskHc_t cHC_MASK = get_Hc_mask(pIDX_GR); 15 | 16 | // 17 | // idxGr == 0 use graph1/graph2 else use graph2 only 18 | // 19 | function maskHc_t get_Hc_mask (input logic idxGr); 20 | begin 21 | get_Hc_mask = '{default : '{default : 1}}; 22 | // 23 | for (int row = 0; row < ((pCODE < cGR_MAX_ROW[1]) ? pCODE : cGR_MAX_ROW[1]); row++) begin 24 | for (int col = 0; col < 14; col++) begin 25 | get_Hc_mask[row % pROW_BY_CYCLE][col] &= (gr2_Hc_LS0[row][col] < 0); 26 | end 27 | end 28 | // 29 | if (idxGr == 0) begin 30 | for (int row = 0; row < ((pCODE < cGR_MAX_ROW[0]) ? pCODE : cGR_MAX_ROW[0]); row++) begin 31 | for (int col = 0; col < 26; col++) begin 32 | get_Hc_mask[row % pROW_BY_CYCLE][col] &= (gr1_Hc_LS0[row][col] < 0); 33 | end 34 | end 35 | end 36 | end 37 | endfunction 38 | 39 | -------------------------------------------------------------------------------- /rtl/ldpc_3gpp/enc/ldpc_3gpp_enc_types.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : ldpc 3gpp TS 38.212 v15.7.0 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : ldpc_3gpp_enc_types.svh 5 | // Description : encoder parameters/types & etc 6 | // 7 | 8 | //------------------------------------------------------------------------------------------------------ 9 | // common code context parameter to contstraint fixed or variable decoder 10 | //------------------------------------------------------------------------------------------------------ 11 | 12 | parameter bit pIDX_GR = 0 ; // use graph1/graph2 (0) or graph2 only (1). graph1 has major matrix 26x4, graph2 14x4 13 | parameter int pIDX_LS = 0 ; 14 | parameter int pIDX_ZC = 7 ; 15 | parameter int pCODE = 46 ; // maximum code rate using (46 for graph1 and 42 for graph2) 16 | parameter bit pDO_PUNCT = 0 ; // use puncture any time (1) or context defined (0) 17 | 18 | //------------------------------------------------------------------------------------------------------ 19 | // encoder engine/interface parameters 20 | //------------------------------------------------------------------------------------------------------ 21 | 22 | parameter int pDAT_W = 8; // 1/2/4/8/16/32 supported 23 | 24 | //------------------------------------------------------------------------------------------------------ 25 | // 26 | //------------------------------------------------------------------------------------------------------ 27 | 28 | localparam int cLOG2_DAT_W = (pDAT_W == 1) ? 1 : clogb2(pDAT_W); 29 | 30 | typedef logic [cLOG2_DAT_W-1 : 0] bshift_t; 31 | 32 | // matrix multiply value type 33 | typedef struct packed { 34 | bshift_t bshift; // bit shift == Hb[c][t] % pDAT_W 35 | hb_zc_t wshift; // word shift == Hb[c][t] / pDAT_W 36 | logic is_masked; // Hb[c][t] < 0 37 | logic is_max; // wshift(Hb[c][t] / pDAT_W) == used_zc/pDAT_W-1 38 | } mm_hb_value_t; 39 | 40 | //------------------------------------------------------------------------------------------------------ 41 | // used data types 42 | //------------------------------------------------------------------------------------------------------ 43 | 44 | typedef logic [pDAT_W-1 : 0] dat_t; 45 | 46 | // control strobes type 47 | typedef struct packed { 48 | logic sof; // start of node frame working (acu ? col/row == 0 & zc == 0) 49 | logic sop; // start of node block working (zc == 0) 50 | logic eop; // end of node block working (zc == used_zc-1) 51 | logic eof; // end of node frame working (acu ? col/row == used_col/used_row-1 & zc == used_zc-1) 52 | } strb_t; 53 | -------------------------------------------------------------------------------- /rtl/ldpc_dvb/README.md: -------------------------------------------------------------------------------- 1 | Static configuration DVB-S2 LDPC code ETSI EN 302 307 V1.2.1 (2009-08) and DVB-S2X LDPC code DVB BlueBook A083-2 (Feb 2020) 2 | 3 | Support all coderates and codewords. 4 | 5 | Encoder has fixed performance engine with variable interface bitwidth. 6 | 7 | Decoder use 2D normalized Min-Sum algorithm with near fixed performance engine, fast decoder syndrome based stop logic, optional 2 types of normalization and self-corrected algorithm. 8 | 9 | Attention only decoder with least performance include in repo!!! 10 | 11 | Codec input/core/output work in different clock domains. 12 | 13 | vivado 2019.1 Kintex 7 - 2 (artix worked but has timings routing problem) 14 | 15 | Encoder settings : DVB-S2 coderate = 5/6, block length = 64800 bits, interface 8 bits per tick, no internal parity bits transponse 16 | 17 | Encoder : LUT/REG/RAMB 3.7k/3.5k/15 iface >250MHz(1.65Gbps -> 2Gbps), core >250MHz (~25.5Gbps at output) 18 | 19 | Decoder settings : DVB-S2 coderate = 1/2, block length = 64800 bits, 8 LLR/bits per tick, pLLR_W = 4 bits, pNORM_OFFSET = 0, pUSE_SC_MODE = 1, 25 iterations 20 | 21 | pNODE_W = 6 bits (optimal codegain for 4 bit LLR) 22 | 23 | Decoder : LUT/REG/RAMB 57k/63k/107.5 iface >250MHz, core >250MHz (480Mbps -> 240Mbps) 24 | 25 | pNODE_W = 5 bits (good codegain for 4 bit LLR) 26 | 27 | Decoder : LUT/REG/RAMB 49k/56k/97.5 iface >250MHz, core >250MHz (480Mbps -> 240Mbps) 28 | 29 | pNODE_W = 4 bits (worst codegain for 4 bit LLR) 30 | 31 | Decoder : LUT/REG/RAMB 41k/49k/87.5 iface >250MHz, core >250MHz (480Mbps -> 240Mbps) 32 | 33 | 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 by default, because there is no parity bits reorder inside. It should be done external of codec during bit interleaving procedure !!! 34 | 35 | PS. There is optinal parity bits transpose unit inside encoder? this unit don't have opponent inside decoder. That's why use it only for encoder aplications. 36 | -------------------------------------------------------------------------------- /rtl/ldpc_dvb/dec/ldpc_dvb_dec_syndrome_count.sv: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | 5 | 6 | 7 | 8 | logic ldpc_dvb_dec_syndrome_count__iclk ; 9 | logic ldpc_dvb_dec_syndrome_count__ireset ; 10 | logic ldpc_dvb_dec_syndrome_count__iclkena ; 11 | // 12 | logic ldpc_dvb_dec_syndrome_count__istart ; 13 | // 14 | logic ldpc_dvb_dec_syndrome_count__ival ; 15 | strb_t ldpc_dvb_dec_syndrome_count__istrb ; 16 | zdat_t ldpc_dvb_dec_syndrome_count__ivnode_hd ; 17 | // 18 | logic ldpc_dvb_dec_syndrome_count__oval ; 19 | logic ldpc_dvb_dec_syndrome_count__odat ; 20 | 21 | 22 | 23 | ldpc_dvb_dec_syndrome_count 24 | ldpc_dvb_dec_syndrome_count 25 | ( 26 | .iclk ( ldpc_dvb_dec_syndrome_count__iclk ) , 27 | .ireset ( ldpc_dvb_dec_syndrome_count__ireset ) , 28 | .iclkena ( ldpc_dvb_dec_syndrome_count__iclkena ) , 29 | // 30 | .istart ( ldpc_dvb_dec_syndrome_count__istart ) , 31 | // 32 | .ival ( ldpc_dvb_dec_syndrome_count__ival ) , 33 | .istrb ( ldpc_dvb_dec_syndrome_count__istrb ) , 34 | .ivnode_hd ( ldpc_dvb_dec_syndrome_count__ivnode_hd ) , 35 | // 36 | .oval ( ldpc_dvb_dec_syndrome_count__oval ) , 37 | .odat ( ldpc_dvb_dec_syndrome_count__odat ) 38 | ); 39 | 40 | 41 | assign ldpc_dvb_dec_syndrome_count__iclk = '0 ; 42 | assign ldpc_dvb_dec_syndrome_count__ireset = '0 ; 43 | assign ldpc_dvb_dec_syndrome_count__iclkena = '0 ; 44 | assign ldpc_dvb_dec_syndrome_count__istart = '0 ; 45 | assign ldpc_dvb_dec_syndrome_count__ival = '0 ; 46 | assign ldpc_dvb_dec_syndrome_count__istrb = '0 ; 47 | assign ldpc_dvb_dec_syndrome_count__ivnode_hd = '0 ; 48 | 49 | 50 | 51 | */ 52 | 53 | // 54 | // Project : ldpc DVB-S2 55 | // Author : Shekhalev Denis (des00) 56 | // Workfile : ldpc_dvb_dec_syndrome_count.sv 57 | // Description : Syndrome counter for fast output mode 58 | // 59 | 60 | module ldpc_dvb_dec_syndrome_count 61 | ( 62 | iclk , 63 | ireset , 64 | iclkena , 65 | // 66 | istart , 67 | // 68 | ival , 69 | istrb , 70 | ivnode_hd , 71 | // 72 | oval , 73 | odat 74 | ); 75 | 76 | `include "../ldpc_dvb_constants.svh" 77 | `include "ldpc_dvb_dec_types.svh" 78 | 79 | //------------------------------------------------------------------------------------------------------ 80 | // 81 | //------------------------------------------------------------------------------------------------------ 82 | 83 | input logic iclk ; 84 | input logic ireset ; 85 | input logic iclkena ; 86 | // 87 | input logic istart ; 88 | // 89 | input logic ival ; 90 | input strb_t istrb ; 91 | input zdat_t ivnode_hd ; 92 | // 93 | output logic oval ; 94 | output logic odat ; 95 | 96 | //------------------------------------------------------------------------------------------------------ 97 | // 98 | //------------------------------------------------------------------------------------------------------ 99 | 100 | logic syndrome_val; 101 | zdat_t syndrome; 102 | 103 | //------------------------------------------------------------------------------------------------------ 104 | // 105 | //------------------------------------------------------------------------------------------------------ 106 | 107 | always_ff @(posedge iclk or posedge ireset) begin 108 | if (ireset) begin 109 | syndrome_val <= 1'b0; 110 | oval <= 1'b0; 111 | end 112 | else if (iclkena) begin 113 | syndrome_val <= ival & istrb.eop; 114 | oval <= syndrome_val; 115 | end 116 | end 117 | 118 | always_ff @(posedge iclk) begin 119 | if (iclkena) begin 120 | // count syndrome by row 121 | if (ival) begin 122 | syndrome <= istrb.sop ? ivnode_hd : (syndrome ^ ivnode_hd); 123 | end 124 | // accumulate syndromes 125 | if (ival & istrb.sop & istrb.sof) begin 126 | odat <= '0; 127 | end 128 | else if (syndrome_val) begin 129 | odat <= odat | (|syndrome); 130 | end 131 | end 132 | end 133 | 134 | endmodule 135 | -------------------------------------------------------------------------------- /rtl/ldpc_dvb/enc/ldpc_dvb_enc_types.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : ldpc DVB-S2 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : ldpc_dvb_enc_types.svh 5 | // Description : encoder parameters/types & etc 6 | // 7 | 8 | //------------------------------------------------------------------------------------------------------ 9 | // used data types 10 | //------------------------------------------------------------------------------------------------------ 11 | 12 | // control strobes type 13 | typedef struct packed { 14 | logic sof; 15 | logic sop; 16 | logic eop; 17 | logic eof; 18 | } strb_t; 19 | 20 | //------------------------------------------------------------------------------------------------------ 21 | // usefull functions 22 | //------------------------------------------------------------------------------------------------------ 23 | 24 | // 25 | // function to get optimal input buffer width to save resources of source unit 26 | // 27 | function automatic int get_buffer_dat_w (input int dat_w); 28 | begin 29 | get_buffer_dat_w = cZC_MAX; 30 | case (dat_w) 31 | 1, 2, 3, 4, 6, 9, 12, 18, 36 : get_buffer_dat_w = 36; 32 | 8, 24, 72 : get_buffer_dat_w = 72; 33 | 5, 10, 15, 30, 45, 90 : get_buffer_dat_w = 90; 34 | 20, 60, 180 : get_buffer_dat_w = 180; 35 | 40, 120, 360 : get_buffer_dat_w = 360; 36 | endcase 37 | end 38 | endfunction 39 | 40 | // 41 | // function to get maximum input buffer ram address 42 | // 43 | function automatic int get_ibuff_max_addr (input int gr, bit xmode = 0); 44 | code_ctx_t ctx; 45 | begin 46 | if (xmode) begin 47 | if (gr == cCODEGR_LARGE) begin 48 | ctx = '{xmode : 1, gr : cCODEGR_LARGE, coderate : cXCODERATE_L_154by180}; 49 | end 50 | else if (gr == cCODEGR_SHORT) begin 51 | ctx = '{xmode : 1, gr : cCODEGR_SHORT, coderate : cXCODERATE_S_32by45}; 52 | end 53 | else begin 54 | ctx = '{xmode : 1, gr : cCODEGR_MEDIUM, coderate : cXCODERATE_M_1by3}; 55 | end 56 | end 57 | else begin 58 | if (gr == cCODEGR_LARGE) begin 59 | ctx = '{xmode : 0, gr : cCODEGR_LARGE, coderate : cCODERATE_9by10}; 60 | end 61 | else begin 62 | ctx = '{xmode : 0, gr : cCODEGR_SHORT, coderate : cCODERATE_8by9}; 63 | end 64 | end 65 | // 66 | get_ibuff_max_addr = get_used_data_col(ctx); 67 | end 68 | endfunction 69 | 70 | // 71 | // function to get maximum output buffer ram address 72 | // 73 | function automatic int get_obuff_max_addr (input int gr); 74 | begin 75 | get_obuff_max_addr = cGET_USED_COL_TAB[gr]; 76 | end 77 | endfunction 78 | 79 | // 80 | // function to get input buffer ram address 81 | // 82 | function automatic int get_ibuff_addr (input int gr, coderate, bit xmode = 0); 83 | code_ctx_t ctx; 84 | begin 85 | // can use any coderate 86 | ctx = '{xmode : xmode, gr : gr, coderate : coderate}; 87 | // 88 | get_ibuff_addr = get_used_data_col(ctx); 89 | end 90 | endfunction 91 | -------------------------------------------------------------------------------- /rtl/llr/README.md: -------------------------------------------------------------------------------- 1 | Static configurated Gray bit canstellation mapper for BSPK..QAM4096 modulation and corresponding LLR demapper. 2 | 3 | Even QAMs and BPSK/8PSK LLR bitwidth can be any, others odd QAMs only LLR = 4bit 4 | 5 | vivado 2019.1 Artix 7 - 2 6 | 7 | Gray bit mapper up to QAM4096 : LUT/REG 74/181 >350MHz 8 | 9 | Even QAM LLR demapper up to 4096 : LUT/REG 500/545 >250MHz 10 | 11 | Odd QAM LLR demapper up to QAM2048 : LUT/REG/RAMB 600/760/12.0 >250MHz 12 | 13 | Odd QAM LLR demapper up to QAM512 : LUT/REG/RAMB 331/483/7.5 >250MHz 14 | 15 | Odd QAM LLR demapper up to QAM128 : LUT/REG/RAMB 151/275/3.0 >250MHz 16 | 17 | Odd QAM LLR demapper up to QAM128 (no BRAM) : LUT/REG 645/548 >250MHz 18 | 19 | Attention: the used map bits to quadrature value converter rules see in tb_qam_mapper.sv file (!!!) 20 | -------------------------------------------------------------------------------- /rtl/pc_3gpp/README.md: -------------------------------------------------------------------------------- 1 | Non systematic Polar code with frozen bits map from 3GPP TS 38.212 V15.1.1 (2018-4) 2 | 3 | Code block size 1024 bits. Coderate [1...1023]/1024. Optional CRC support. 4 | 5 | Coder use recursive polar coding algorithm based upon x8 polar codes encode ALU. 6 | 7 | Decoder use fast serial successive cancellation algorithm based upon x4 polar codes decode ALU. 8 | 9 | vivado 2019.1 Artix 7 - 2, LLR = 4bits, coderate = 1/2 10 | 11 | Encoder : LUT/REG/RAMB 172/204/2.5 >250MHz (125Mbps -> 250Mbps) 12 | 13 | Decoder : LUT/REG/RAMB 1.9k/850/4.5 ~125MHz (40Mbps -> 20Mbps) 14 | 15 | Attention: this IP contain behaviour SV models too with separate testbench, because it's not so clear how it works from RTL code. See it in pc_3gpp/beh folder 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /rtl/pc_3gpp/dec/_start_psm.bat: -------------------------------------------------------------------------------- 1 | "D:\Program Files\Python26\python.exe" D:\work_des00\prj_python\vlog_tools\psm_compiler\src\psm.py pc_3gpp_dec_sc_ctrl_state.psm 2 | -------------------------------------------------------------------------------- /rtl/pc_3gpp/dec/pc_3gpp_dec_types.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : polar code 3gpp 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : pc_3gpp_dec_types.svh 5 | // Description : Decoder parameters, constants and types 6 | // 7 | 8 | parameter int pN_MAX = 1024; // fixed. don't change 9 | 10 | parameter int pLLR_W = 4; 11 | 12 | parameter int pTAG_W = 4; 13 | 14 | // internal engine parameters 15 | parameter int pWORD_W = 8; // engine word width fixed. don't change 16 | 17 | //------------------------------------------------------------------------------------------------------ 18 | // 19 | //------------------------------------------------------------------------------------------------------ 20 | 21 | localparam int cNLOG2 = $clog2(pN_MAX); 22 | 23 | localparam int cBIT_ADDR_W = $clog2(pN_MAX); 24 | 25 | localparam int cWORD_ADDR_W = $clog2(pN_MAX/pWORD_W); 26 | 27 | localparam int cCRC_W = 5; 28 | 29 | localparam int cALPHA_TRUE_W = pLLR_W + cNLOG2 - ($clog2(pWORD_W) - 1); 30 | localparam int cALPHA_W = min(pLLR_W + 4, cALPHA_TRUE_W); // saturate data 31 | 32 | localparam int cDLEN_W = 16; 33 | 34 | //------------------------------------------------------------------------------------------------------ 35 | // alu opcodes 36 | //------------------------------------------------------------------------------------------------------ 37 | 38 | typedef enum bit [3 : 0] { 39 | cNOP = 4'b00_00 , 40 | 41 | cDO_8x8 = 4'b00_01 , 42 | cDO_8x8_W = 4'b00_11 , // wait for 43 | 44 | cCALC_F4 = 4'b10_00 , 45 | cCALC_F4LLR = 4'b10_01 , 46 | 47 | cCALC_G4 = 4'b11_00 , 48 | cCALC_G4LLR = 4'b11_01 , 49 | cCALC_G4_int = 4'b11_10 , // internal reg 50 | 51 | cCOMB_int = 4'b01_00 , // internal reg 52 | cCOMB_intc = 4'b01_01 , // internal cache 53 | cCOMB_ext = 4'b01_10 , // external ram 54 | cCOMB_last = 4'b01_11 // last comb 55 | } alu_opcode_e; 56 | 57 | typedef logic [3 : 0] alu_opcode_t; 58 | 59 | //------------------------------------------------------------------------------------------------------ 60 | // frozen bit decode opcodes to detect duration of alu execution 61 | //------------------------------------------------------------------------------------------------------ 62 | 63 | typedef enum bit [2 : 0] { 64 | cDEC_RATE0_8 , // 1 tick decoding delay 65 | cDEC_RATE1_8 , // 1 tick decoding delay 66 | // 67 | cDEC_X_4_RATE0_4 , // 3 tick decoding delay 68 | cDEC_RATE0_4_X_4 , // 3 tick decoding delay 69 | // 70 | cDEC_X_8 // 5 tick decoding delay :: usual decoding 71 | } frozenb_type_e; 72 | 73 | typedef logic [2 : 0] frozenb_type_t; 74 | 75 | //------------------------------------------------------------------------------------------------------ 76 | // 77 | //------------------------------------------------------------------------------------------------------ 78 | 79 | typedef logic [cDLEN_W-1 : 0] dlen_t; 80 | typedef logic [cDLEN_W-1 : 0] err_t; 81 | 82 | typedef logic [cBIT_ADDR_W-1 : 0] bit_addr_t; 83 | 84 | typedef logic [cWORD_ADDR_W-1 : 0] beta_w_addr_t; 85 | typedef logic [pWORD_W-1 : 0] beta_w_dat_t; 86 | 87 | typedef logic [cCRC_W-1 : 0] crc_t; 88 | 89 | typedef logic [pTAG_W-1 : 0] tag_t; 90 | 91 | typedef logic [pLLR_W-1 : 0] llr_t; 92 | typedef llr_t llr_w_t [pWORD_W]; 93 | 94 | typedef logic signed [cALPHA_W-1 : 0] alpha_dat_t; 95 | typedef logic signed [cALPHA_TRUE_W-1 : 0] alpha_tdat_t; // alpha true dat to simplify mathematic 96 | 97 | typedef logic [cWORD_ADDR_W-1 : 0] alpha_w_addr_t; 98 | 99 | typedef alpha_dat_t alpha_w_t [pWORD_W]; // word 100 | typedef alpha_dat_t alpha_hw_t [pWORD_W/2]; // half word 101 | 102 | //------------------------------------------------------------------------------------------------------ 103 | // 104 | //------------------------------------------------------------------------------------------------------ 105 | 106 | `include "../pc_3gpp_functions.svh" 107 | -------------------------------------------------------------------------------- /rtl/pc_3gpp/enc/_start_psm.bat: -------------------------------------------------------------------------------- 1 | "D:\Program Files\Python26\python.exe" D:\work_des00\prj_python\vlog_tools\psm_compiler\src\psm.py pc_3gpp_enc_ctrl_state.psm 2 | -------------------------------------------------------------------------------- /rtl/pc_3gpp/enc/pc_3gpp_enc_ctrl_state.psm: -------------------------------------------------------------------------------- 1 | // 2 | // FSM 3 | // 4 | 5 | branch 6 | // buffer flags 7 | ibuf_full = br0; 8 | obuf_empty = br1; 9 | // 10 | beta_done = br2; 11 | // 12 | phiU = br3; 13 | endbranch 14 | 15 | const 16 | // buffer controls 17 | ibuf_set_empty = 0x01; 18 | obuf_set_full = 0x02; 19 | nbusy = 0x04; 20 | // 21 | // counter controls 22 | phi_clear = 0x10; 23 | phi_incr = 0x20; 24 | beta_clear = 0x40; 25 | beta_incr = 0x80; 26 | // 27 | // layers index 28 | lambda_m_3 = 0x700; 29 | lambda_m_4 = 0x600; 30 | lambda_m_5 = 0x500; 31 | lambda_m_6 = 0x400; 32 | lambda_m_7 = 0x300; 33 | lambda_m_8 = 0x200; 34 | lambda_m_9 = 0x100; 35 | // 36 | // alu opcode 37 | do8x8 = 0x1000; 38 | 39 | comb_by_8_int = 0x4000; 40 | comb_by_8_intc = 0x5000; 41 | comb_by_8_ext = 0x6000; 42 | comb_by_8_last = 0x7000; 43 | endconst 44 | 45 | begin 46 | 47 | Reset : 48 | nop, 0; 49 | // 50 | // wait sync buffer handshake 51 | Wait_BufferReay : 52 | if (ibuf_full & obuf_empty) jump Do_8x8, nbusy + phi_clear + beta_clear; 53 | else wait , nbusy + phi_clear + beta_clear; 54 | 55 | Do_8x8 : 56 | nop, phi_incr + do8x8; 57 | nop, phi_incr + do8x8; 58 | 59 | // no beta_done logic. Comb8 takes 2 cycle only 60 | Comb8 : 61 | nop, lambda_m_3 + comb_by_8_int + beta_incr ; 62 | 63 | if (phiU) nop, lambda_m_3 + comb_by_8_int + beta_clear; 64 | else jump Do_8x8, lambda_m_3 + comb_by_8_int + beta_clear; 65 | 66 | //nop, lambda_m_3; // need if small cashe is not using 67 | 68 | Comb16 : 69 | if (beta_done & phiU) nop, lambda_m_4 + comb_by_8_intc + beta_incr; // phi2 >> 70 | else if (beta_done) jump Do_8x8, lambda_m_4 + comb_by_8_intc + beta_incr; 71 | else wait, lambda_m_4 + comb_by_8_intc + beta_incr; 72 | 73 | Comb32 : 74 | if (beta_done & phiU) nop, lambda_m_5 + comb_by_8_ext + beta_incr; // phi3 >> 75 | else if (beta_done) jump Do_8x8, lambda_m_5 + comb_by_8_ext + beta_incr; 76 | else wait, lambda_m_5 + comb_by_8_ext + beta_incr; 77 | 78 | Comb64 : 79 | if (beta_done & phiU) nop, lambda_m_6 + comb_by_8_ext + beta_incr; // phi4 >> 80 | else if (beta_done) jump Do_8x8, lambda_m_6 + comb_by_8_ext + beta_incr; 81 | else wait, lambda_m_6 + comb_by_8_ext + beta_incr; 82 | 83 | Comb128 : 84 | if (beta_done & phiU) nop, lambda_m_7 + comb_by_8_ext + beta_incr; // phi5 >> 85 | else if (beta_done) jump Do_8x8, lambda_m_7 + comb_by_8_ext + beta_incr; 86 | else wait, lambda_m_7 + comb_by_8_ext + beta_incr; 87 | 88 | Comb256 : 89 | if (beta_done & phiU) nop, lambda_m_8 + comb_by_8_ext + beta_incr; // phi6 >> 90 | else if (beta_done) jump Do_8x8, lambda_m_8 + comb_by_8_ext + beta_incr; 91 | else wait, lambda_m_8 + comb_by_8_ext + beta_incr; 92 | 93 | Comb512 : 94 | if (beta_done) nop, lambda_m_9 + comb_by_8_last + beta_incr; 95 | else wait, lambda_m_9 + comb_by_8_last + beta_incr; 96 | 97 | Done : 98 | jump Wait_BufferReay, ibuf_set_empty + obuf_set_full; 99 | 100 | end -------------------------------------------------------------------------------- /rtl/pc_3gpp/enc/pc_3gpp_enc_types.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : polar code 3gpp 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : pc_3gpp_enc_types.svh 5 | // Description : Encoder parameters, constants and types 6 | // 7 | 8 | parameter int pN_MAX = 1024; // fixed. don't change 9 | 10 | parameter int pTAG_W = 4; 11 | 12 | // internal engine parameters 13 | parameter int pWORD_W = 8; // engine word width fixed. don't change 14 | 15 | //------------------------------------------------------------------------------------------------------ 16 | // 17 | //------------------------------------------------------------------------------------------------------ 18 | 19 | localparam int cNLOG2 = $clog2(pN_MAX); 20 | 21 | localparam int cBIT_ADDR_W = $clog2(pN_MAX); 22 | 23 | localparam int cWORD_ADDR_W = $clog2(pN_MAX/pWORD_W); 24 | 25 | localparam int cCRC_W = 5; 26 | 27 | //------------------------------------------------------------------------------------------------------ 28 | // alu opcodes 29 | //------------------------------------------------------------------------------------------------------ 30 | 31 | typedef enum bit [2 : 0] { 32 | cNOP = 3'b0_00 , 33 | 34 | cDO_8x8 = 3'b0_01 , 35 | 36 | cCOMB_int = 3'b1_00 , // internal reg 37 | cCOMB_intc = 3'b1_01 , // internal cache 38 | cCOMB_ext = 3'b1_10 , // external ram 39 | cCOMB_last = 3'b1_11 // last comb 40 | } alu_opcode_e; 41 | 42 | typedef logic [2 : 0] alu_opcode_t; 43 | 44 | //------------------------------------------------------------------------------------------------------ 45 | // 46 | //------------------------------------------------------------------------------------------------------ 47 | 48 | typedef logic [cBIT_ADDR_W-1 : 0] bit_addr_t; 49 | 50 | typedef logic [cWORD_ADDR_W-1 : 0] beta_w_addr_t; 51 | typedef logic [pWORD_W-1 : 0] beta_w_dat_t; 52 | 53 | typedef logic [cCRC_W-1 : 0] crc_t; 54 | 55 | typedef logic [pTAG_W-1 : 0] tag_t; 56 | 57 | `include "../pc_3gpp_functions.svh" 58 | -------------------------------------------------------------------------------- /rtl/pc_3gpp/pc_3gpp_beta_ram.sv: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | 5 | parameter int pADDR_W = 8 ; 6 | parameter int pDAT_W = 8 ; 7 | parameter bit pPIPE = 0 ; 8 | 9 | 10 | 11 | logic pc_3gpp_beta_ram__iclk ; 12 | logic pc_3gpp_beta_ram__ireset ; 13 | logic pc_3gpp_beta_ram__iclkena ; 14 | logic pc_3gpp_beta_ram__iwrite ; 15 | logic [pADDR_W-1 : 0] pc_3gpp_beta_ram__iwaddr ; 16 | logic pc_3gpp_beta_ram__iwsel ; 17 | logic [pDAT_W-1 : 0] pc_3gpp_beta_ram__iwdat ; 18 | logic [pADDR_W-1 : 0] pc_3gpp_beta_ram__iraddr ; 19 | logic [pDAT_W-1 : 0] pc_3gpp_beta_ram__ordat [2] ; 20 | 21 | 22 | 23 | pc_3gpp_beta_ram 24 | #( 25 | .pADDR_W ( pADDR_W ) , 26 | .pDAT_W ( pDAT_W ) , 27 | .pPIPE ( pPIPE ) 28 | ) 29 | pc_3gpp_beta_ram 30 | ( 31 | .iclk ( pc_3gpp_beta_ram__iclk ) , 32 | .ireset ( pc_3gpp_beta_ram__ireset ) , 33 | .iclkena ( pc_3gpp_beta_ram__iclkena ) , 34 | .iwrite ( pc_3gpp_beta_ram__iwrite ) , 35 | .iwaddr ( pc_3gpp_beta_ram__iwaddr ) , 36 | .iwsel ( pc_3gpp_beta_ram__iwsel ) , 37 | .iwdat ( pc_3gpp_beta_ram__iwdat ) , 38 | .iraddr ( pc_3gpp_beta_ram__iraddr ) , 39 | .ordat ( pc_3gpp_beta_ram__ordat ) 40 | ); 41 | 42 | 43 | assign pc_3gpp_beta_ram__iclk = '0 ; 44 | assign pc_3gpp_beta_ram__ireset = '0 ; 45 | assign pc_3gpp_beta_ram__iclkena = '0 ; 46 | assign pc_3gpp_beta_ram__iwrite = '0 ; 47 | assign pc_3gpp_beta_ram__iwaddr = '0 ; 48 | assign pc_3gpp_beta_ram__iwsel = '0 ; 49 | assign pc_3gpp_beta_ram__iwdat = '0 ; 50 | assign pc_3gpp_beta_ram__iraddr = '0 ; 51 | 52 | 53 | 54 | */ 55 | 56 | // 57 | // Project : polar code 3gpp 58 | // Author : Shekhalev Denis (des00) 59 | // Workfile : pc_3gpp_beta_ram.v 60 | // Description : Beta (bit) ram for intermediate layer bit data. Ram used in recursive encoder and decoder 61 | // 62 | 63 | 64 | module pc_3gpp_beta_ram 65 | #( 66 | parameter int pADDR_W = 8 , 67 | parameter int pDAT_W = 8 , 68 | parameter bit pPIPE = 0 69 | ) 70 | ( 71 | iclk , 72 | ireset , 73 | iclkena , 74 | // 75 | iwrite , 76 | iwaddr , 77 | iwsel , 78 | iwdat , 79 | // 80 | iraddr , 81 | ordat 82 | ); 83 | 84 | //------------------------------------------------------------------------------------------------------ 85 | // 86 | //------------------------------------------------------------------------------------------------------ 87 | 88 | input logic iclk ; 89 | input logic ireset ; 90 | input logic iclkena ; 91 | // 92 | input logic iwrite ; 93 | input logic [pADDR_W-1 : 0] iwaddr ; 94 | input logic iwsel ; 95 | input logic [pDAT_W-1 : 0] iwdat ; 96 | // 97 | input logic [pADDR_W-1 : 0] iraddr ; 98 | output logic [pDAT_W-1 : 0] ordat [2] ; 99 | 100 | //------------------------------------------------------------------------------------------------------ 101 | // 102 | //------------------------------------------------------------------------------------------------------ 103 | 104 | bit [pDAT_W-1 : 0] ram0 [2**pADDR_W] /* synthesis ramstyle = "no_rw_check" */; 105 | bit [pDAT_W-1 : 0] ram1 [2**pADDR_W] /* synthesis ramstyle = "no_rw_check" */; 106 | 107 | logic [pDAT_W-1 : 0] rdat [2][2]; 108 | 109 | //------------------------------------------------------------------------------------------------------ 110 | // 111 | //------------------------------------------------------------------------------------------------------ 112 | 113 | always_ff @(posedge iclk) begin 114 | if (iclkena) begin 115 | if (iwrite) begin 116 | if (iwsel) begin 117 | ram1[iwaddr] <= iwdat; 118 | end 119 | else begin 120 | ram0[iwaddr] <= iwdat; 121 | end 122 | end 123 | rdat[0][0] <= ram0[iraddr]; 124 | rdat[0][1] <= ram1[iraddr]; 125 | // 126 | rdat[1] <= rdat[0]; 127 | end 128 | end 129 | 130 | assign ordat = rdat[pPIPE]; 131 | 132 | endmodule 133 | -------------------------------------------------------------------------------- /rtl/pc_3gpp/pc_3gpp_functions.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : polar code 3gpp 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : pc_3gpp_functions.svh 5 | // Description : Common for encoder and decoder functions 6 | // 7 | 8 | //------------------------------------------------------------------------------------------------------ 9 | // address bit reverse function 10 | //------------------------------------------------------------------------------------------------------ 11 | 12 | function bit_addr_t reverse_bit (input bit_addr_t addr, int used_nlog2 = cNLOG2); 13 | reverse_bit = '0; 14 | for (int i = 0; i < used_nlog2; i++) begin 15 | reverse_bit[used_nlog2-1-i] = addr[i]; 16 | end 17 | endfunction 18 | 19 | //------------------------------------------------------------------------------------------------------ 20 | // 3GPP CRC function 21 | //------------------------------------------------------------------------------------------------------ 22 | 23 | function bit [4 : 0] get_crc (input bit [4 : 0] crc, bit dat); 24 | get_crc = {crc[0], crc[4 : 1] ^ {3'b000, dat}}; 25 | endfunction 26 | 27 | //------------------------------------------------------------------------------------------------------ 28 | // polar coding 8x8 engine. reverse bit order only 29 | //------------------------------------------------------------------------------------------------------ 30 | 31 | function automatic bit [7 : 0] do_ns_encode_8x8 (input bit [7 : 0] datb); 32 | bit [7 : 0] codeb; 33 | begin 34 | codeb[0] = datb[0]; 35 | codeb[1] = datb[4]; 36 | codeb[2] = datb[2]; 37 | codeb[3] = datb[6]; 38 | 39 | codeb[4] = datb[1]; 40 | codeb[5] = datb[5]; 41 | codeb[6] = datb[3]; 42 | codeb[7] = datb[7]; 43 | // layer 2 44 | codeb[0] ^= codeb[1]; 45 | codeb[2] ^= codeb[3]; 46 | codeb[4] ^= codeb[5]; 47 | codeb[6] ^= codeb[7]; 48 | // layer 1 49 | codeb[0] ^= codeb[2]; 50 | codeb[1] ^= codeb[3]; 51 | codeb[4] ^= codeb[6]; 52 | codeb[5] ^= codeb[7]; 53 | // layer 0 54 | codeb[0] ^= codeb[4]; 55 | codeb[1] ^= codeb[5]; 56 | codeb[2] ^= codeb[6]; 57 | codeb[3] ^= codeb[7]; 58 | // 59 | do_ns_encode_8x8 = codeb; 60 | end 61 | endfunction 62 | 63 | //------------------------------------------------------------------------------------------------------ 64 | // comb 8 encoding engine. reverse bit order only 65 | //------------------------------------------------------------------------------------------------------ 66 | 67 | function automatic bit [7 : 0] do_comb8 (input bit [7 : 0] bitL, bitR, bit bsel); 68 | bit [7 : 0] codeb; 69 | begin 70 | if (bsel) begin 71 | {codeb[6], codeb[4], codeb[2], codeb[0]} = bitL[4 +: 4] ^ bitR[4 +: 4]; 72 | {codeb[7], codeb[5], codeb[3], codeb[1]} = bitR[4 +: 4]; 73 | end 74 | else begin 75 | {codeb[6], codeb[4], codeb[2], codeb[0]} = bitL[0 +: 4] ^ bitR[0 +: 4]; 76 | {codeb[7], codeb[5], codeb[3], codeb[1]} = bitR[0 +: 4]; 77 | end 78 | // 79 | do_comb8 = codeb; 80 | end 81 | endfunction 82 | -------------------------------------------------------------------------------- /rtl/rs/README.md: -------------------------------------------------------------------------------- 1 | Static configuration Reed-Solomon decoder based upon Reformulated Inversion-less Berlekamp algorithm & Chieny Search. 2 | 3 | Generator polynomial generated automatically from module settings. 4 | 5 | There is 4 version of RIBM realisation in simple decoder. The fastest one use "t = d/2" tick only for decoding. 6 | 7 | There is 2 verion of RIBM realization in erasure decoder. The fastest one use "2*t = d" tick only for decoding. 8 | 9 | Decoders has no any FIFO and use strong external synchronisation inside. It should be reliable completely) 10 | 11 | vivado 2019.1 Artix 7 - 2 12 | 13 | RS (240, 210, 30), RIBM take 6*30=180 ticks for simple decoding & 2*30=60 ticks for erasure decoding 14 | 15 | Encoder : LUT/REG 240/252 >250MHz (1.75Gbps -> 2Gbps) 16 | 17 | Decoder simple : LUT/REG/RAMB 2.2k/1.6k/1.0 ~250MHz (2Gbps -> 1.75Gbps) 18 | 19 | Decoder erasure : LUT/REG/RAMB 10k/2.6k/1.0 ~225MHz (1.8Gbps -> 1.55Gbps) 20 | 21 | Attention: Simple decoder don't revert back symbol errors if "decoder fail" occurred. 22 | The erasure decoder will revert back symbols to input channel state in that case 23 | 24 | 25 | -------------------------------------------------------------------------------- /rtl/rs/erasure/rs_eras_berlekamp_ribm_2check.sv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dshekhalev/FEC/917f5c85e6638c2a38a74f2f8ca0ab928d7dfd98/rtl/rs/erasure/rs_eras_berlekamp_ribm_2check.sv -------------------------------------------------------------------------------- /rtl/rs/erasure/rs_eras_berlekamp_ribm_2check_by_check.sv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dshekhalev/FEC/917f5c85e6638c2a38a74f2f8ca0ab928d7dfd98/rtl/rs/erasure/rs_eras_berlekamp_ribm_2check_by_check.sv -------------------------------------------------------------------------------- /rtl/rsc/README.md: -------------------------------------------------------------------------------- 1 | Static configuration DVB-RSC (ETSI EN 301 790 V1.5.1) & Wimax CTC (IEEE Std 802.16-2009) duo-binary convolution turbo code with MAX-Log-MAP decoding. 2 | 3 | Supported modes: DVB-RCS 12 modes, Wimax OFDM 4 P0 factor up to 4096 duo-bits , Wimax OFDMA 16 modes. 4 | 5 | Supports code rates: all defined in the standards + additional code rates like 7/8, 8/9, 9/10 or 3/7 6 | 7 | Encoder uses two pass coding with minimal delays. 8 | 9 | Decoder uses special MAP engine with 1 duo-bits per tick processing and simultaneous forward/backard recursion. 10 | 11 | vivado 2019.1 Artix 7 - 2 12 | 13 | Wimax OFDMA Nduobits = 1920(3840 bits), coderate = 2/3, 5bit metric, 10 iteration. Encoder use output buffer 14 | 15 | Encoder : LUT/REG/RAMB 210/179/2.0 >200MHz (200Mbps -> 300Mbps) 16 | 17 | Decoder simple : LUT/REG/RAMB 5.3k/4.7k/12.0 ~160MHz (24Mbps -> 16Mbps) 18 | 19 | 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. 20 | -------------------------------------------------------------------------------- /rtl/rsc/dec/rsc_dec_types.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : rsc 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : rsc_dec_types.svh 5 | // Description : file with all decoder used types 6 | // 7 | 8 | //------------------------------------------------------------------------------------------------------ 9 | // used types for decoder 10 | //------------------------------------------------------------------------------------------------------ 11 | 12 | localparam int cDLLR_W = pLLR_W + 1; // duo-bin LLR 13 | localparam int cL_EXT_W = cDLLR_W + 2; // Lextrinsic ~= 4*cDLLR_W 14 | localparam int cSTATE_W = cL_EXT_W + 3; // state(k) ~= Lextrinsic + gamma + state(k) 15 | localparam int cGAMMA_W = cSTATE_W + 1; // Lextrinsic + gammaL + alpha(k) + beta(k+1) 16 | 17 | localparam int cSTATE_DIFF_W = cSTATE_W - 2; // State difference is 2 bit less then state 18 | 19 | // 20 | // single word type 21 | typedef logic signed [pLLR_W-1 : 0] bit_llr_t; 22 | typedef logic signed [cDLLR_W-1 : 0] dbit_llr_t; 23 | 24 | typedef logic signed [cL_EXT_W-1 : 0] extr_llr_t; 25 | 26 | typedef logic signed [cSTATE_W-1 : 0] trel_state_t; 27 | typedef logic signed [cSTATE_DIFF_W-1 : 0] trel_state_diff_t; 28 | 29 | typedef logic signed [cGAMMA_W-1 : 0] trel_branch_t; 30 | typedef logic signed [cGAMMA_W : 0] trel_branch_p1_t; 31 | typedef logic signed [cGAMMA_W+1 : 0] trel_branch_p2_t; 32 | 33 | // 34 | // arrays type 35 | typedef dbit_llr_t dbit_allr_t [1:3]; 36 | 37 | typedef extr_llr_t Lextr_t [1:3]; 38 | typedef trel_state_t Lapri_t [1:3]; 39 | typedef trel_branch_t Lapo_t [1:3]; 40 | 41 | typedef trel_state_t state_t [8]; 42 | typedef trel_state_t gamma_t [8][4]; 43 | 44 | typedef trel_branch_t bm_t [8][4]; 45 | 46 | // 47 | // packed types for metric memory : TODO in future 48 | typedef struct packed { 49 | trel_state_t basea; 50 | trel_state_diff_t diffa0, diffa1, diff2; 51 | trel_state_t baseb; 52 | trel_state_diff_t diffb0, diffb1, diffb2; 53 | } metric_mem_t; 54 | 55 | 56 | -------------------------------------------------------------------------------- /rtl/rsc/dec/rsc_mmax.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : rsc 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : rsc_mmax.svh 5 | // Description : file with MAX* function realisation for different decoder data types 6 | // 7 | 8 | //------------------------------------------------------------------------------------------------------ 9 | // define used MAX* functions 10 | //------------------------------------------------------------------------------------------------------ 11 | 12 | function trel_state_t st_mmax (input trel_state_t a, b); 13 | st_mmax = (a > b) ? a : b; 14 | endfunction 15 | 16 | // 17 | // module based max for state processor 18 | function trel_state_t st_m_mmax (input trel_state_t a, b); 19 | trel_state_t tmp; 20 | begin 21 | tmp = a - b; 22 | st_m_mmax = tmp[cSTATE_W-1] ? b : a; 23 | end 24 | endfunction 25 | 26 | function trel_branch_t bm_mmax (input trel_branch_t a, b); 27 | bm_mmax = (a > b) ? a : b; 28 | endfunction 29 | 30 | function trel_branch_t bm_mmax1 (input trel_branch_t a, b); 31 | trel_branch_p1_t tmp; 32 | begin 33 | tmp = a - b; 34 | bm_mmax1 = (tmp[cGAMMA_W] ? b : a) + (~|tmp[cGAMMA_W : pLLR_FP+1] | &tmp[cGAMMA_W : pLLR_FP+1]); 35 | end 36 | endfunction 37 | 38 | // 39 | // module parallel max selector 40 | function trel_state_t st_m_p_mmax (input trel_state_t a, b, c, d); 41 | trel_state_t tmp_ab; 42 | trel_state_t tmp_ac; 43 | trel_state_t tmp_ad; 44 | trel_state_t tmp_bc; 45 | trel_state_t tmp_bd; 46 | trel_state_t tmp_cd; 47 | // 48 | bit b_more_a, c_more_a, d_more_a; 49 | bit c_more_b, d_more_b; 50 | bit d_more_c; 51 | // 52 | trel_state_t tmpH; 53 | trel_state_t tmpL; 54 | begin 55 | tmp_ab = a - b; tmp_ac = a - c; tmp_ad = a - d; 56 | tmp_bc = b - c; tmp_bd = b - d; 57 | tmp_cd = c - d; 58 | // 59 | b_more_a = tmp_ab[cSTATE_W-1]; 60 | c_more_a = tmp_ac[cSTATE_W-1]; 61 | d_more_a = tmp_ad[cSTATE_W-1]; 62 | c_more_b = tmp_bc[cSTATE_W-1]; 63 | d_more_b = tmp_bd[cSTATE_W-1]; 64 | d_more_c = tmp_cd[cSTATE_W-1]; 65 | // 66 | tmpH = b_more_a ? b : a; 67 | tmpL = d_more_c ? d : c; 68 | 69 | case ({b_more_a, d_more_c}) 70 | 2'b00 : st_m_p_mmax = c_more_a ? tmpL : tmpH; 71 | 2'b01 : st_m_p_mmax = d_more_a ? tmpL : tmpH; 72 | 2'b10 : st_m_p_mmax = c_more_b ? tmpL : tmpH; 73 | default : st_m_p_mmax = d_more_b ? tmpL : tmpH; 74 | endcase 75 | end 76 | endfunction 77 | 78 | // 79 | // parallel max selector 80 | function trel_state_t st_p_mmax (input trel_state_t a, b, c, d); 81 | bit a_more_b, a_more_c, a_more_d; 82 | bit b_more_c, b_more_d; 83 | bit c_more_d; 84 | bit [1 : 0] sel; 85 | begin 86 | a_more_b = (a > b); a_more_c = (a > c); a_more_d = (a > d); 87 | b_more_c = (b > c); b_more_d = (b > d); 88 | c_more_d = (c > d); 89 | // 90 | if (a_more_b) begin 91 | if (c_more_d) begin 92 | sel = a_more_c ? 2'b00 : 2'b10; 93 | end 94 | else begin// d_more_c 95 | sel = a_more_d ? 2'b00 : 2'b11; 96 | end 97 | end 98 | else begin // b_more_a 99 | if (c_more_d) begin 100 | sel = b_more_c ? 2'b01 : 2'b10; 101 | end 102 | else begin// d_more_c 103 | sel = b_more_d ? 2'b01 : 2'b11; 104 | end 105 | end 106 | // 107 | case (sel) 108 | 2'b00 : st_p_mmax = a; 109 | 2'b01 : st_p_mmax = b; 110 | 2'b10 : st_p_mmax = c; 111 | 2'b11 : st_p_mmax = d; 112 | default : st_p_mmax = a; 113 | endcase 114 | end 115 | endfunction 116 | 117 | -------------------------------------------------------------------------------- /rtl/rsc/dec/rsc_trellis.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : rsc 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : rsc_trellis.svh 5 | // Description : file with RSC trellis generate functions 6 | // 7 | 8 | //------------------------------------------------------------------------------------------------------ 9 | // define types and functions to get RSC trellis 10 | //------------------------------------------------------------------------------------------------------ 11 | 12 | typedef struct { 13 | bit [2 : 0] nextStates [8][4]; 14 | bit [2 : 0] preStates [8][4]; 15 | bit [1 : 0] outputs [8][4]; 16 | bit outputsy [8][4]; 17 | bit outputsw [8][4]; 18 | } trellis_t; 19 | 20 | trellis_t trel; 21 | 22 | always_comb begin 23 | trel = get_rsc_trellis (0); 24 | end 25 | 26 | //------------------------------------------------------------------------------------------------------ 27 | // function's to get rsc trellis 28 | //------------------------------------------------------------------------------------------------------ 29 | 30 | function trellis_t get_rsc_trellis (input int tmp); 31 | trellis_t trel; 32 | bit [2 : 0] nstate; 33 | bit y, w; 34 | begin 35 | for (int ab = 0; ab < 4; ab++) begin 36 | for (int state = 0; state < 8; state++) begin 37 | nstate = {ab[1] ^ state[2] ^ state[0], state[2:1]}; // feedback poly [1 1 0 1] 38 | nstate = nstate ^ {3{ab[0]}}; 39 | 40 | y = nstate[2] ^ state[1] ^ state[0]; // poly [1 0 1 1] 41 | w = nstate[2] ^ state[0]; // poly [1 0 0 1] 42 | // 43 | trel.nextStates[state][ab] = nstate; 44 | trel.outputsy [state][ab] = y; 45 | trel.outputsw [state][ab] = w; 46 | trel.outputs [state][ab] = {y, w}; 47 | end 48 | end 49 | // 50 | for (int ab = 0; ab < 4; ab++) begin 51 | for (int state = 0; state < 8; state++) begin 52 | nstate = trel.nextStates[state][ab]; 53 | trel.preStates[nstate][ab] = state[2 : 0]; 54 | end 55 | end 56 | // 57 | get_rsc_trellis = trel; 58 | end 59 | endfunction 60 | 61 | function logic [4 : 0] do_encode (input logic a, b, input logic [2 : 0] state); 62 | logic [2 : 0] nstate; 63 | logic y, w; 64 | begin 65 | nstate = {a ^ state[2] ^ state[0], state[2:1]}; // feedback poly [1 1 0 1] 66 | nstate = nstate ^ {3{b}}; 67 | 68 | y = nstate[2] ^ state[1] ^ state[0]; // poly [1 0 1 1] 69 | w = nstate[2] ^ state[0]; // poly [1 0 0 1] 70 | 71 | do_encode = {y, w, nstate}; 72 | end 73 | endfunction 74 | -------------------------------------------------------------------------------- /rtl/rsc/rsc_constants.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : rsc 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : rsc_constants.svh 5 | // Description : DVB/Wimax constants and constant types 6 | // 7 | 8 | typedef logic [3 : 0] code_t; // code rate 0 - 1/3, 9 | // [1 : 9] - [1/2; 2/3; 3/4; 4/5; 5/6; 6/7; 7/8; 8/9; 9/10] 10 | // [10:11] - [2:3]/5 11 | // 12 - 3/7 12 | 13 | typedef logic [4 : 0] ptype_t; // permutation type [ 0:11] - DVB P0/P1/P2/P3, 14 | // [12:15] - WiMax P0 = 7/11/13/17 15 | // [16:31] - WimaxA P0/P1/P2/P3, 16 | 17 | typedef logic [12 : 0] dbits_num_t; // number of data duobits/byte size [32:4096]/[8:1024] 18 | 19 | //------------------------------------------------------------------------------------------------------ 20 | // 21 | //------------------------------------------------------------------------------------------------------ 22 | 23 | typedef struct packed { 24 | code_t code; 25 | ptype_t ptype; 26 | dbits_num_t Ndbits; 27 | } code_ctx_t; 28 | 29 | -------------------------------------------------------------------------------- /rtl/rsc/rsc_enc_wrp.sv: -------------------------------------------------------------------------------- 1 | // 2 | // Project : rsc 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : rsc_enc_wrp.sv 5 | // Description : RSC encoder wrapper for synthesis 6 | // 7 | 8 | module rsc_enc_wrp 9 | #( 10 | parameter int pTAG_W = 8 , 11 | // 12 | parameter int pCODE = 3 , // coderate 13 | parameter int pPTYPE = 31 , // permutation type 14 | parameter int pN = 1920 , // number of data duobit's <= 4096 15 | // 16 | parameter bit pUSE_OBUFFER = 1 // use output buffer at encoder output 17 | ) 18 | ( 19 | iclk , 20 | ireset , 21 | iclkena , 22 | // 23 | isop , 24 | ieop , 25 | ival , 26 | idat , 27 | itag , 28 | // 29 | obusy , 30 | ordy , 31 | // 32 | idbsclk , 33 | ofull , 34 | // 35 | osop , 36 | oeop , 37 | oeof , 38 | oval , 39 | odat , 40 | otag 41 | ); 42 | 43 | //------------------------------------------------------------------------------------------------------ 44 | // 45 | //------------------------------------------------------------------------------------------------------ 46 | 47 | input logic iclk ; 48 | input logic ireset ; 49 | input logic iclkena ; 50 | // 51 | input logic isop ; 52 | input logic ieop ; 53 | input logic ival ; 54 | input logic [1 : 0] idat ; 55 | input logic [pTAG_W-1 : 0] itag ; 56 | // 57 | output logic obusy ; 58 | output logic ordy ; 59 | // 60 | input logic idbsclk ; // output debit symbol clock 61 | output logic ofull ; 62 | // 63 | output logic osop ; 64 | output logic oeop ; 65 | output logic oeof ; 66 | output logic oval ; 67 | output logic [1 : 0] odat ; 68 | output logic [pTAG_W-1 : 0] otag ; 69 | 70 | //------------------------------------------------------------------------------------------------------ 71 | // 72 | //------------------------------------------------------------------------------------------------------ 73 | 74 | rsc_enc 75 | #( 76 | .pTAG_W ( pTAG_W ) , 77 | .pN_MAX ( pN ) , 78 | .pUSE_FIXED_CODE ( 1 ) , 79 | .pUSE_OBUFFER ( pUSE_OBUFFER ) 80 | ) 81 | rsc_enc 82 | ( 83 | .iclk ( iclk ) , 84 | .ireset ( ireset ) , 85 | .iclkena ( iclkena ) , 86 | // 87 | .icode ( pCODE ) , 88 | .iptype ( pPTYPE ) , 89 | .iN ( pN ) , 90 | // 91 | .isop ( isop ) , 92 | .ieop ( ieop ) , 93 | .ival ( ival ) , 94 | .idat ( idat ) , 95 | .itag ( itag ) , 96 | // 97 | .obusy ( obusy ) , 98 | .ordy ( ordy ) , 99 | // 100 | .idbsclk ( idbsclk ) , 101 | .ofull ( ofull ) , 102 | // 103 | .osop ( osop ) , 104 | .oeop ( oeop ) , 105 | .oeof ( oeof ) , 106 | .oval ( oval ) , 107 | .odat ( odat ) , 108 | .otag ( otag ) 109 | ); 110 | 111 | endmodule 112 | -------------------------------------------------------------------------------- /rtl/rsc/rsc_sctable.sv: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | logic rsc_sctable__iclk ; 5 | logic rsc_sctable__ireset ; 6 | logic rsc_sctable__iclkena ; 7 | logic [2 : 0] rsc_sctable__iNmod7 ; 8 | logic [2 : 0] rsc_sctable__istate ; 9 | logic [2 : 0] rsc_sctable__ostate ; 10 | logic [2 : 0] rsc_sctable__ostate_r ; 11 | 12 | 13 | 14 | rsc_sctable 15 | rsc_sctable 16 | ( 17 | .iclk ( rsc_sctable__iclk ) , 18 | .ireset ( rsc_sctable__ireset ) , 19 | .iclkena ( rsc_sctable__iclkena ) , 20 | .iNmod7 ( rsc_sctable__iNmod7 ) , 21 | .istate ( rsc_sctable__istate ) , 22 | .ostate ( rsc_sctable__ostate ) , 23 | .ostate_r ( rsc_sctable__ostate_r ) 24 | ); 25 | 26 | 27 | assign rsc_sctable__iclk = '0 ; 28 | assign rsc_sctable__ireset = '0 ; 29 | assign rsc_sctable__iclkena = '0 ; 30 | assign rsc_sctable__iNmod7 = '0 ; 31 | assign rsc_sctable__istate = '0 ; 32 | 33 | 34 | 35 | */ 36 | 37 | // 38 | // Project : rsc 39 | // Author : Shekhalev Denis (des00) 40 | // Workfile : rsc_sctable.sv 41 | // Description : Circullar state correspondence table. Its static table for different packet lengths 8 <= N/4 <= 1024 42 | // Module can use asynchronus or register output for correspondence state 43 | // 44 | 45 | module rsc_sctable 46 | ( 47 | iclk , 48 | ireset , 49 | iclkena , 50 | iNmod7 , 51 | istate , 52 | ostate , 53 | ostate_r 54 | ); 55 | 56 | //------------------------------------------------------------------------------------------------------ 57 | // 58 | //------------------------------------------------------------------------------------------------------ 59 | 60 | input logic iclk ; 61 | input logic ireset ; 62 | input logic iclkena ; 63 | input logic [2 : 0] iNmod7 ; 64 | input logic [2 : 0] istate ; 65 | output logic [2 : 0] ostate ; 66 | output logic [2 : 0] ostate_r ; 67 | 68 | //------------------------------------------------------------------------------------------------------ 69 | // 70 | //------------------------------------------------------------------------------------------------------ 71 | 72 | typedef bit [2 : 0] lut_line_t [0 : 7]; 73 | typedef lut_line_t lut_t [0 : 7]; 74 | 75 | localparam lut_t cLUT = '{ 76 | '{0, 0, 0, 0, 0, 0, 0, 0} , // 0 77 | '{0, 6, 4, 2, 7, 1, 3, 5} , // 1 78 | '{0, 3, 7, 4, 5, 6, 2, 1} , // 2 79 | '{0, 5, 3, 6, 2, 7, 1, 4} , // 3 80 | '{0, 4, 1, 5, 6, 2, 7, 3} , // 4 81 | '{0, 2, 5, 7, 1, 3, 4, 6} , // 5 82 | '{0, 7, 6, 1, 3, 4, 5, 2} , // 6 83 | '{0, 0, 0, 0, 0, 0, 0, 0} // 7 84 | }; 85 | 86 | //------------------------------------------------------------------------------------------------------ 87 | // 88 | //------------------------------------------------------------------------------------------------------ 89 | 90 | assign ostate = cLUT[iNmod7][istate]; 91 | 92 | always_ff @(posedge iclk) begin 93 | if (iclkena) begin 94 | ostate_r <= ostate; 95 | end 96 | end 97 | 98 | endmodule 99 | -------------------------------------------------------------------------------- /rtl/rsc2/README.md: -------------------------------------------------------------------------------- 1 | Dynamic configuration DVB-RSC2 (ETSI EN 301 545-2 V1.2.1) duo-binary convolution turbo code with MAX-Log-MAP decoding. 2 | 3 | Supported modes: all modes defined in Table A-1/2/4/5 4 | 5 | Supports code rates: [1/3; 1/2; 2/3; 3/4; 4/5; 5/6; 6/7; 7/8] 6 | 7 | Encoder uses two pass coding with minimal delays. 8 | 9 | Decoder uses special MAP engine with 1 duo-bits per tick processing and simultaneous forward/backard recursion. 10 | 11 | vivado 2019.1 Artix 7 - 2 12 | 13 | Wimax OFDMA Nduobits = 152(304 bits), coderate = 1/2, 5bit metric, 10 iteration. Encoder use output buffer 14 | 15 | Encoder : LUT/REG/RAMB 330/255/2.0 >200MHz (245Mbps -> 490Mbps) 16 | 17 | Decoder simple : LUT/REG/RAMB 9.5k/8k/10.0 ~160MHz (29Mbps -> 14.5Mbps) 18 | 19 | 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. 20 | -------------------------------------------------------------------------------- /rtl/rsc2/dec/rsc2_dec_types.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : rsc 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : rsc_dec_types.sv 5 | // Description : file with all decoder used types 6 | // 7 | 8 | //------------------------------------------------------------------------------------------------------ 9 | // used types for decoder 10 | //------------------------------------------------------------------------------------------------------ 11 | 12 | localparam int cDLLR_W = pLLR_W + 1; // duo-bin LLR 13 | localparam int cL_EXT_W = cDLLR_W + 2; // Lextrinsic ~= 4*cDLLR_W 14 | localparam int cSTATE_W = cL_EXT_W + 3; // state(k) ~= Lextrinsic + gamma + state(k) 15 | localparam int cGAMMA_W = cSTATE_W + 1; // Lextrinsic + gammaL + alpha(k) + beta(k+1) 16 | 17 | localparam int cSTATE_DIFF_W = cSTATE_W - 2; // State difference is 2 bit less then state 18 | 19 | // 20 | // single word type 21 | typedef logic signed [pLLR_W-1 : 0] bit_llr_t; 22 | typedef logic signed [cDLLR_W-1 : 0] dbit_llr_t; 23 | 24 | typedef logic signed [cL_EXT_W-1 : 0] extr_llr_t; 25 | 26 | typedef logic signed [cSTATE_W-1 : 0] trel_state_t; 27 | typedef logic signed [cSTATE_DIFF_W-1 : 0] trel_state_diff_t; 28 | 29 | typedef logic signed [cGAMMA_W-1 : 0] trel_branch_t; 30 | typedef logic signed [cGAMMA_W : 0] trel_branch_p1_t; 31 | typedef logic signed [cGAMMA_W+1 : 0] trel_branch_p2_t; 32 | 33 | // 34 | // arrays type 35 | typedef dbit_llr_t dbit_allr_t [1:3]; 36 | 37 | typedef extr_llr_t Lextr_t [1:3]; 38 | typedef trel_state_t Lapri_t [1:3]; 39 | typedef trel_branch_t Lapo_t [1:3]; 40 | 41 | typedef trel_state_t state_t [16]; 42 | typedef trel_state_t gamma_t [16][4]; 43 | 44 | typedef trel_branch_t bm_t [16][4]; 45 | 46 | // 47 | // packed types for metric memory : TODO in future 48 | typedef struct packed { 49 | trel_state_t basea; 50 | trel_state_diff_t diffa0, diffa1, diff2; 51 | trel_state_t baseb; 52 | trel_state_diff_t diffb0, diffb1, diffb2; 53 | } metric_mem_t; 54 | 55 | 56 | -------------------------------------------------------------------------------- /rtl/rsc2/dec/rsc2_mmax.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : rsc2 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : rsc2_mmax.svh 5 | // Description : file with MAX* function realisation for different decoder data types 6 | // 7 | 8 | //------------------------------------------------------------------------------------------------------ 9 | // define used MAX* functions 10 | //------------------------------------------------------------------------------------------------------ 11 | 12 | function trel_state_t st_mmax (input trel_state_t a, b); 13 | st_mmax = (a > b) ? a : b; 14 | endfunction 15 | 16 | // 17 | // module based max for state processor 18 | function trel_state_t st_m_mmax (input trel_state_t a, b); 19 | trel_state_t tmp; 20 | begin 21 | tmp = a - b; 22 | st_m_mmax = tmp[cSTATE_W-1] ? b : a; 23 | end 24 | endfunction 25 | 26 | function trel_branch_t bm_mmax (input trel_branch_t a, b); 27 | bm_mmax = (a > b) ? a : b; 28 | endfunction 29 | 30 | function trel_branch_t bm_mmax1 (input trel_branch_t a, b); 31 | trel_branch_p1_t tmp; 32 | begin 33 | tmp = a - b; 34 | bm_mmax1 = (tmp[cGAMMA_W] ? b : a) + (~|tmp[cGAMMA_W : pLLR_FP+1] | &tmp[cGAMMA_W : pLLR_FP+1]); 35 | end 36 | endfunction 37 | 38 | // 39 | // module parallel max selector 40 | function trel_state_t st_m_p_mmax (input trel_state_t a, b, c, d); 41 | trel_state_t tmp_ab; 42 | trel_state_t tmp_ac; 43 | trel_state_t tmp_ad; 44 | trel_state_t tmp_bc; 45 | trel_state_t tmp_bd; 46 | trel_state_t tmp_cd; 47 | // 48 | bit b_more_a, c_more_a, d_more_a; 49 | bit c_more_b, d_more_b; 50 | bit d_more_c; 51 | // 52 | trel_state_t tmpH; 53 | trel_state_t tmpL; 54 | begin 55 | tmp_ab = a - b; tmp_ac = a - c; tmp_ad = a - d; 56 | tmp_bc = b - c; tmp_bd = b - d; 57 | tmp_cd = c - d; 58 | // 59 | b_more_a = tmp_ab[cSTATE_W-1]; 60 | c_more_a = tmp_ac[cSTATE_W-1]; 61 | d_more_a = tmp_ad[cSTATE_W-1]; 62 | c_more_b = tmp_bc[cSTATE_W-1]; 63 | d_more_b = tmp_bd[cSTATE_W-1]; 64 | d_more_c = tmp_cd[cSTATE_W-1]; 65 | // 66 | tmpH = b_more_a ? b : a; 67 | tmpL = d_more_c ? d : c; 68 | 69 | case ({b_more_a, d_more_c}) 70 | 2'b00 : st_m_p_mmax = c_more_a ? tmpL : tmpH; 71 | 2'b01 : st_m_p_mmax = d_more_a ? tmpL : tmpH; 72 | 2'b10 : st_m_p_mmax = c_more_b ? tmpL : tmpH; 73 | default : st_m_p_mmax = d_more_b ? tmpL : tmpH; 74 | endcase 75 | end 76 | endfunction 77 | 78 | // 79 | // parallel max selector 80 | function trel_state_t st_p_mmax (input trel_state_t a, b, c, d); 81 | bit a_more_b, a_more_c, a_more_d; 82 | bit b_more_c, b_more_d; 83 | bit c_more_d; 84 | bit [1 : 0] sel; 85 | begin 86 | a_more_b = (a > b); a_more_c = (a > c); a_more_d = (a > d); 87 | b_more_c = (b > c); b_more_d = (b > d); 88 | c_more_d = (c > d); 89 | // 90 | if (a_more_b) begin 91 | if (c_more_d) 92 | sel = a_more_c ? 2'b00 : 2'b10; 93 | else // d_more_c 94 | sel = a_more_d ? 2'b00 : 2'b11; 95 | end 96 | else begin // b_more_a 97 | if (c_more_d) 98 | sel = b_more_c ? 2'b01 : 2'b10; 99 | else // d_more_c 100 | sel = b_more_d ? 2'b01 : 2'b11; 101 | end 102 | // 103 | case (sel) 104 | 2'b00 : st_p_mmax = a; 105 | 2'b01 : st_p_mmax = b; 106 | 2'b10 : st_p_mmax = c; 107 | 2'b11 : st_p_mmax = d; 108 | default : st_p_mmax = a; 109 | endcase 110 | end 111 | endfunction 112 | 113 | -------------------------------------------------------------------------------- /rtl/rsc2/dec/rsc2_trellis.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : rsc2 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : rsc2_trellis.svh 5 | // Description : file with RSC2 trellis generate functions 6 | // 7 | 8 | //------------------------------------------------------------------------------------------------------ 9 | // define types and functions to get RSC2 trellis 10 | //------------------------------------------------------------------------------------------------------ 11 | 12 | typedef struct { 13 | bit [3 : 0] nextStates [16][4]; 14 | bit [3 : 0] preStates [16][4]; 15 | bit [1 : 0] outputs [16][4]; 16 | bit outputsy [16][4]; 17 | bit outputsw [16][4]; 18 | } trellis_t; 19 | 20 | trellis_t trel; 21 | 22 | always_comb begin 23 | trel = get_rsc2_trellis (0); 24 | end 25 | 26 | //------------------------------------------------------------------------------------------------------ 27 | // function's to get RSC2 trellis 28 | //------------------------------------------------------------------------------------------------------ 29 | 30 | function trellis_t get_rsc2_trellis (input int tmp); 31 | trellis_t trel; 32 | bit [3 : 0] nstate; 33 | bit y, w; 34 | begin 35 | for (int ab = 0; ab < 4; ab++) begin 36 | for (int state = 0; state < 16; state++) begin 37 | nstate = {ab[1] ^ state[0] ^ state[1], state[3:1]}; // feedback poly [1 0 0 1 1] 38 | nstate = nstate ^ {ab[0], ab[0], 1'b0, ab[0]}; 39 | 40 | y = nstate[3] ^ state[3] ^ state[2] ^ state[0]; // poly [1 1 1 0 1] 41 | w = nstate[3] ^ state[2] ^ state[1] ^ state[0]; // poly [1 0 1 1 1] 42 | // 43 | trel.nextStates[state][ab] = nstate; 44 | trel.outputsy [state][ab] = y; 45 | trel.outputsw [state][ab] = w; 46 | trel.outputs [state][ab] = {y, w}; 47 | end 48 | end 49 | // 50 | for (int ab = 0; ab < 4; ab++) begin 51 | for (int state = 0; state < 16; state++) begin 52 | nstate = trel.nextStates[state][ab]; 53 | trel.preStates[nstate][ab] = state[3 : 0]; 54 | end 55 | end 56 | // 57 | get_rsc2_trellis = trel; 58 | end 59 | endfunction 60 | 61 | -------------------------------------------------------------------------------- /rtl/rsc2/rsc2_constants.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : rsc 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : rsc2_constants.svh 5 | // Description : DVB RSC2 constants and constant types 6 | // 7 | 8 | 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] 9 | 10 | typedef logic [5 : 0] ptype_t; // permutation type [0: 33] - reordered Table A-1/2/4/5 11 | 12 | typedef logic [12 : 0] dbits_num_t; // number of data duobits/byte size [32:4096]/[8:1024] 13 | 14 | typedef struct packed { 15 | code_t code; // coderate [0 : 7] - [1/3; 1/2; 2/3; 3/4; 4/5; 5/6; 6/7; 7/8] 16 | ptype_t ptype; // permutation type [0: 33] - reordered Table A-1/2/4/5 17 | } code_ctx_t; 18 | 19 | -------------------------------------------------------------------------------- /rtl/rsc2/rsc2_dvb_ptable.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : rsc2 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : rsc2_dvb_ptable.svh 5 | // Description : file with RSC2 reordered permutation tables A-1/2/4/5 6 | // 7 | 8 | localparam int cDVB_PTABLE_SIZE = 34; 9 | 10 | typedef int tab_t [6]; // {P, Q0, Q1, Q2, Q3, N} 11 | typedef tab_t tab_dvb_t [cDVB_PTABLE_SIZE]; 12 | 13 | // {P, Q0, Q1, Q2, Q3, N} 14 | localparam tab_dvb_t cDVB_PTABLE = '{ 15 | '{ 9, 2, 2, 8, 0, 14 * 4 } , // 0 16 | '{ 17, 9, 5, 14, 1, 38 * 4 } , // 1 17 | '{ 23, 10, 5, 0, 0, 51 * 4 } , // 2 18 | '{ 23, 6, 10, 4, 0, 55 * 4 } , // 3 19 | '{ 23, 10, 2, 11, 1, 59 * 4 } , // 4 20 | '{ 23, 6, 8, 1, 1, 62 * 4 } , // 5 21 | '{ 25, 1, 1, 2, 0, 69 * 4 } , // 6 22 | '{ 23, 8, 1, 4, 1, 84 * 4 } , // 7 23 | '{ 23, 6, 13, 10, 0, 85 * 4 } , // 8 24 | '{ 25, 1, 7, 2, 1, 93 * 4 } , // 9 25 | '{ 25, 1, 2, 0, 1, 96 * 4 } , // 10 26 | '{ 23, 10, 8, 2, 1, 100 * 4 } , // 11 27 | '{ 29, 1, 4, 1, 1, 108 * 4 } , // 12 28 | '{ 29, 6, 5, 0, 0, 115 * 4 } , // 13 29 | '{ 31, 0, 3, 1, 0, 123 * 4 } , // 14 30 | '{ 31, 1, 1, 2, 1, 128 * 4 } , // 15 31 | '{ 31, 0, 1, 2, 0, 130 * 4 } , // 16 32 | '{ 31, 0, 0, 0, 0, 144 * 4 } , // 17 33 | '{ 33, 9, 15, 3, 1, 170 * 4 } , // 18 34 | '{ 37, 0, 2, 0, 2, 175 * 4 } , // 19 35 | '{ 37, 1, 3, 4, 2, 188 * 4 } , // 20 36 | '{ 37, 6, 1, 15, 0, 192 * 4 } , // 21 37 | '{ 39, 7, 0, 0, 0, 194 * 4 } , // 22 38 | '{ 45, 1, 1, 4, 0, 256 * 4 } , // 23 39 | '{ 43, 0, 0, 6, 2, 264 * 4 } , // 24 40 | '{ 49, 0, 3, 5, 0, 298 * 4 } , // 25 41 | '{ 49, 0, 6, 0, 1, 307 * 4 } , // 26 42 | '{ 49, 0, 5, 0, 5, 333 * 4 } , // 27 43 | '{ 53, 1, 4, 6, 2, 355 * 4 } , // 28 44 | '{ 53, 1, 10, 7, 1, 400 * 4 } , // 29 45 | '{ 59, 1, 1, 2, 1, 438 * 4 } , // 30 46 | '{ 59, 3, 8, 5, 1, 444 * 4 } , // 31 47 | '{ 65, 0, 3, 7, 0, 539 * 4 } , // 32 48 | '{ 81, 1, 2, 5, 2, 599 * 4 } // 33 49 | }; 50 | -------------------------------------------------------------------------------- /rtl/rsc2/rsc2_ntable.sv: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | 5 | parameter pW = 13 ; 6 | 7 | 8 | 9 | logic [5 : 0] rsc2_ntable__iptype ; 10 | logic [pW-1 : 0] rsc2_ntable__oN ; 11 | logic [pW-1 : 0] rsc2_ntable__oNm1 ; 12 | 13 | 14 | 15 | 16 | rsc2_ntable 17 | #( 18 | .pW ( pW ) 19 | ) 20 | rsc2_ntable 21 | ( 22 | .iptype ( rsc2_ntable__iptype ) , 23 | .oN ( rsc2_ntable__oN ) , 24 | .oNm1 ( rsc2_ntable__oNm1 ) 25 | ); 26 | 27 | 28 | assign rsc2_ntable__iptype = '0 ; 29 | 30 | 31 | 32 | */ 33 | 34 | // 35 | // Project : rsc2 36 | // Author : Shekhalev Denis (des00) 37 | // Workfile : rsc2_ntable.sv 38 | // Description : Packet length in duobits parameters table. 39 | // 40 | 41 | module rsc2_ntable 42 | #( 43 | parameter pW = 13 // fixed, don't change 44 | ) 45 | ( 46 | iptype , 47 | // 48 | oN , 49 | oNm1 50 | ); 51 | 52 | //------------------------------------------------------------------------------------------------------ 53 | // 54 | //------------------------------------------------------------------------------------------------------ 55 | 56 | input logic [5 : 0] iptype ; // permutation type [ 0: 33] - reordered Table A-1/2/4/5 57 | // 58 | output logic [pW-1 : 0] oN ; // used data pair size 59 | output logic [pW-1 : 0] oNm1 ; 60 | 61 | //------------------------------------------------------------------------------------------------------ 62 | // 63 | //------------------------------------------------------------------------------------------------------ 64 | 65 | `include "rsc2_dvb_ptable.svh" 66 | 67 | typedef int used_tab_t [2]; // {N, Nm1} 68 | typedef used_tab_t used_tab_dvb_t [cDVB_PTABLE_SIZE]; 69 | 70 | localparam used_tab_dvb_t cUSED_DVB_NTABLE = get_dvb_ntable(0); 71 | 72 | //------------------------------------------------------------------------------------------------------ 73 | // 74 | //------------------------------------------------------------------------------------------------------ 75 | 76 | function used_tab_dvb_t get_dvb_ntable (input int pipa); 77 | for (int i = 0; i < cDVB_PTABLE_SIZE; i++) begin 78 | get_dvb_ntable[i][0] = cDVB_PTABLE[i][5]; 79 | get_dvb_ntable[i][1] = cDVB_PTABLE[i][5] - 1; 80 | end 81 | endfunction 82 | 83 | //------------------------------------------------------------------------------------------------------ 84 | // length decoding 85 | //------------------------------------------------------------------------------------------------------ 86 | 87 | assign oN = cUSED_DVB_NTABLE[iptype][0][pW-1 : 0]; 88 | assign oNm1 = cUSED_DVB_NTABLE[iptype][1][pW-1 : 0]; 89 | 90 | endmodule 91 | -------------------------------------------------------------------------------- /rtl/rsc2/rsc2_sctable.sv: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | logic rsc2_sctable__iclk ; 5 | logic rsc2_sctable__ireset ; 6 | logic rsc2_sctable__iclkena ; 7 | logic [3 : 0] rsc2_sctable__iNmod15 ; 8 | logic [3 : 0] rsc2_sctable__istate ; 9 | logic [3 : 0] rsc2_sctable__ostate ; 10 | logic [3 : 0] rsc2_sctable__ostate_r ; 11 | 12 | 13 | 14 | rsc2_sctable 15 | rsc2_sctable 16 | ( 17 | .iclk ( rsc2_sctable__iclk ) , 18 | .ireset ( rsc2_sctable__ireset ) , 19 | .iclkena ( rsc2_sctable__iclkena ) , 20 | .iNmod15 ( rsc2_sctable__iNmod15 ) , 21 | .istate ( rsc2_sctable__istate ) , 22 | .ostate ( rsc2_sctable__ostate ) , 23 | .ostate_r ( rsc2_sctable__ostate_r ) 24 | ); 25 | 26 | 27 | assign rsc2_sctable__iclk = '0 ; 28 | assign rsc2_sctable__ireset = '0 ; 29 | assign rsc2_sctable__iclkena = '0 ; 30 | assign rsc2_sctable__iNmod15 = '0 ; 31 | assign rsc2_sctable__istate = '0 ; 32 | 33 | 34 | 35 | */ 36 | 37 | // 38 | // Project : rsc2 39 | // Author : Shekhalev Denis (des00) 40 | // Workfile : rsc2_sctable.sv 41 | // Description : Circullar state correspondence table. Its static table for different packet lengths 42 | // Module can use asynchronus or register output for correspondence state 43 | // 44 | 45 | module rsc2_sctable 46 | ( 47 | iclk , 48 | ireset , 49 | iclkena , 50 | iNmod15 , 51 | istate , 52 | ostate , 53 | ostate_r 54 | ); 55 | 56 | //------------------------------------------------------------------------------------------------------ 57 | // 58 | //------------------------------------------------------------------------------------------------------ 59 | 60 | input logic iclk ; 61 | input logic ireset ; 62 | input logic iclkena ; 63 | input logic [3 : 0] iNmod15 ; 64 | input logic [3 : 0] istate ; 65 | output logic [3 : 0] ostate ; 66 | output logic [3 : 0] ostate_r ; 67 | 68 | //------------------------------------------------------------------------------------------------------ 69 | // 70 | //------------------------------------------------------------------------------------------------------ 71 | 72 | typedef bit [3 : 0] lut_line_t [0 : 15]; 73 | typedef lut_line_t lut_t [0 : 15]; 74 | 75 | localparam lut_t cLUT = '{ 76 | '{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} , // 0 77 | '{0, 14, 3, 13, 7, 9, 4, 10, 15, 1, 12, 2, 8, 6, 11, 5} , // 1 78 | '{0, 11, 13, 6, 10, 1, 7, 12, 5, 14, 8, 3, 15, 4, 2, 9} , // 2 79 | '{0, 8, 9, 1, 2, 10, 11, 3, 4, 12, 13, 5, 6, 14, 15, 7} , // 3 80 | '{0, 3, 4, 7, 8, 11, 12, 15, 1, 2, 5, 6, 9, 10, 13, 14} , // 4 81 | '{0, 12, 5, 9, 11, 7, 14, 2, 6, 10, 3, 15, 13, 1, 8, 4} , // 5 82 | '{0, 4, 12, 8, 9, 13, 5, 1, 2, 6, 14, 10, 11, 15, 7, 3} , // 6 83 | '{0, 6, 10, 12, 5, 3, 15, 9, 11, 13, 1, 7, 14, 8, 4, 2} , // 7 84 | '{0, 7, 8, 15, 1, 6, 9, 14, 3, 4, 11, 12, 2, 5, 10, 13} , // 8 85 | '{0, 5, 14, 11, 13, 8, 3, 6, 10, 15, 4, 1, 7, 2, 9, 12} , // 9 86 | '{0, 13, 7, 10, 15, 2, 8, 5, 14, 3, 9, 4, 1, 12, 6, 11} , // 10 87 | '{0, 2, 6, 4, 12, 14, 10, 8, 9, 11, 15, 13, 5, 7, 3, 1} , // 11 88 | '{0, 9, 11, 2, 6, 15, 13, 4, 12, 5, 7, 14, 10, 3, 1, 8} , // 12 89 | '{0, 10, 15, 5, 14, 4, 1, 11, 13, 7, 2, 8, 3, 9, 12, 6} , // 13 90 | '{0, 15, 1, 14, 3, 12, 2, 13, 7, 8, 6, 9, 4, 11, 5, 10} , // 14 91 | '{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} // 15 92 | }; 93 | 94 | //------------------------------------------------------------------------------------------------------ 95 | // 96 | //------------------------------------------------------------------------------------------------------ 97 | 98 | assign ostate = cLUT[iNmod15][istate]; 99 | 100 | always_ff @(posedge iclk) begin 101 | if (iclkena) begin 102 | ostate_r <= ostate; 103 | end 104 | end 105 | 106 | //------------------------------------------------------------------------------------------------------ 107 | // 108 | //------------------------------------------------------------------------------------------------------ 109 | 110 | endmodule 111 | -------------------------------------------------------------------------------- /rtl/super_fec/README.md: -------------------------------------------------------------------------------- 1 | ITU-T G.975.1 (Super FEC) some codes realization 2 | 3 | I.3 Concatenated BCH super FEC codes 4 | 5 | vivado 2020.2 Kintex 7 - 2 6 | 7 | Encoder: 8 | 9 | LUT/REG/BRAM ~2k/~2.5k/7.5 > 250MHz ( > 32Gbps) 10 | 11 | Decoder, 3 iterations, endpoint mode: 12 | 13 | LUT/REG/BRAM ~113k/~97k/73.5 > 156.25MHz (with fanout optimization) ( > 20Gbps) 14 | 15 | Attention: The coder and decoder correspond each other but can have different bit order with standard codes. 16 | -------------------------------------------------------------------------------- /rtl/super_fec/i3/super_i3_bch_inner_types.svh: -------------------------------------------------------------------------------- 1 | 2 | //------------------------------------------------------------------------------------------------------ 3 | // GF 4 | //------------------------------------------------------------------------------------------------------ 5 | 6 | localparam int cM = 11; // GF(2^11) 7 | localparam int cIRRPOL = 2053; // D^11+D^2+1'1 8 | 9 | //------------------------------------------------------------------------------------------------------ 10 | // BCH 11 | //------------------------------------------------------------------------------------------------------ 12 | 13 | localparam int cT = 10; 14 | localparam int cT2 = 2*cT; 15 | localparam int cD = cT2 + 1; 16 | 17 | localparam int cK = 1930 ; 18 | localparam int cN = 2040 ; 19 | localparam int cK_MAX = 2**cM - 1 - (cN - cK) ; 20 | 21 | //------------------------------------------------------------------------------------------------------ 22 | // data bitwidrh per engine 23 | //------------------------------------------------------------------------------------------------------ 24 | 25 | localparam int cDAT_W = 8; 26 | localparam int cDEC_NUM = 16; 27 | 28 | //------------------------------------------------------------------------------------------------------ 29 | // 30 | //------------------------------------------------------------------------------------------------------ 31 | 32 | localparam int cEOP_EDGE = 1930/8 + 1; // 241.25 words 33 | localparam int cEOF_EDGE = 2040/8; // 255 words (+110 pbits = 13.75 words) 34 | 35 | localparam int cFRAME_SIZE = 255; // == cEOF_EDGE 36 | 37 | localparam int cRAM_ADDR_W = 8; // for full frame 38 | localparam int cRAM_DAT_W = 128; 39 | 40 | //------------------------------------------------------------------------------------------------------ 41 | // types 42 | //------------------------------------------------------------------------------------------------------ 43 | 44 | typedef logic [cM-1 : 0] gf_dat_t; 45 | typedef logic [cDAT_W-1 : 0] dat_t; 46 | typedef logic [cRAM_ADDR_W-1 : 0] ram_addr_t; 47 | typedef logic [cRAM_DAT_W-1 : 0] ram_dat_t; 48 | -------------------------------------------------------------------------------- /rtl/super_fec/i3/super_i3_bch_outer_types.svh: -------------------------------------------------------------------------------- 1 | 2 | //------------------------------------------------------------------------------------------------------ 3 | // GF 4 | //------------------------------------------------------------------------------------------------------ 5 | 6 | localparam int cM = 12; // GF(2^12) 7 | localparam int cIRRPOL = 6465; // D^12+D^11+D^8+D^6+1 8 | 9 | //------------------------------------------------------------------------------------------------------ 10 | // BCH 11 | //------------------------------------------------------------------------------------------------------ 12 | 13 | localparam int cT = 3; 14 | localparam int cT2 = 2*cT; 15 | localparam int cD = cT2 + 1; 16 | 17 | localparam int cK = 3824 ; 18 | localparam int cN = 3860 ; 19 | localparam int cK_MAX = 2**cM - 1 - (cN - cK) ; 20 | 21 | //------------------------------------------------------------------------------------------------------ 22 | // data bitwidrh per engine 23 | //------------------------------------------------------------------------------------------------------ 24 | 25 | localparam int cDAT_W = 16; 26 | localparam int cDEC_NUM = 8; 27 | 28 | //------------------------------------------------------------------------------------------------------ 29 | // 30 | //------------------------------------------------------------------------------------------------------ 31 | 32 | localparam int cEOP_EDGE = 3824/16; // 239 words 33 | localparam int cEOF_EDGE = 3860/16 + 1; // 241.25 words (+36 pbits = 2.25 pbits) 34 | 35 | localparam int cFRAME_SIZE = 255; // 255 words for bypass inner check bits 36 | 37 | localparam int cRAM_ADDR_W = 8; // for full frame 38 | localparam int cRAM_DAT_W = 128; 39 | 40 | //------------------------------------------------------------------------------------------------------ 41 | // types 42 | //------------------------------------------------------------------------------------------------------ 43 | 44 | typedef logic [cM-1 : 0] gf_dat_t; 45 | typedef logic [cDAT_W-1 : 0] dat_t; 46 | typedef logic [cRAM_ADDR_W-1 : 0] ram_addr_t; 47 | typedef logic [cRAM_DAT_W-1 : 0] ram_dat_t; 48 | -------------------------------------------------------------------------------- /rtl/viterbi/README.md: -------------------------------------------------------------------------------- 1 | Static configuration convolution encoder and Viterbi decoder for 1/N non recursive codes 2 | 3 | vivado 2019.1 Artix 7 - 2 Code (171, 131) Constraint Length = 7 4 | 5 | Encoder : LUT/REG 21/22 >250MHz (250Mbps -> 500Mbps) 6 | 7 | Decoder : LUT/REG/RAMB 3k/1.5k/1.5 ~200MHz (400Mbps -> 200Mbps) 8 | 9 | Single configuration convolution envoder and Viterbi decoder for 3/4 code from TCM_4D_8PSK 10 | 11 | vivado 2019.1 Artix 7 - 2 Constraint Length = 7 12 | 13 | Encoder : LUT/REG 5/17 >250MHz (750Mbps -> 1Gbps) 14 | 15 | Decoder : LUT/REG/RAMB 17k/3k/3.5 ~100MHz (400Mbps -> 300Mbps) 16 | 17 | Viterbi decoders use module arithmetic for state registers and ram based traceback 18 | 19 | -------------------------------------------------------------------------------- /rtl/viterbi/vit_1byN/vit_dec_types.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : viterbi 1byN 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : vit_dec_types.svh 5 | // Description : viterbi codec parameters and types 6 | // 7 | 8 | //------------------------------------------------------------------------------------------------------ 9 | // used parameters 10 | //------------------------------------------------------------------------------------------------------ 11 | 12 | parameter int pTAG_W = 4; 13 | parameter int pERR_CNT_W = 16; // error counter width 14 | 15 | // traceback parameters 16 | parameter int pTRB_LENGTH = 5*pCONSTR_LENGTH; 17 | 18 | localparam int cTRB_RAM_ADDR_W = $clog2(pTRB_LENGTH) + 2; // 4D buffer 19 | localparam int cTRB_LIFO_ADDR_W = $clog2(pTRB_LENGTH); 20 | 21 | // LLR metric for each bit. pLLR_W == 1 - hard decision (search path with minimum hamming metric) else soft decision (search path with maximum LLR metric) 22 | parameter int pLLR_W = 4; 23 | 24 | localparam bit cHD_MODE = (pLLR_W == 1); 25 | 26 | // trellis branch metric bitwidth and number 27 | localparam int cBM_W = pLLR_W + $clog2(pCODE_GEN_NUM); 28 | localparam int cBM_NUM = 2**pCODE_GEN_NUM; 29 | 30 | // trellis state path metric (search minumum, metric is positive) 31 | localparam int cSTATEM_W = cBM_W + 1 + 2; // 2*BM + 2 bits for module arithmetic (!!!) 32 | 33 | //------------------------------------------------------------------------------------------------------ 34 | // used types 35 | //------------------------------------------------------------------------------------------------------ 36 | 37 | typedef logic [pTAG_W-1 : 0] tag_t ; 38 | typedef logic [pERR_CNT_W-1 : 0] errcnt_t; 39 | 40 | typedef logic signed [pLLR_W-1 : 0] llr_t; 41 | 42 | // trellis metrics 43 | typedef logic [cBM_W-1 : 0] trel_ubm_t ; 44 | typedef logic signed [cBM_W-1 : 0] trel_bm_t ; 45 | typedef logic signed [cSTATEM_W-1 : 0] trel_statem_t ; 46 | typedef logic trel_decision_t ; 47 | 48 | // trellis array metrics 49 | typedef trel_bm_t bm_t [cBM_NUM]; 50 | typedef trel_statem_t statem_t [cSTATE_NUM]; 51 | typedef logic [cSTATE_NUM-1 : 0] decision_t ; 52 | 53 | typedef struct packed { 54 | logic [1 : 0] bidx; // use 4D architecture 55 | logic [cTRB_RAM_ADDR_W-3 : 0] addr; // 56 | } trb_ram_addr_t; 57 | 58 | typedef logic [cTRB_LIFO_ADDR_W-1 : 0] trb_lifo_addr_t; 59 | 60 | //------------------------------------------------------------------------------------------------------ 61 | // function for decision at module arithmetic 62 | //------------------------------------------------------------------------------------------------------ 63 | 64 | function logic statem_a_decision (input trel_statem_t a, b, input bit minmode = 0); 65 | trel_statem_t tmp; 66 | begin 67 | tmp = a - b; 68 | statem_a_decision = minmode ? tmp[cSTATEM_W-1] : !tmp[cSTATEM_W-1]; 69 | end 70 | endfunction 71 | -------------------------------------------------------------------------------- /rtl/viterbi/vit_3by4/vit_3by4_dec_types.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : viterbi 3by4 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : vit_dec_types.svh 5 | // Description : viterbi codec parameters and types 6 | // 7 | 8 | //------------------------------------------------------------------------------------------------------ 9 | // used parameters 10 | //------------------------------------------------------------------------------------------------------ 11 | 12 | parameter int pTAG_W = 4; 13 | parameter int pERR_CNT_W = 16; // error counter width 14 | 15 | // traceback parameters 16 | parameter int pTRB_LENGTH = 64; 17 | 18 | localparam int cTRB_RAM_ADDR_W = $clog2(pTRB_LENGTH) + 2; // 4D buffer 19 | localparam int cTRB_LIFO_ADDR_W = $clog2(pTRB_LENGTH); 20 | 21 | // LLR metric for each bit 22 | parameter int pLLR_W = 4; 23 | 24 | // trellis branch metric == sum of 4 metric, 16 metric in all 25 | localparam int cBM_W = pLLR_W + 2; 26 | localparam int cBM_NUM = 16; 27 | 28 | // trellis state path metric (search minumum, metric is positive) 29 | localparam int cSTATEM_W = cBM_W + 1 + 2; // 2*BM + 2 bits for module arithmetic (!!!) 30 | 31 | //------------------------------------------------------------------------------------------------------ 32 | // used types 33 | //------------------------------------------------------------------------------------------------------ 34 | 35 | typedef logic [pTAG_W-1 : 0] tag_t ; 36 | typedef logic [pERR_CNT_W-1 : 0] errcnt_t; 37 | 38 | typedef logic signed [pLLR_W-1 : 0] llr_t; 39 | 40 | // trellis metrics 41 | typedef logic signed [cBM_W-1 : 0] trel_bm_t ; 42 | typedef logic signed [cSTATEM_W-1 : 0] trel_statem_t ; 43 | typedef logic [2 : 0] trel_decision_t ; 44 | 45 | // trellis array metrics 46 | typedef trel_bm_t bm_t [cBM_NUM]; 47 | typedef trel_statem_t statem_t [cSTATE_NUM]; 48 | typedef trel_decision_t decision_t [cSTATE_NUM]; 49 | 50 | typedef struct packed { 51 | logic [1 : 0] bidx; // use 4D architecture 52 | logic [cTRB_RAM_ADDR_W-3 : 0] addr; // 53 | } trb_ram_addr_t; 54 | 55 | typedef logic [cTRB_LIFO_ADDR_W-1 : 0] trb_lifo_addr_t; 56 | 57 | //------------------------------------------------------------------------------------------------------ 58 | // function for decision at module arithmetic 59 | //------------------------------------------------------------------------------------------------------ 60 | 61 | function logic statem_a_max (input trel_statem_t a, b); 62 | trel_statem_t tmp; 63 | begin 64 | tmp = a - b; 65 | statem_a_max = !tmp[cSTATEM_W-1]; 66 | end 67 | endfunction 68 | -------------------------------------------------------------------------------- /rtl/viterbi/vit_3by4/vit_3by4_enc.sv: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | parameter int pTAG_W = 4 ; 5 | 6 | 7 | 8 | logic vit_enc__iclk ; 9 | logic vit_enc__ireset ; 10 | logic vit_enc__iclkena ; 11 | logic vit_enc__isop ; 12 | logic vit_enc__ival ; 13 | logic vit_enc__ieop ; 14 | logic [pTAG_W-1 : 0] vit_enc__itag ; 15 | logic [3 : 1] vit_enc__idat ; 16 | logic vit_enc__osop ; 17 | logic vit_enc__oval ; 18 | logic vit_enc__oeop ; 19 | logic [pTAG_W-1 : 0] vit_enc__otag ; 20 | logic [3 : 0] vit_enc__odat ; 21 | 22 | 23 | 24 | vit_3by4_enc 25 | #( 26 | .pTAG_W ( pTAG_W ) 27 | ) 28 | vit_enc 29 | ( 30 | .iclk ( vit_enc__iclk ) , 31 | .ireset ( vit_enc__ireset ) , 32 | .iclkena ( vit_enc__iclkena ) , 33 | .isop ( vit_enc__isop ) , 34 | .ival ( vit_enc__ival ) , 35 | .ieop ( vit_enc__ieop ) , 36 | .itag ( vit_enc__itag ) , 37 | .idat ( vit_enc__idat ) , 38 | .osop ( vit_enc__osop ) , 39 | .oval ( vit_enc__oval ) , 40 | .oeop ( vit_enc__oeop ) , 41 | .otag ( vit_enc__otag ) , 42 | .odat ( vit_enc__odat ) 43 | ); 44 | 45 | 46 | assign vit_enc__iclk = '0 ; 47 | assign vit_enc__ireset = '0 ; 48 | assign vit_enc__iclkena = '0 ; 49 | assign vit_enc__isop = '0 ; 50 | assign vit_enc__ival = '0 ; 51 | assign vit_enc__ieop = '0 ; 52 | assign vit_enc__itag = '0 ; 53 | assign vit_enc__idat = '0 ; 54 | 55 | 56 | 57 | */ 58 | 59 | // 60 | // Project : viterbi 3by4 61 | // Author : Shekhalev Denis (des00) 62 | // Workfile : vit_3by4_enc.sv 63 | // Description : 64 | // 65 | 66 | module vit_3by4_enc 67 | ( 68 | iclk , 69 | ireset , 70 | iclkena , 71 | // 72 | isop , 73 | ival , 74 | ieop , 75 | itag , 76 | idat , 77 | // 78 | osop , 79 | oval , 80 | oeop , 81 | otag , 82 | odat 83 | ); 84 | 85 | `include "vit_3by4_trellis.svh" 86 | 87 | parameter int pTAG_W = 4; 88 | 89 | //------------------------------------------------------------------------------------------------------ 90 | // 91 | //------------------------------------------------------------------------------------------------------ 92 | 93 | input logic iclk ; 94 | input logic ireset ; 95 | input logic iclkena ; 96 | // 97 | input logic isop ; 98 | input logic ival ; 99 | input logic ieop ; 100 | input logic [pTAG_W-1 : 0] itag ; 101 | input logic [3 : 1] idat ; 102 | // 103 | output logic osop ; 104 | output logic oval ; 105 | output logic oeop ; 106 | output logic [pTAG_W-1 : 0] otag ; 107 | output logic [3 : 0] odat ; 108 | 109 | //------------------------------------------------------------------------------------------------------ 110 | // 111 | //------------------------------------------------------------------------------------------------------ 112 | 113 | stateb_t state; 114 | 115 | //------------------------------------------------------------------------------------------------------ 116 | // do coding througth trellis. it's more universal 117 | //------------------------------------------------------------------------------------------------------ 118 | 119 | always_ff @(posedge iclk or posedge ireset) begin 120 | if (ireset) begin 121 | oval <= 1'b0; 122 | state <= '0; 123 | end 124 | else if (iclkena) begin 125 | oval <= ival; 126 | if (ival) begin 127 | state <= isop ? trel.nextStates[0][idat] : trel.nextStates[state][idat]; 128 | end 129 | end 130 | end 131 | 132 | always_ff @(posedge iclk) begin 133 | if (iclkena) begin 134 | if (ival) begin 135 | osop <= isop; 136 | oeop <= ieop; 137 | if (isop) begin 138 | otag <= itag; 139 | end 140 | odat <= isop ? {idat, 1'b0} : {idat, state[0]}; 141 | end 142 | end 143 | end 144 | 145 | endmodule 146 | -------------------------------------------------------------------------------- /rtl/viterbi/vit_3by4/vit_3by4_trellis.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : viterbi 3by4 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : vit_dec_types.svh 5 | // Description : viterbi codec trellis defines and used functions 6 | // 7 | 8 | //------------------------------------------------------------------------------------------------------ 9 | // trellis base parameters 10 | //------------------------------------------------------------------------------------------------------ 11 | 12 | localparam int pCONSTR_LENGTH = 7; 13 | 14 | //------------------------------------------------------------------------------------------------------ 15 | // trellis constants 16 | //------------------------------------------------------------------------------------------------------ 17 | 18 | localparam int cSTATE_NUM = 2**(pCONSTR_LENGTH-1); 19 | localparam int cSTATE_W = pCONSTR_LENGTH-1; 20 | 21 | // code state 22 | typedef bit [cSTATE_W-1 : 0] stateb_t; 23 | typedef bit [3 : 0] boutputs_t; 24 | 25 | typedef struct { 26 | stateb_t nextStates [cSTATE_NUM][8]; 27 | stateb_t preStates [cSTATE_NUM][8]; 28 | boutputs_t outputs [cSTATE_NUM][8]; 29 | } trellis_t; 30 | 31 | trellis_t trel; 32 | 33 | always_comb begin 34 | trel = get_trellis (0); 35 | end 36 | 37 | //------------------------------------------------------------------------------------------------------ 38 | // function's to get trellis 39 | //------------------------------------------------------------------------------------------------------ 40 | 41 | function trellis_t get_trellis (input int tmp); 42 | stateb_t nstate; 43 | begin 44 | for (int x3x2x1 = 0; x3x2x1 < 8; x3x2x1++) begin 45 | for (int state = 0; state < cSTATE_NUM; state++) begin 46 | nstate = {state[0], state[cSTATE_W-1 : 2], state[1] ^ state[0]}; 47 | nstate ^= 6'b0_10100 & {6{x3x2x1[2]}}; 48 | nstate ^= 6'b0_01010 & {6{x3x2x1[1]}}; 49 | nstate ^= 6'b0_00011 & {6{x3x2x1[0]}}; 50 | // 51 | get_trellis.nextStates [state][x3x2x1] = nstate; 52 | get_trellis.outputs [state][x3x2x1] = {x3x2x1[2 : 0], state[0]}; 53 | end 54 | end 55 | // 56 | for (int x3x2x1 = 0; x3x2x1 < 8; x3x2x1++) begin 57 | for (int state = 0; state < cSTATE_NUM; state++) begin 58 | nstate = get_trellis.nextStates[state][x3x2x1]; 59 | get_trellis.preStates[nstate][x3x2x1] = state[cSTATE_W-1 : 0]; 60 | end 61 | end 62 | end 63 | endfunction 64 | /* 65 | //------------------------------------------------------------------------------------------------------ 66 | // function to get previous state from current state 67 | // previous state is shift rigth for this trellis 68 | //------------------------------------------------------------------------------------------------------ 69 | 70 | function automatic stateb_t get_pre_state(input stateb_t state, input logic decision); 71 | get_pre_state = {state[cSTATE_W-2 : 0], decision}; 72 | endfunction 73 | 74 | //------------------------------------------------------------------------------------------------------ 75 | // function to get input binary data 76 | // data bit is msb of state for this trellis 77 | //------------------------------------------------------------------------------------------------------ 78 | 79 | function automatic logic get_binput (input stateb_t state); 80 | get_binput = state[cSTATE_W-1]; 81 | endfunction 82 | */ 83 | -------------------------------------------------------------------------------- /rtl/viterbi/vit_trb_ram.sv: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | 5 | parameter int pDATA_W = 32 ; 6 | parameter int pADDR_W = 8 ; 7 | 8 | 9 | 10 | logic vit_trb_ram__iclk ; 11 | logic vit_trb_ram__ireset ; 12 | logic vit_trb_ram__iclkena ; 13 | logic vit_trb_ram__iwrite ; 14 | logic [pADDR_W-1 : 0] vit_trb_ram__iwaddr ; 15 | logic [pDATA_W-1 : 0] vit_trb_ram__iwdata ; 16 | logic [pADDR_W-1 : 0] vit_trb_ram__iraddr ; 17 | logic [pDATA_W-1 : 0] vit_trb_ram__ordata ; 18 | 19 | 20 | 21 | vit_trb_ram 22 | #( 23 | .pDATA_W ( pDATA_W ) , 24 | .pADDR_W ( pADDR_W ) 25 | ) 26 | vit_trb_ram 27 | ( 28 | .iclk ( vit_trb_ram__iclk ) , 29 | .ireset ( vit_trb_ram__ireset ) , 30 | .iclkena ( vit_trb_ram__iclkena ) , 31 | .iwrite ( vit_trb_ram__iwrite ) , 32 | .iwaddr ( vit_trb_ram__iwaddr ) , 33 | .iwdata ( vit_trb_ram__iwdata ) , 34 | .iraddr ( vit_trb_ram__iraddr ) , 35 | .ordata ( vit_trb_ram__ordata ) 36 | ); 37 | 38 | 39 | assign vit_trb_ram__iclk = '0 ; 40 | assign vit_trb_ram__ireset = '0 ; 41 | assign vit_trb_ram__iclkena = '0 ; 42 | assign vit_trb_ram__iwrite = '0 ; 43 | assign vit_trb_ram__iwaddr = '0 ; 44 | assign vit_trb_ram__iwdata = '0 ; 45 | assign vit_trb_ram__iraddr = '0 ; 46 | 47 | 48 | 49 | */ 50 | 51 | // 52 | // Project : viterbi 53 | // Author : Shekhalev Denis (des00) 54 | // Workfile : vit_trb_ram.sv 55 | // Description : Viterbi decoder ram for trellis state decisions (traceback). 56 | // No any xD buffer control inside 57 | // 58 | 59 | module vit_trb_ram 60 | #( 61 | parameter int pDATA_W = 32 , 62 | parameter int pADDR_W = 8 63 | ) 64 | ( 65 | iclk , 66 | ireset , 67 | iclkena , 68 | // 69 | iwrite , 70 | iwaddr , 71 | iwdata , 72 | // 73 | iraddr , 74 | ordata 75 | ); 76 | 77 | //------------------------------------------------------------------------------------------------------ 78 | // 79 | //------------------------------------------------------------------------------------------------------ 80 | 81 | input logic iclk ; 82 | input logic ireset ; 83 | input logic iclkena ; 84 | // 85 | input logic iwrite ; 86 | input logic [pADDR_W-1 : 0] iwaddr ; 87 | input logic [pDATA_W-1 : 0] iwdata ; 88 | // 89 | input logic [pADDR_W-1 : 0] iraddr ; 90 | output logic [pDATA_W-1 : 0] ordata ; 91 | 92 | //------------------------------------------------------------------------------------------------------ 93 | // 94 | //------------------------------------------------------------------------------------------------------ 95 | 96 | logic [pDATA_W-1 : 0] ram [2**pADDR_W] /*synthesis syn_ramstyle = "no_rw_check"*/; 97 | logic [pDATA_W-1 : 0] rdata; 98 | 99 | //------------------------------------------------------------------------------------------------------ 100 | // 101 | //------------------------------------------------------------------------------------------------------ 102 | 103 | always_ff @(posedge iclk) begin 104 | if (iclkena) begin 105 | if (iwrite) begin 106 | ram[iwaddr] <= iwdata; 107 | end 108 | rdata <= ram[iraddr]; 109 | ordata <= rdata; 110 | end 111 | end 112 | 113 | 114 | endmodule 115 | -------------------------------------------------------------------------------- /testbench/TCM_4D_8PSK/tcm_pkt_class.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : 4D-8PSK TCM 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : tcm_pkt_class.svh 5 | // Description : 4D-8PSK TCM codec data packet class 6 | // 7 | 8 | `include "pkt_class.svh" 9 | 10 | class tcm_pkt_class extends pkt_class #(11); 11 | 12 | bit [1 : 0] code; 13 | 14 | function new (int n, int code = 0); 15 | super.new(n); 16 | this.code = code; 17 | endfunction : new 18 | 19 | constraint data_range 20 | { 21 | if (code == 0) 22 | foreach ( dat[i] ) dat[i][10: 8] == 0; 23 | else if (code == 1) 24 | foreach ( dat[i] ) dat[i][10: 9] == 0; 25 | else if (code == 2) 26 | foreach ( dat[i] ) dat[i][10:10] == 0; 27 | } 28 | 29 | endclass 30 | 31 | -------------------------------------------------------------------------------- /testbench/viterbi/vit_1byN/vit_pkt_class.svh: -------------------------------------------------------------------------------- 1 | // 2 | // Project : viterbi 3 | // Author : Shekhalev Denis (des00) 4 | // Workfile : vit_pkt_class.svh 5 | // Description : viterbi 1byN codec data packet class 6 | // 7 | 8 | `include "pkt_class.svh" 9 | 10 | class vit_pkt_class extends pkt_class #(1); 11 | 12 | int term_bit_num; 13 | 14 | function new (int n, int term_bit_num = 0); 15 | super.new(n + term_bit_num); 16 | this.term_bit_num = term_bit_num; 17 | endfunction : new 18 | 19 | function void post_randomize (); 20 | // add termination bits if need 21 | for (int i = $size(dat) - term_bit_num; i < $size(dat); i++) begin 22 | dat[i] = 0; 23 | end 24 | endfunction 25 | 26 | function int do_compare (vit_pkt_class rdat); 27 | int err; 28 | begin 29 | assert (rdat.dat.size() == dat.size()) else begin 30 | $error("data array size compare mismatch"); 31 | return dat.size(); 32 | end 33 | err = 0; 34 | for (int i = 0; i < $size(dat) - term_bit_num; i++) begin 35 | err += (dat[i] != rdat.dat[i]); 36 | end 37 | return err; 38 | end 39 | endfunction 40 | 41 | endclass 42 | 43 | --------------------------------------------------------------------------------