当前位置:首页>python>[基于python实现PUSCH信道模拟] DMRS生成

[基于python实现PUSCH信道模拟] DMRS生成

  • 2026-10-11 08:37:02
[基于python实现PUSCH信道模拟] DMRS生成

终端通过PUSCH(物理上行共享信道)向基站发送数据时,信号在终端经过CRC、LDPC、信道编码、速率匹配、加扰、调制、映射等流程后,信号经过复杂的无线信道,基站侧接收到PUSCH数据后进行信道估计及相应的逆操作,还原出终端发射的原始数据。本系列基于Python实现PUSCH简化的信道处理过程,主要是为了学习信道估计过程中的算法知识。

DMRS

DMRS(解调参考信号)是一个发送端(终端)和接收端(基站)都已知的信号。终端在发送PUSCH数据的同时,会在特定的时频资源上插入DMRS信号。基站收到信号后,通过对比接收到的DMRS和它已知的原始DMRS,就能精确地估算出当前信道的状态。有了这个信道状态,基站就可以对PUSCH上的数据进行反向补偿,即相干解调,从而准确恢复出终端发送的信息。

关于PUSCH DMRS的相关定义详见协议38.211 6.4.1.1相关章节。

DMRS序列生成

如果PUSCH transform precoding disable,DMRS序列公式为:

这里是pseudo-random(伪随机)序列(即一个长度为的Gold序列),在38.211 5.2.1中定义。

Gold序列

[5GNR] 什么是Gold序列

Gold序列是由两个m序列组成,长度为31,协议中关于Gold sequence的定义:

Generic pseudo-random sequences are defined by a length-31 Gold sequence. The output sequence  of length , where , is defined by

where

  • N_c = 1600
  • and the first m-sequence  shall be initialized with .
  • The initialization of the second m-sequence  is denoted by 

初始化公式如下:

DMRS序列生成相关公式之间的关系

python实现DMRS序列生成

定义系统参数

SCS = 30e3# 子载波间隔 (Hz)NUMEROLOGY = 1N_FFT = 2048# FFT点数CP_LENGTH = 144# 循环前缀长度N_SYMBOLS_PER_SLOT = 14# 每个时隙OFDM符号数N_SUBCARRIERS = 100*12# 子载波总数 (100 RB)MODULATION = '16QAM'N_PUSCH_SYMBOL = 14# PUSCH调度symbol数

定义一个DMRS配置类

该DMRS配置类包含DMRS所有相关参数和处理函数

classDMRSConfig:"""DMRS配置类, 封装所有DMRS相关的参数和操作"""def__init__(self, dmrs_type, additionalDmrs, n_id, n_scid, n_s, nc, dmrs_type_a_position, ld):# DMRS参数        self.dmrs_type = dmrs_type        self.additionalDmrs = additionalDmrs        self.n_id = n_id        self.n_scid = n_scid        self.n_s = n_s        self.nc = nc        self.dmrs_type_a_position = dmrs_type_a_position  # 'pos2' or 'pos3'        self.ld = ld  # PUSCH调度长度 (0~14个符号)        self._validate_parameters()        self.dmrsPositions = self._get_dmrs_positions()def_validate_parameters(self):if self.ld < 0or self.ld > 14:raise ValueError("ld must be between 0 and 14")if self.additionalDmrs > 0and self.ld < 4:raise ValueError("Additional DMRS not supported when ld < 4")if self.dmrs_type_a_position notin ['pos2', 'pos3']:raise ValueError("dmrs_type_a_position must be 'pos2' or 'pos3'")if self.additionalDmrs < 0or self.additionalDmrs > 3:raise ValueError("additionalDmrs must be between 0 and 3")def_get_dmrs_positions(self):"""        根据Table 6.4.1.1.3-3确定DMRS符号位置        仅考虑mapping type A && single-symbol DMRS的情况        """        l0 = 2if self.dmrs_type_a_position == 'pos2'else3        dmrsPositions=[#dmrs-AdditionalPosition#       0              1              2              3            [[l0, 0, 0 ,0], [l0, 0, 0 ,0], [l0, 0, 0 ,0], [l0, 0, 0 ,0]],       #ld = 4            [[l0, 0, 0 ,0], [l0, 0, 0 ,0], [l0, 0, 0 ,0], [l0, 0, 0 ,0]],       #ld = 5            [[l0, 0, 0 ,0], [l0, 0, 0 ,0], [l0, 0, 0 ,0], [l0, 0, 0 ,0]],       #ld = 6            [[l0, 0, 0 ,0], [l0, 0, 0 ,0], [l0, 0, 0 ,0], [l0, 0, 0 ,0]],       #ld = 7            [[l0, 0, 0 ,0], [l0, 7, 0 ,0], [l0, 7, 0 ,0], [l0, 7, 0 ,0]],       #ld = 8            [[l0, 0, 0 ,0], [l0, 7, 0 ,0], [l0, 7, 0 ,0], [l0, 7, 0 ,0]],       #ld = 9            [[l0, 0, 0 ,0], [l0, 9, 0 ,0], [l0, 6, 9 ,0], [l0, 6, 9 ,0]],       #ld = 10            [[l0, 0, 0 ,0], [l0, 9, 0 ,0], [l0, 6, 9 ,0], [l0, 6, 9 ,0]],       #ld = 11            [[l0, 0, 0 ,0], [l0, 9, 0 ,0], [l0, 6, 9 ,0], [l0, 5, 8 ,11]],      #ld = 12            [[l0, 0, 0 ,0], [l0, 11, 0 ,0], [l0, 7, 11 ,0], [l0, 5, 8 ,11]],    #ld = 13            [[l0, 0, 0 ,0], [l0, 11, 0 ,0], [l0, 7, 11 ,0], [l0, 5, 8 ,11]]     #ld = 14        ]        tmp = dmrsPositions[self.ld - 4][self.additionalDmrs]return [num for num in tmp if num > 0]

