CDMA-система
Моделирование CDMA-системы с QPSK-модуляцией
В современных системах беспроводной связи технология множественного доступа с кодовым разделением каналов CDMA (Code Division Multiple Access) остается фундаментальным методом обеспечения одновременной передачи данных для нескольких пользователей в общей частотной полосе. Ключевым аспектом проектирования таких систем является обеспечение ортогональности каналов и устойчивость к шумам, что требует тщательного моделирования на этапе разработки.
Ключевые принципы CDMA:
| Принцип | Описание |
|---|---|
| Расширение спектра | Каждый бит данных умножается на высокочастотную кодовую последовательность (chip sequence), что «расширяет» сигнал по частоте |
| Ортогональность кодов | Коды разных каналов выбираются так, чтобы их взаимная корреляция была близка к нулю (например, коды Уолша), что минимизирует интерференцию |
| Совместное использование частоты | Все пользователи работают на одной несущей частоте одновременно, различаясь только кодом |
| Связывание (Despreading) | На приёмной стороне сигнал умножается на тот же код, что восстанавливает исходные данные и подавляет сигналы других пользователей |
Преимущества CDMA:
- Устойчивость к узкополосным помехам и замираниям
- Возможность мягкого хандовера (soft handoff) в сотовых сетях
- Гибкое управление ёмкостью системы
- Повышенная безопасность передачи за счёт псевдослучайных кодов
Применение:
- Сотовые сети 2G/3G (IS-95, CDMA2000, WCDMA)
- Системы глобального позиционирования (GPS, ГЛОНАСС)
- Спутниковая связь
- Военные системы защищённой связи
В нашей модели CDMA реализована через комбинацию QPSK-модуляции, кодов Уолша (для разделения пилотного и пользовательского каналов) и PN-последовательностей (для дополнительного расширения спектра), что соответствует классической архитектуре систем с прямым расширением спектра (DSSS-CDMA).

Модель состоит из двух пользовательских подсистем (Pilot_Channel и User1_Traffic_Channel), которые формируют сигналы пилот-канала и пользовательского трафика. Сигналы подвергаются квадратурной фазовой манипуляции (QPSK), расширяются уникальными кодовыми последовательностями и суммируются перед передачей через шумовой канал. На стороне приемника производится обратная операция свертки и демодуляция для восстановления исходных данных.

