PUCCH signals in 5G
The article presents a system for generating and processing uplink signals in the 5G standard, namely– the PUCCH (Physical Uplink Control Channel) control channel. This example allows us to visually explore the differences in signal processing chains for each format, comparing their structural complexity, the methods of modulation, encoding and spectrum expansion used. PUCCH (Physical Uplink Control Channel) is a physical uplink channel in 5G NR designed exclusively for transmitting UCI (Uplink Control Information) control information from user equipment (UE) to the base station (gNB).
PUCCH provides transmission of three main types of control information (UCI):
- HARQ-ACK — confirmation of incoming data reception (HARQ-ACK/NACK).
- CSI (Channel State Information) — Radio channel status reports (CQI, RI, PMI).
- SR (Scheduling Request) — Request to allocate resources for data transmission.
Unlike
the PUSCH data channel, PUCCH is optimized for transmitting small amounts of service information with minimal latency and high reliability. In 5G NR, the channel is implemented with increased flexibility compared to LTE: support for multiple formats (0-4), configurable duration (1-14 OFDM characters), dynamic resource allocation and frequency/time multiplexing.
The model implements and compares the PUCCH 1-4 formats (PUCCH 0 is not implemented because it is designed for 1-2 bits with an ultra-short duration). Each format is optimized for transmitting certain types of control information (UCI – Uplink Control Information).
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("PUCCH_model")
Comparative analysis of PUCCH formats implemented in the model:
Technical characteristics of PUCCH formats
[PIPE]Format[PIPE]Appointment[PIPE]Modulation[PIPE]Transform Precoding[PIPE]Features[PIPE]
[PIPE]:---[PIPE]:---[PIPE]:---[PIPE]:---[PIPE]:---[PIPE]
[PIPE]PUCCH1[PIPE]Short UCI (1-2 bits)[PIPE]Low PAPR[PIPE]Yes[PIPE]OCC[PIPE]
[PIPE]PUCCH2[PIPE]CSI[PIPE]QPSK[PIPE]No[PIPE]-[PIPE]
[PIPE]PUCCH3[PIPE]HARQ-ACK, SR[PIPE]QPSK + DFT[PIPE]Yes[PIPE]-[PIPE]
[PIPE]PUCCH4[PIPE]High capacity[PIPE]QPSK + Spreading[PIPE]Yes[PIPE]OCC + CDM[PIPE]
neededLibs = ["EngeeDSP", "Statistics", "LinearAlgebra", "FFTW", "StatsBase"]
for lib in neededLibs
try
eval(Meta.parse("using $lib"))
catch ex
Pkg.add(lib)
eval(Meta.parse("using $lib"))
end
end
function unwrap(phase::Vector{Float64})
unwrapped = copy(phase)
for i in 2:length(phase)
diff = phase[i] - phase[i-1]
if diff > π
unwrapped[i] -= 2π
elseif diff < -π
unwrapped[i] += 2π
end
end
return unwrapped
end
function compute_papr(signal::AbstractArray{<:Complex})
power = abs2.(signal)
papr_db = 10 * log10(maximum(power) / mean(power))
return round(papr_db, digits=2)
end
function compute_spectrum(signal::AbstractArray{<:Complex}, fs=1.0)
N = length(signal)
fft_result = fft(signal)
freqs = fftfreq(N, fs)
pwr = abs2.(fft_result) / N
return freqs, pwr
end
function analyze_constellation(signal::AbstractArray{<:Complex}, title)
p = scatter(real.(signal), imag.(signal),
title=title, xlabel="In-phase (I)", ylabel="Quadrature (Q)",
legend=false, markersize=4, markerstrokewidth=0, alpha=0.7,
aspect_ratio=:equal)
return p
end
function compute_signal_stats(signal::AbstractArray{<:Complex}, name)
println("\n" * "═"^50)
println("СТАТИСТИКА: $name")
println("═"^50)
println(" Тип данных: $(eltype(signal))")
println(" Размер: $(size(signal))")
println(" PAPR: $(compute_papr(signal)) дБ")
println(" Энергия: $(round(sum(abs2.(signal)), digits=2))")
println(" Средняя амплитуда: $(round(mean(abs.(signal)), digits=4))")
println(" Средняя фаза: $(round(mean(angle.(signal)), digits=4)) рад")
end
PUCCH Format 1: Simulates the transmission of short control information (1-2 bits) using sequences with a low PAPR (peak factor). Includes operations:
-
Generation of low-PAPR sequences (
nrLowPAPRS). -
External parameter management via user blocks (
Engee Function). -
The use of Orthogonal Cover Codes (OCC – Orthogonal Cover Codes) through the blocks
Spreading Formatto separate users.
y = collect(simout["PUCCH_model/PUCCH1/# Parse and validate inputs.y"]).value[end]
oSeq1 = collect(simout["PUCCH_model/PUCCH1/Spreading Format-1.1"]).value[end]
final = collect(simout["PUCCH_model/PUCCH1/# Get the PUCCH format 1 sequence.Seq"]).value[end]
compute_signal_stats(y, "Сигнал y (после nrPUCCH1)")
compute_signal_stats(oSeq1, "Ортогональная последовательность 1")
compute_signal_stats(final, "Финальная последовательность")
p1 = analyze_constellation(y, "PUCCH1: Созвездие сигнала 'y'")
p2 = analyze_constellation(final, "PUCCH1: Финальное созвездие")
p3 = plot(abs.(final), title="PUCCH1: The amplitude envelope",
xlabel="The counts", ylabel="The amplitude", legend=false, grid=true)
display(plot(p1, p2, p3, layout=(1,3), size=(1200, 400)))
savefig("pucch1_analysis.png");
PUCCH Format 2: Is intended for transmission of CSI (Channel State Information) of longer length. The processing chain includes:
-
Scrambling using a pseudorandom sequence generator (
PUCCH PRBS). -
QPSK modulation (
Symbol Modulate). -
Relatively simple structure compared to other formats.
prbs_bits = collect(simout["PUCCH_model/PUCCH2/PUCCH PRBS-1.1"]).value[end]
modulated = collect(simout["PUCCH_model/PUCCH2/Symbol Modulate-1.1"]).value[end]
println("\nСкремблированные биты (PRBS):")
println(" Кол-во бит: $(length(prbs_bits))")
println(" Баланс (1/0): $(sum(prbs_bits))/$(sum(.!prbs_bits))")
compute_signal_stats(modulated, "Модулированные QPSK символы")
unique_symbols = unique(round.(modulated, digits=6))
println("\nУникальные точки QPSK созвездия:")
for sym in unique_symbols
println(" I=$(round(real(sym), digits=4)), Q=$(round(imag(sym), digits=4))")
end
phase = angle.(modulated)
instant_freq = diff(unwrap(phase))
p1 = histogram(instant_freq, bins=30, title="PUCCH2: Instantaneous frequency",
xlabel="Frequency", ylabel="Frequency of occurrence", legend=false)
p2 = analyze_constellation(modulated, "PUCCH2: Созвездие QPSK")
display(plot(p1, p2, layout=(1,2), size=(1200, 400)))
savefig("pucch2_analysis.png");
PUCCH Format 3: Is used to transmit HARQ-ACK and SR medium capacity. Features:
-
Converting logical bits to integer values.
-
Symbolic Modulation (QPSK).
-
Transform Precoding, using DFT (Discrete Fourier Transform) before OFDM modulation, which is typical for subcarriers with DFT-s-OFDM (SC-FDMA) in the uplink.
converted = collect(simout["PUCCH_model/PUCCH3/Convert in Int.1"]).value[end]
final = collect(simout["PUCCH_model/PUCCH3/Transform Precoding-1.1"]).value[end]
println("\nПреобразованные целочисленные данные:")
println(" Диапазон: $(minimum(converted)) - $(maximum(converted))")
println(" Среднее: $(round(mean(converted), digits=2))")
compute_signal_stats(final, "Сигнал после Transform Precoding")
N = length(final)
fs = 1.0
fft_result = fft(final)
freqs = fftfreq(N, fs)
pwr = abs2.(fft_result) / N
p1 = plot(freqs, pwr, title="PUCCH3: Power spectral Density",
xlabel="Frequency", ylabel="Power (dB)", legend=false, grid=true,
xlim=(-0.5, 0.5))
p2 = analyze_constellation(final, "PUCCH3: Созвездие после DFT")
max_pwr = maximum(pwr)
half_pwr = max_pwr / 2
indices = findall(pwr .> half_pwr)
if !isempty(indices)
min_freq = minimum(freqs[indices])
max_freq = maximum(freqs[indices])
bandwidth = max_freq - min_freq
println("\nОценка ширины полосы:")
println(" Ширина полосы по уровню 3 дБ: $(round(bandwidth, digits=4))")
else
println("\nНе удалось оценить ширину полосы по уровню 3 дБ")
end
display(plot(p1, p2, layout=(1,2), size=(900, 400)))
savefig("pucch3_analysis.png");
PUCCH Format 4: Is designed to transmit high-capacity control information for a single user or with code division multiplexing for multiple users. It has the most complex structure:
-
Sequential scrambling, QPSK modulation.
-
Block-wise Spreading implemented in a separate subsystem
Spreading. This process multiplies modulated symbols by orthogonal cover codes (OCCs) to create multiple copies of the signal, which increases reliability and/or allows multiplexing of users. -
Transform precoding.
prbs = collect(simout["PUCCH_model/PUCCH4/PUCCH PRBS.1"]).value[end]
modulated = collect(simout["PUCCH_model/PUCCH4/Symbol Modulate.1"]).value[end]
after_spreading = collect(simout["PUCCH_model/PUCCH4/Spreading.Out1"]).value[end]
final = collect(simout["PUCCH_model/PUCCH4/Transform Precoding.1"]).value[end]
compute_signal_stats(modulated, "До Block-wise Spreading")
compute_signal_stats(after_spreading, "После Spreading")
compute_signal_stats(final, "После Transform Precoding")
gain_factor = mean(abs2.(after_spreading)) / mean(abs2.(modulated))
println("\nЭффективность Block-wise Spreading:")
println(" Коэффициент усиления мощности: $(round(gain_factor, digits=2))")
plots = []
push!(plots, analyze_constellation(modulated, "До Spreading"))
push!(plots, analyze_constellation(after_spreading, "После Spreading"))
push!(plots, analyze_constellation(final, "Финальный сигнал"))
p4 = plot(abs.(modulated), label="Before Spreading", linewidth=1.5, alpha=0.8)
plot!(p4, abs.(after_spreading), label="After Spreading", linewidth=1, alpha=0.7)
plot!(p4, abs.(final), label="After Precoding", linewidth=1, alpha=0.7,
title="PUCCH4: Comparing amplitudes", xlabel="The counts", ylabel="The amplitude", grid=true)
push!(plots, p4)
display(plot(plots..., layout=(2,2), size=(1000, 800)))
savefig("pucch4_analysis.png");
, Key modeling results
📈 PAPR (peak factor)
- PUCCH1: 0.0 dB — low-PAPR sequences, ideal for UE energy efficiency
- PUCCH2: 0.0 dB — QPSK with constant envelope in the model
- PUCCH3: 13.8 dB — high PAPR is typical for DFT-s-OFDM
- PUCCH4: 8.73 dB — balance between capacity and power consumption
🔧 Specific features
- PUCCH1: low-PAPR+ OCC — for short ACK/NACK and SR
- PUCCH2: Simple QPSK chain — for periodic CSI reports
- PUCCH3: DFT-s-OFDM — for HARQ-ACK+SR medium capacity
- PUCCH4: Block-wise Spreading + CDM — for high capacity and multi-user scenarios
💾 Amount of data
- PUCCH1: 84 characters (low efficiency, ~0.024 bits/character)
- PUCCH2: 48 characters (1.0 bit/character)
- PUCCH3: 48 characters (1.0 bit/character)
- PUCCH4: 96 characters after expansion (1.0 bit/character)
⚡ Comparison with theory
All results comply with 3GPP specifications:
- PUCCH1: Low PAPR as designed for IoT devices
- PUCCH3: high PAPR (13.8 dB) expected for DFT-s-OFDM
- PUCCH4: spreading gives 1.0 power gain — orthogonal codes to separate users, not gain
- Resource efficiency increases from PUCCH1 to PUCCH4 in proportion to the complexity of processing
Conclusion
All four PUCCH formats are correctly implemented in the model, and their characteristics comply with 3GPP 5G NR specifications.
[PIPE]Format[PIPE]Appointment[PIPE]Advantages[PIPE]
[PIPE]:---[PIPE]:---[PIPE]:---[PIPE]
[PIPE]PUCCH1[PIPE]Short control information[PIPE]Minimum power consumption, low PAPR[PIPE]
[PIPE]PUCCH2[PIPE]CSI transmission (Channel status information)[PIPE]Easy to implement, stable operation[PIPE]
[PIPE]PUCCH3[PIPE]HARQ-ACK and scheduling requests[PIPE]Balance of capacity and reliability[PIPE]
[PIPE]PUCCH4[PIPE]High capacity, multi-user access[PIPE]CDM support, advanced functionality[PIPE]
Key conclusions on the implementation of PUCCH formats in the 5G NR model:
-
Each of the four PUCCH formats implements a well-defined compromise between capacity, latency, and energy efficiency, which allows adaptive configuration to meet the specific requirements of a network scenario.
-
The model clearly demonstrates the direct relationship between the type of control information transmitted (UCI) and the complexity of the signal path — from the minimalistic PUCCH 0 for short confirmations to the high-capacity PUCCH 4 with CDM support for multi-user operation.
-
All critical components of the physical layer — scrambling, modulation, transform precoding and spectrum expansion — are implemented in strict accordance with 3GPP TS 38.211 specifications, ensuring full compatibility of the model with the standard.
-
The proposed implementation serves not only as a learning tool, but also as a valid basis for prototyping, testing and verifying real-world PUCCH signal processing algorithms in fifth-generation communication systems.