Gold序列生成函数

在DMRS配置类中定义Gold序列生成函数

defgenerate_gold_sequence(self, c_init, length):"""生成Gold序列 (38.211 5.2.1)"""        x1 = np.zeros(31, dtype=int)        x1[0] = 1        x2 = np.zeros(31, dtype=int)for i in range(31):            x2[i] = (c_init >> i) & 1        c = np.zeros(length + self.nc, dtype=int)for n in range(length + self.nc):            c[n] = (x1[n % 31] + x2[n % 31]) % 2# 更新x1            x1_shift = (x1[3] + x1[0]) % 2            x1 = np.roll(x1, -1)            x1[-1] = x1_shift# 更新x2            x2_shift = (x2[3] + x2[2] + x2[1] + x2[0]) % 2            x2 = np.roll(x2, -1)            x2[-1] = x2_shiftreturn c[self.nc:self.nc+length]

关于gold序列的介绍可阅读什么是Gold序列 m序列及LFSR序列基本概念

DMRS序列生成函数

在DMRS配置类中定义DMRS序列生成函数,主要调用gold序列生成和调制。在5G中参考信号都是使用QPSK调制方式,协议规定每两个bit映射成一个复数调制符号,

该生成函数按DMRS symbol被调用,每次生成一个symbol的DMRS复数信号

defgenerate_dmrs_sequence(self, length, l):"""生成DMRS序列 (38.211 6.4.1.1.1)"""        c_init = (2**17 * (14 * self.n_s + l + 1) * (2 * self.n_id + 1) + 2 * self.n_id + self.n_scid) % (2**31)        gold_seq = self.generate_gold_sequence(c_init, 2 * length)        r = np.zeros(length, dtype=complex)for n in range(length):            r[n] = (1 - 2 * gold_seq[2*n]) / np.sqrt(2) + 1j * (1 - 2 * gold_seq[2*n + 1]) / np.sqrt(2)return r

DMRS序列生成主函数

该函数按DMRS symbol调用generate_dmrs_sequence() 生成该符号上的DMRS序列

defmain():# 创建DMRS配置    dmrs_config = DMRSConfig(        dmrs_type=1,        additional_dmrs=2,        n_id=1000,        n_scid=0,        n_s=0,        nc=1600,        dmrs_type_a_position='pos2',        ld=N_PUSCH_SYMBOL    )    print(f"DMRS positions: {dmrs_config.dmrs_positions}")# 生产DMRS    plt.figure("DMRS Sequence", constrained_layout=True)    i = 1for l in dmrs_config.dmrs_positions:        num_dmrs = (N_SUBCARRIERS // 12) * 6        dmrs_seq = dmrs_config.generate_dmrs_sequence(num_dmrs, l)        print(f'Dmrs Seq Generate sym {l} len { 2 * num_dmrs}: {dmrs_seq}')        plt.subplot(2, 2, i)        plt.scatter(np.real(np.array(dmrs_seq)), np.imag(np.array(dmrs_seq)), alpha=0.1)        plt.title(f'Symbol {l}')        plt.xlabel('I'); plt.ylabel('Q'); plt.grid(True); plt.axis('equal')        i = i + 1    plt.show()

最新文章

随机文章