Интеграция с Engee позволяет гибко управлять параметрами сигналов: кодовые последовательности, рассчитанные в скрипте, загружаются в модель через блоки Signal From Workspace, что обеспечивает высокую точность соответствия математического описания и симуляции.
Pkg.add("JLD2")
using JLD2, Statistics, DataFrames
Код ниже выполняет начальную загрузку и визуальную проверку данных для моделирования.
A = load("data.jld2", "A")
Size_A = length(A)
println("Size A: $(Size_A)")
plot(A[1:300])
Функция pn_gen(init_state::Vector{Int}, poly_exp::Vector{Int}, n::Int)
- Реализует генератор псевдослучайной последовательности (PN) на основе регистра сдвига с линейной обратной связью (LFSR).
- Принимает начальное состояние регистра, вектор показателей образующего полинома и требуемую длину выходной последовательности.
- Определяет длину регистра N и создает его копию для работы.
- Преобразует показатели полинома в позиции отводов (taps): если показатель равен 0 — добавляет отвод на последнюю позицию N, иначе — на позицию N-e.
- Выполняет генерацию последовательности заданной длины: на каждом шаге сохраняет последний бит регистра как выходной, вычисляет бит обратной связи как XOR всех отводов и выполняет сдвиг регистра вправо с помещением бита обратной связи в начало.
- Возвращает массив целых чисел 0 и 1 (совместимый с форматом MATLAB).
Функция pn_gen_walsh(init_state::Vector{Int}, poly_exp::Vector{Int}, n::Int)
- Вызывает
pn_genдля получения базовой бинарной последовательности. - Выполняет преобразование формата: каждый 0 заменяет на 1, каждую 1 заменяет на -1.
- Возвращает последовательность в формате +1/-1, готовую для использования в модуляции и умножении на коды Уолша.
Функция walsh_hadamard(n::Int, size::Int)
- Генерирует ортогональные коды Уолша-Адамара заданной длины.
- Начинает с базовой матрицы Адамара размером 4×4.
- Выполняет два итеративных расширения по правилу [H H; H -H], формируя матрицу 16×16.
- Извлекает строку с индексом n+1 (нумерация каналов с 0).
- Повторяет (повтор) полученную строку необходимое количество раз для достижения требуемой длины size.
- Возвращает последовательность из +1/-1, ортогональную другим строкам матрицы Адамара.
function pn_gen(init_state::Vector{Int}, poly_exp::Vector{Int}, n::Int)
N = length(init_state)
reg = copy(init_state)
taps = Int[]
for e in poly_exp
if e == 0
push!(taps, N)
elseif e != N
push!(taps, N - e)
end
end
outputs = Bool[]
for _ in 1:n
push!(outputs, reg[end] == 1)
fb = 0
for t in taps
fb = xor(fb, reg[t])
end
reg = [fb; reg[1:end-1]]
end
return Int.(outputs)
end
function pn_gen_walsh(init_state::Vector{Int}, poly_exp::Vector{Int}, n::Int)
raw = pn_gen(init_state, poly_exp, n)
return [x == 0 ? 1 : -1 for x in raw]
end
function walsh_hadamard(n::Int, size::Int)
H = [1 1 1 1; 1 -1 1 -1; 1 1 -1 -1; 1 -1 -1 1]
for i in 1:2
H = [H H; H -H]
end
code = H[n+1, :]
return repeat(code, inner=div(size, 16))
end
Ниже представлен код формирования PN-кодов.
PN-код генерируется отдельно для двух ветвей сигнала — синфазной (I) и квадратурной (Q). Для каждой ветви используется специальный генератор, формирующий последовательность случайных значений (+1 или −1), основанную на определенных параметрах регистра сдвига и полинома обратной связи.
Коды Уолша создаются для разделения каналов внутри системы. Пилотный канал получает код, состоящий из одних единиц, а первый пользовательский канал — чередующийся код. Эти коды позволяют разделить сигналы разных пользователей и помогают приемнику выделять нужный сигнал среди множества передающихся одновременно.
Для каждого канала формируется итоговый сигнал путем перемножения PN-кода и соответствующего кода Уолша. Это обеспечивает разделение сигналов различных пользователей и помогает эффективно передавать данные параллельно. Затем выполняется проверка характеристик полученных сигналов. Подтверждается, что они хорошо сбалансированы (среднее близко к нулю, стандартное отклонение равно 1), что важно для качественной передачи данных.
pn_I = pn_gen_walsh([1; zeros(Int, 14)], [15, 13, 9, 8, 7, 5, 1], Size_A)
pn_Q = pn_gen_walsh([1; zeros(Int, 14)], [15, 12, 11, 10, 6, 5, 4, 3, 1], Size_A)
walsh_pilot = walsh_hadamard(0, Size_A) # [1,1,1,1...]
walsh_user1 = walsh_hadamard(1, Size_A) # [1,-1,1,-1...]
pilot_I = pn_I .* walsh_pilot
pilot_Q = pn_Q .* walsh_pilot
user1_I = pn_I .* walsh_user1
user1_Q = pn_Q .* walsh_user1
code_list = [A, pilot_I, pilot_Q, user1_I, user1_Q]
code_names = ["A (engee)", "Pilot I", "Pilot Q", "User1 I", "User1 Q"]
df_stats = DataFrame(
Код = code_names,
Длина = [length(c) for c in code_list],
Среднее = [round(mean(c), digits=4) for c in code_list],
Std = [round(std(c), digits=4) for c in code_list],
Мин = [minimum(c) for c in code_list],
Макс = [maximum(c) for c in code_list],
Процент_1 = [round(count(==(1), c)/length(c)*100, digits=2) for c in code_list],
Процент_minus1 = [round(count(==(-1), c)/length(c)*100, digits=2) for c in code_list]
)
println(df_stats)
Анализ статистической таблицы показывает следующие характеристики сигналов:
- Исходный сигнал "A" является униполярным с равным распределением нулей и единиц. Стандартное отклонение соответствует ожиданиям для бинарного сигнала с равной вероятностью символов.
- Сигналы пилотного канала (Pilot I и Pilot Q) имеют средние значения близкие к нулю, что указывает на хорошую балансировку и отсутствие постоянной составляющей. Стандартное отклонение равно единице, подтверждающее нормированную мощность сигнала. Процентное распределение единиц и минус единиц близко к 50/50, обеспечивая сбалансированность последовательностей.
- Пользовательские каналы (User1 I и User1 Q) также демонстрируют близкие к нулю средние значения и стандартное отклонение, равное единице. Распределение положительных и отрицательных единиц максимально сбалансировано, особенно у User1 Q.
Общие выводы подтверждают, что все канальные сигналы обладают оптимальными характеристиками для передачи: нулевая постоянная составляющая, нормированная мощность и равновероятность символов. Небольшие отклонения от идеала связаны с конечностью последовательности и статистическими колебаниями.
Код ниже вычисляет корреляцию между парами каналов, в нём создается список corr_data, содержащий пары каналов и соответствующие коэффициенты корреляции. Коэффициент рассчитывается путем поэлементного перемножения соответствующих элементов двух каналов, суммирования результата и нормализации делением на длину последовательности. Затем формируется таблица df_corr с двумя столбцами: названия пар каналов и численные значения корреляций. Таблица выводится на экран командой println.
corr_data = [
("Pilot I × User1 I", round(sum(pilot_I .* user1_I)/length(pilot_I), digits=4)),
("Pilot Q × User1 Q", round(sum(pilot_Q .* user1_Q)/length(pilot_Q), digits=4))
]
df_corr = DataFrame(
Пара = [x[1] for x in corr_data],
Корреляция = [x[2] for x in corr_data]
)
println(df_corr)
Нулевая корреляция подтверждает ортогональность кодов Уолша, отсутствие взаимных помех и правильное формирование канальных сигналов в системе CDMA, теперь запустим нашу модель и убедимся в корректности выбранных значений.
.png)
function run_model( name_model)
Path = (@__DIR__) * "/" * name_model * ".engee"
if name_model in [m.name for m in engee.get_all_models()]
model = engee.open( name_model )
model_output = engee.run( model, verbose=true );
else
model = engee.load( Path, force=true )
model_output = engee.run( model, verbose=true );
engee.close( name_model, force=true );
end
sleep(0.1)
return model_output
end
run_model("CDMA_MAI")
BER = collect(simout["CDMA_MAI/Error Rate Calculation.1"]).value[end]
println("Коэффициент битовых ошибок (BER): $(BER[1])")
println("Количество ошибок: $(BER[2])")
println("Общее количество бит: $(BER[3])")
Вывод
При уровне отношения сигнал-шум SNR = 10 дБ, была достигнута нулевая вероятность битовой ошибки (BER = 0). Это демонстрирует правильную работу всех компонентов модели CDMA: генерация псевдошумовых последовательностей, создание ортогональных канальных кодов, модуляцию QPSK с фазовым сдвигом /4 и последующую демодуляцию.
Полученный результат корреляционного анализа подтверждает полное отсутствие перекрестных помех между каналами благодаря идеальной ортогональности используемых кодов Уолша. Таким образом, проведённое моделирование успешно продемонстрировало правильность функционирования системы CDMA и её способность обеспечивать надёжную передачу данных без потерь на заданной длине последовательности.