卷积码编码和维特比译码

合集下载

卷积码的编码及解码Viterbi解码Word版

卷积码的编码及解码Viterbi解码Word版

卷积码的编码及解码(Viterbi 解码)一、实验目的1、了解卷积码的基本原理;2、掌握卷积码编码的电路设计方法;2、掌握卷积码 Viterbi 译码的基本方法和电路设计方法。

二、实验仪器1、移动通信实验箱一台;2、台式计算机一台;三、实验原理1.卷积码编码原理卷积码是一个有限记忆系统,它也将信息序列切割成长度 k的一个个分组,与分组码不同的是在某一分组编码时,不仅参看本时刻的分组而且参看本时刻以前的 L 个分组。

我们把 L+1 称为约束长度。

2.卷积码的译码算法(硬判决 Viterbi 译码)Viterbi译码算法是一种最大似然算法,它不是在网络图上依次比较所有可能的路径,而是接收一段,计算,比较一段,保留最有可能的路径,从而达到整个码序列是一个最大似然序列。

Viterbi解码算法的基本步骤如下:1、从某一时间单位j=m开始,对进入每一状态的所有长为j段分支的部分路径,计算部分路径度量。

对每一状态,挑选并存储一条有最大度量的部分路径及其部分度量,称此部分路径为留选(幸存)路径。

2、j增加1,把此时刻进入每一状态的所有分支度量,和同这些分支相连的前一时刻的留选路径的度量相加,得到了此时刻进入每一状态的留选路径,加以存储并删去其他所有的路径。

因此留选路径延长了一个分支。

3、若j<L+m,则重复以上步骤,否则停止,译码器得到了有最大路径度量的路径。

上面的过程可以简单的总结为“加、比、选”(也称ACS)。

四、实验步骤1、将实验箱和计算机通过串行口连接好,为实验箱上电。

2、将与实验箱相连的电脑上的学生平台程序打开。

在“实验选择”栏中选择“卷积码”实验,点击确认键。

从而进入此实验界面。

3、在实验界面上点“生成数据”,让系统生成待编码的随机比特。

也可在界面上直接双击所显示的 bit,修改其值。

4、在界面上点击下发“原始数据”,该数据将被送入单片机(或 CPLD)进行卷积编码然后经过编码的数据被送回学生平台并显示在“编码数据”栏。

FEC前向纠错,卷积编码之维特比译码

FEC前向纠错,卷积编码之维特比译码

FEC前向纠错,卷积编码之维特⽐译码因为要学习做WCDMA的流程解析,需要先提取卷积数据,⾸先就要做FEC卷积译码。

于是⽹上翻了好⼤⼀圈,特地学习了下viterbi译码算法,费很⼤⼒⽓才凑齐能够正确跑起来的代码,特记录⼀下。

说点题外话:viterbi是个⼈,全名Andrew J. Viterbi,⼀枚数学家,美国⾼通公司的创始⼈之⼀(没错,就是现在⼿机上那个⾼通芯⽚的⾼通),现代⽆线数字通讯⼯程的奠基⼈。

此外,viterbi算法不但可⽤来做卷积译码,另外⼀个⼴泛的应⽤是做股票证券量化预测计算(隐马模型预测)。

没错,就是⾼频量化交易炒股的算法基础。

美国量化对冲基⾦的传奇,⼤奖章基⾦背后的⽼板James Simons,⾸创将隐马模型预测⽤于炒股,也是⼀枚数学家。

两枚玩数学算法的巨富,谁说学数学算法没⽤的?FEC前向纠错译码⽤的viterbi算法代码摘抄⾃libfec,⾥⾯的实现很全⾯,还有mmx,sse加速版。

测试是做WCDMA,所以解交织和译码⽤的3GPP WCDMA的卷积编码参数(⼀帧编码长度262bits,卷积编码多项式是 r=1/2 k=9),我就只摘取了需要的viterbi29部分,有需要全部实现的同学可以⾃⾏去下载libfec。

下⾯是写来⽤于测试验证算法正确性的线程代码。

从IQ⽂件中⼀次读取2个float数,读取262+8(⼀帧viterbi译码长度)个数据后进⾏译码,若译码成功程序停在对应的测试断点上。

UINT CALLBACK ProcessIQDataThread(void *p_param){Convolution2Viterbi_t *p_sys = (Convolution2Viterbi_t *)p_param;vector<double> *p_data = NULL;int framebits = 262;struct v29 *vp;vector<float> uninter1;vector<float> uninter2;vector<float> radioFrame;vector<float> frameL;vector<float> frameR;vector<uint8_t> viterbi_in;uint8_t viterbi_out[33];uninter2.resize((framebits + 8));uninter1.resize((framebits + 8) * 2);viterbi_in.resize((framebits + 8) * 2);if ((vp = (struct v29 *)create_viterbi29_port(framebits)) == NULL) {return -1;}while (!p_sys->exit_thread){if (!p_data){WaitForSingleObject(p_sys->iq_data_event, 200);p_sys->iq_data_list.Lock();p_data = p_sys->iq_data_list.GetUse();p_sys->iq_data_list.UnLock();}if (!p_data)continue;// 读取2个浮点数for (int i = 0; i < p_data->size() / 2; i++){frameL.push_back(p_data->at(0));frameR.push_back(p_data->at(1));}// ⼀帧译码长度if (frameL.size() >= (framebits + 8)){// 解交织inter2deInterleavingNP(30, inter2Perm, frameL, uninter2);radioFrame.insert(radioFrame.end(), uninter2.begin(), uninter2.end());deInterleavingNP(30, inter2Perm, frameR, uninter2);radioFrame.insert(radioFrame.end(), uninter2.begin(), uninter2.end());if (radioFrame.size() >= (framebits + 8) * 2){// 解交织inter1deInterleavingNP(inter1Columns[1], inter1Perm[1], radioFrame, uninter1);radioFrame.clear();// 使⽤Viterbi算法做FEC译码for (int i = 0; i < (framebits + 8) * 2; i++){viterbi_in.push_back( ((int)uninter1[i] >> 24) );}init_viterbi29_port(vp, 0);update_viterbi29_blk_port(vp, viterbi_in.data(), framebits + 8);chainback_viterbi29_port(vp, viterbi_out, framebits, 0);#ifdef _DEBUG// 数据验证for (int i = 0; i < 33 - 4; i++) {if (viterbi_out[i] == 0x98 && viterbi_out[i + 1] == 0x54 && viterbi_out[i + 2] == 0xA0 && viterbi_out[i + 3] == 0x00) int bbb = 0;if (viterbi_out[i] == 0x05 && viterbi_out[i + 1] == 0x33 && viterbi_out[i + 2] == 0x00 && viterbi_out[i + 3] == 0x0c) int bbb = 0;if (viterbi_out[i] == 0x00 && viterbi_out[i + 1] == 0x03 && viterbi_out[i + 2] == 0xf4 && viterbi_out[i + 3] == 0x40) int bbb = 0;if (viterbi_out[i] == 0xc5 && viterbi_out[i + 1] == 0x80 && viterbi_out[i + 2] == 0x05 && viterbi_out[i + 3] == 0x5a) int bbb = 0;if (viterbi_out[i] == 0xe4 && viterbi_out[i + 1] == 0x00 && viterbi_out[i + 2] == 0x33 && viterbi_out[i + 3] == 0xe6) int bbb = 0;if (viterbi_out[i] == 0x72 && viterbi_out[i + 1] == 0x08 && viterbi_out[i + 2] == 0x38)int bbb = 0;if (viterbi_out[i] == 0xe2 && viterbi_out[i + 1] == 0x00 && viterbi_out[i + 2] == 0x38)int bbb = 0;}#endif}frameL.clear();frameR.clear();}p_sys->iq_data_list.Lock();p_sys->iq_data_list.PushEmpty(p_data);p_data = p_sys->iq_data_list.GetUse();p_sys->iq_data_list.UnLock();}return 0;}解交织 Interleaving.h#pragma once#include <vector>#include <assert.h>const int inter1Columns[4] = {1, // TTI = 10ms2, // TTI = 20ms4, // TTI = 40ms8 // TTI = 80ms};// 25.212 4.2.5.2 table 4: Inter-Column permutation pattern for 1st interleaving:const char inter1Perm[4][8] = {{0}, // TTI = 10ms{0, 1}, // TTI = 20ms{0, 2, 1, 3}, // TTI = 40ms{0, 4, 2, 6, 1, 5, 3, 7} // TTI = 80ms};// 25.212 4.2.11 table 7: Inter-Column permutation pattern for 2nd interleaving:const char inter2Perm[30] = { 0,20,10,5,15,25,3,13,23,8,18,28,1,11,21,6,16,26,4,14,24,19,9,29,12,2,7,22,27,17 };/* FIRST steps two pointers through a mapping, one pointer into the interleaved* data and the other through the uninterleaved data. The fifth argument, COPY,* determines whether the copy is from interleaved to uninterleaved, or back.* FIRST assumes no padding is necessary.* The reason for the define is to minimize the cost of parameterization and* function calls, as this is meant for L1 code, while also minimizing the* duplication of code.*/#define FIRST(UNINTERLEAVED,UNINTERLEAVEDP,INTERLEAVED,INTERLEAVEDP,COPY) \assert(UNINTERLEAVED.size() == INTERLEAVED.size()); \unsigned int rows = UNINTERLEAVED.size() / columns; \assert(rows * columns == UNINTERLEAVED.size()); \const char *colp = permutation; \float *INTERLEAVEDP = &INTERLEAVED[0]; \for (unsigned i = 0; i < columns; i++) { \float *UNINTERLEAVEDP = &UNINTERLEAVED[*colp++]; \for (unsigned int j = 0; j < rows; j++) { \COPY; \UNINTERLEAVEDP += columns; \} \}/** interleaving with No Padding */void interleavingNP(const unsigned int columns, const char *permutation, vector<float> &in, vector<float> &out) {FIRST(in, inp, out, outp, *outp++ = *inp)}/** de-interleaving with No Padding */void deInterleavingNP(const unsigned int columns, const char *permutation, vector<float> &in, vector<float> &out) {FIRST(out, outp, in, inp, *outp = *inp++)}/* SECOND steps two pointers through a mapping, one pointer into the interleaved* data and the other through the uninterleaved data. The fifth argument, COPY,* determines whether the copy is from interleaved to uninterleaved, or back.* SECOND pads if necessary.* The reason for the define is to minimize the cost of parameterization and* function calls, as this is meant for L1 code, while also minimizing the* duplication of code.*/#define SECOND(UNINTERLEAVED,UNINTERLEAVEDP,INTERLEAVED,INTERLEAVEDP,COPY) \assert(UNINTERLEAVED.size() == INTERLEAVED.size()); \int R2 = (UNINTERLEAVED.size() + columns - 1) / columns; \int padding = columns * R2 - UNINTERLEAVED.size(); \int rows = R2; \int firstPaddedColumn = columns - padding; \const char *colp = permutation; \float *UNINTERLEAVEDP = &UNINTERLEAVED[0]; \for (int i = 0; i < columns; i++) { \int trows = rows - (*colp >= firstPaddedColumn); \float *INTERLEAVEDP = &INTERLEAVED[*colp++]; \for (int j = 0; j < trows; j++) { \COPY; \INTERLEAVEDP += columns; \} \}/** interleaving With Padding */void interleavingWP(const int columns, const char *permutation, vector<float> &in, vector<float> &out){SECOND(in, inp, out, outp, *outp = *inp++)}/** de-interleaving With Padding */void deInterleavingWP(const int columns, const char *permutation, vector<float> &in, vector<float> &out){SECOND(out, outp, in, inp, *outp++ = *inp)}/*Determining the constants.From the standard we know:* All frame sizes for the BCH.* transport block is 246 bits* there are two radio frames, 270 bits each* TTI is 20 ms* SF is 256* parity word Li is 16 bits* For all downlink TrCH except BCH, the radio frame size is 2*38400/SF = 76800/SF.* For SF=256 that's 300.* For SF=4 that's 19200.* The maximum code block size for convulutional coding is 540 bits (25.212 4.2.2.2).* That corresponds to a radio frame size of 1080 bits, or a spreading factor of 71,meaning that the smallest spreading factor that can be used is 128.* 76800/128 = 600 coded bits -> roughly 300 data bits.* That corresponds to an input rate of roughly 30 kb/s at.* The maximum code block size for turbo coding is 5114 bits (25.212 4.2.2.2).* That corresponds to a radio frame size of 15342 bits, or a spreading factor of 5,meaning that the smallest spreading factor that can be used is 8.* 76800/8 = 9600 coded bits -> roughly 3200 data bits.* That corresponds to an input rate of roughly 320 kb/s.OK - SO HOW DO YOU GET HIGHER RATES?? HOW CAN YOU USE SF=4??A: Use the full 5114-but code block and then expand it with rate-matching.You still can't get the full ~640 kb/s implied by SF=4, but you get to ~500 kb/s.(pat) A: They considered this problem. See 25.212 4.2.2.2 Code block segmentation.In Layer1, after transport block concatenation, you then simply chop the result upinto the largest pieces that can go through the encoder, then put them back together after. From "higher layers" we are given:* SF: 4, 8, 16, 32, 64, 128, 256.* P: 24, 16, 8, 0 bits* TTI: 10, 20, 40 ms.To simplify things, we set:* TTI 10 ms always on DCH and FACH, 20 ms on PCH and BCH* BCH and PCH are always rate-1/2 convolutional code* DCH and FACH are always rate-1/3 turbo code* no rate-matching, no puncturing* parity word is always 16 bits* So the only parameter than changes is spreading factor.* We will only support 15-slot (non-compressed) slot formats.From our simplifications we also know:* For non-BCH/PCH TrCH there is one radio frame,76800/SF channel (coded) bits, per transport block.* DCH and FACH always use rate-1/3 turbo code,which has 12 terminating bits in the output.* For DCH and FACH, the transport block size is((76800/SF - 12)/3) - P = (25600/SF) - 4 - P data bits,where P is the parity word size.* Fix P=16 for simplicity and transport block size is (25600/SF) - 20.* for SF=256, that's 80 bits.* for SF=16, that's 1580 bits.* for SF=8, that's 3180 bits.* For PCH there is one radio frame,76800/SF channel (coded) bits, per transport block.* SF=64, for that's 1200 channel bits.* It's a rate-1/2 conv code, so that's 1200/2 - 8 - P data bits.* P=16 so that's 1200/2 - 24 = 576 transport bits. Really?*/#if 0const int inter1Columns[] = { 1, 2, 4, 8 };const char inter1Perm[4][8] = {{0},{0, 1},{0, 2, 1, 3},{0, 4, 2, 6, 1, 5, 3, 7}};const char inter2Perm[] = {0, 20, 10, 5, 15, 25, 3, 13, 23, 8, 18, 28, 1, 11, 21,6, 16, 26, 4, 14, 24, 19, 9, 29, 12, 2, 7, 22, 27, 17};vector<char> randomBitVector(int n){vector<char> t(n);for (int i = 0; i < n; i++) t[i] = random() % 2;return t;}void testInterleavings(){int lth1 = 48;int C2 = 30;for (int i = 0; i < 4; i++) {vector<char> v1 = randomBitVector(lth1);vector<char> v2(lth1);vector<char> v3(lth1);v1.interleavingNP(inter1Columns[i], inter1Perm[i], v2);v2.deInterleavingNP(inter1Columns[i], inter1Perm[i], v3);cout << "first " << i << " " << (veq(v1, v3) ? "ok" : "fail") << endl;}for (int lth2 = 90; lth2 < 120; lth2++) {vector<char> v1 = randomBitVector(lth2);vector<char> v2(lth2);vector<char> v3(lth2);v1.interleavingWP(C2, inter2Perm, v2);v2.deInterleavingWP(C2, inter2Perm, v3);cout << "second " << lth2 << " " << (veq(v1, v3) ? "ok" : "fail") << endl;}for (int lth = 48; lth <= 4800; lth *= 10) {TurboInterleaver er(lth);cout << "Turbo Interleaver permutation(" << lth << ") " << (permutationCheck(er.permutation()) ? "ok" : "fail") << endl; vector<char> er1 = randomBitVector(lth);vector<char> er2(lth);er.interleave(er1, er2);vector<char> er3(lth);er.unInterleave(er2, er3);cout << "Turbo Interleaver(" << lth << ") " << (veq(er1.sliced(), er3) ? "ok" : "fail") << endl;}}#endifviterbi译码partab实现 partab.c/* Utility routines for FEC support* Copyright 2004, Phil Karn, KA9Q*/#include <stdio.h>#include "fec.h"unsigned char Partab[256] = {0};int P_init = 0;/* Create 256-entry odd-parity lookup table* Needed only on non-ia32 machines*/void partab_init(void) {int i, cnt, ti;/* Initialize parity lookup table */for (i = 0; i < 256; i++) {cnt = 0;ti = i;while (ti) {if (ti & 1)cnt++;ti >>= 1;}Partab[i] = cnt & 1;}P_init = 1;}/* Lookup table giving count of 1 bits for integers 0-255 */int Bitcnt[] = {0, 1, 1, 2, 1, 2, 2, 3,1, 2, 2, 3, 2, 3, 3, 4,1, 2, 2, 3, 2, 3, 3, 4,2, 3, 3, 4, 3, 4, 4, 5,1, 2, 2, 3, 2, 3, 3, 4,2, 3, 3, 4, 3, 4, 4, 5,2, 3, 3, 4, 3, 4, 4, 5,3, 4, 4, 5, 4, 5, 5, 6,1, 2, 2, 3, 2, 3, 3, 4,2, 3, 3, 4, 3, 4, 4, 5,2, 3, 3, 4, 3, 4, 4, 5,3, 4, 4, 5, 4, 5, 5, 6,2, 3, 3, 4, 3, 4, 4, 5,3, 4, 4, 5, 4, 5, 5, 6,3, 4, 4, 5, 4, 5, 5, 6,4, 5, 5, 6, 5, 6, 6, 7,1, 2, 2, 3, 2, 3, 3, 4,2, 3, 3, 4, 3, 4, 4, 5,2, 3, 3, 4, 3, 4, 4, 5,3, 4, 4, 5, 4, 5, 5, 6,2, 3, 3, 4, 3, 4, 4, 5,3, 4, 4, 5, 4, 5, 5, 6,3, 4, 4, 5, 4, 5, 5, 6,4, 5, 5, 6, 5, 6, 6, 7,2, 3, 3, 4, 3, 4, 4, 5,3, 4, 4, 5, 4, 5, 5, 6,3, 4, 4, 5, 4, 5, 5, 6,4, 5, 5, 6, 5, 6, 6, 7,3, 4, 4, 5, 4, 5, 5, 6,4, 5, 5, 6, 5, 6, 6, 7,4, 5, 5, 6, 5, 6, 6, 7,5, 6, 6, 7, 6, 7, 7, 8,};fec.h/* User include file for libfec* Copyright 2004, Phil Karn, KA9Q* May be used under the terms of the GNU Lesser General Public License (LGPL)*/#ifndef _FEC_H_#define _FEC_H_#ifdef __cplusplusextern "C" {#endif/* r=1/2 k=9 convolutional encoder polynomials */#define V29POLYA 0x1af#define V29POLYB 0x11dvoid *create_viterbi29_port(int len);void set_viterbi29_polynomial_port(int polys[2]);int init_viterbi29_port(void *p, int starting_state);int chainback_viterbi29_port(void *p, unsigned char *data, unsigned int nbits, unsigned int endstate); void delete_viterbi29_port(void *p);int update_viterbi29_blk_port(void *p, unsigned char *syms, int nbits);void partab_init();static inline int parityb(unsigned char x) {extern unsigned char Partab[256];extern int P_init;if (!P_init) {partab_init();}return Partab[x];}static inline int parity(int x) {/* Fold down to one byte */x ^= (x >> 16);x ^= (x >> 8);return parityb(x);}#ifdef __cplusplus}#endif#endif /* _FEC_H_ */viterbi29_port.c/* K=9 r=1/2 Viterbi decoder in portable C* Copyright Feb 2004, Phil Karn, KA9Q* May be used under the terms of the GNU Lesser General Public License (LGPL)*/#include <stdio.h>#include <stdlib.h>#include <memory.h>#include "fec.h"typedef union { unsigned int w[256]; } metric_t;typedef union { unsigned long w[8]; } decision_t;static union { unsigned char c[128]; } Branchtab29[2];static int Init = 0;/* State info for instance of Viterbi decoder */struct v29 {metric_t metrics1; /* path metric buffer 1 */metric_t metrics2; /* path metric buffer 2 */decision_t* dp; /* Pointer to current decision */metric_t* old_metrics, * new_metrics; /* Pointers to path metrics, swapped on every bit */decision_t* decisions; /* Beginning of decisions for block */};/* Initialize Viterbi decoder for start of new frame */int init_viterbi29_port(void* p, int starting_state) {struct v29* vp = p;int i;if (p == NULL)return -1;for (i = 0; i < 256; i++)vp->metrics1.w[i] = 63;vp->old_metrics = &vp->metrics1;vp->new_metrics = &vp->metrics2;vp->dp = vp->decisions;vp->old_metrics->w[starting_state & 255] = 0; /* Bias known start state */return 0;}void set_viterbi29_polynomial_port(int polys[2]) {int state;for (state = 0; state < 128; state++) {Branchtab29[0].c[state] = (polys[0] < 0) ^ parity((2 * state) & abs(polys[0])) ? 255 : 0; Branchtab29[1].c[state] = (polys[1] < 0) ^ parity((2 * state) & abs(polys[1])) ? 255 : 0; }Init++;}/* Create a new instance of a Viterbi decoder */void* create_viterbi29_port(int len) {struct v29* vp;if (!Init) {int polys[2] = { V29POLYA,V29POLYB };set_viterbi29_polynomial_port(polys);}if ((vp = (struct v29*)malloc(sizeof(struct v29))) == NULL)return NULL;if ((vp->decisions = (decision_t*)malloc((len + 8) * sizeof(decision_t))) == NULL) {free(vp);return NULL;}init_viterbi29_port(vp, 0);return vp;}/* Viterbi chainback */int chainback_viterbi29_port(void* p,unsigned char* data, /* Decoded output data */unsigned int nbits, /* Number of data bits */unsigned int endstate) /* Terminal encoder state */{struct v29* vp = p;decision_t* d;if (p == NULL)return -1;d = vp->decisions;/* Make room beyond the end of the encoder register so we can* accumulate a full byte of decoded data*/endstate %= 256;/* The store into data[] only needs to be done every 8 bits.* But this avoids a conditional branch, and the writes will* combine in the cache anyway*/d += 8; /* Look past tail */while (nbits-- != 0) {int k;k = (d[nbits].w[(endstate) / 32] >> (endstate % 32)) & 1;data[nbits >> 3] = endstate = (endstate >> 1) | (k << 7);}return 0;}/* Delete instance of a Viterbi decoder */void delete_viterbi29_port(void* p) {struct v29* vp = p;if (vp != NULL) {free(vp->decisions);free(vp);}}/* C-language butterfly */#define BFLY(i) {\unsigned int metric,m0,m1,decision;\metric = (Branchtab29[0].c[i] ^ sym0) + (Branchtab29[1].c[i] ^ sym1);\ m0 = vp->old_metrics->w[i] + metric;\m1 = vp->old_metrics->w[i+128] + (510 - metric);\decision = (signed int)(m0-m1) > 0;\vp->new_metrics->w[2*i] = decision ? m1 : m0;\d->w[i/16] |= decision << ((2*i)&31);\m0 -= (metric+metric-510);\m1 += (metric+metric-510);\decision = (signed int)(m0-m1) > 0;\vp->new_metrics->w[2*i+1] = decision ? m1 : m0;\d->w[i/16] |= decision << ((2*i+1)&31);\}/* Update decoder with a block of demodulated symbols* Note that nbits is the number of decoded data bits, not the number* of symbols!*/int update_viterbi29_blk_port(void* p, unsigned char* syms, int nbits) { struct v29* vp = p;decision_t* d;if (p == NULL)return -1;d = (decision_t*)vp->dp;while (nbits--) {void* tmp;unsigned char sym0, sym1;int i;for (i = 0; i < 8; i++)d->w[i] = 0;sym0 = *syms++;sym1 = *syms++;for (i = 0; i < 128; i++)BFLY(i);d++;tmp = vp->old_metrics;vp->old_metrics = vp->new_metrics;vp->new_metrics = tmp;}vp->dp = d;return 0;}。

卷积码的维特比译码

卷积码的维特比译码
主要内容
卷积码编码原理 维特比译码原理 Matlab实验 DSP仿真实验
1.卷积码编码
卷积编码则把k比特信息段编成n比特的 码组,但所编的n长码组不仅同当前的k 比特信息段有关联,而且还同前面的(N1)个信息段有关联,人们常称这N为该卷 积码的约束长度。
一般来说,对于卷积码,k和n是较小的 整数, 常把卷积码记作(n,k,N)卷积码,它 的编码效率为R=k/n。

主程序完成 对输入比特的
译码
探针将已译 码的数据写入
文件
译码实验结果对比
MATLAB译码 结果
DSP译码结 果
图2 :(2,1,2)卷积码的树状图
2.
格图也称网络图或篱笆图,它由状态图在时间上展开而得到,如图3所示。图 中画出了所有可能的数据输入时, 状态转移的全部可能轨迹,实线表示数据为 0, 虚线表示数据为 1, 线旁数字为输出码字,节点表示状态。
图3:(2,1,2)卷积码的网格图
2.卷积码的维特比译码
4.卷积码编码的C54x Simulator仿 真试验
初始化
探针从PC文件 中读取比特数

主程序完成 对输入比特的
卷积编码
探针将已编 码的数据写入
文件
编码结果对比
未编码数据
DSP编码后的数 据
MATLAB编码 后的数据
Viterbi译码的C54x Simulator仿真 试验
初始化
探针从PC文件 中读取比特数
维特比译码是一种最大似然译码算法。 最大似然译码算法的基本思路是: 把接收码字与所有可能的码字比较,选择一种码距最小的码字作为解码输出。 由于接收序列通常很长,所以维特比译码时最大似然译码做了简化, 即它把接 收码字分段累接处理,每接收一段码字,计算、 比较一次, 保留码距最小的路 径,直至译完整个序列。

卷积编码和Viterbi译码

卷积编码和Viterbi译码

卷积编码和Viterbi译码摘要本文的目的是向读者介绍了前向纠错技术的卷积编码和Viterbi译码。

前向纠错的目的(FEC)的是改善增加了一些精心设计的冗余信息,正在通过信道传输数据的通道容量。

在添加这种冗余信息的过程称为信道编码。

卷积编码和分组编码是两个主要的渠道形式编码。

简介前向纠错的目的(FEC)的是改善增加了一些精心设计的冗余信息,正在通过信道传输数据的通道容量。

在添加这种冗余信息的过程称为信道编码。

卷积编码和分组编码是两个主要的渠道形式编码。

卷积码串行数据操作,一次一个或数位。

分组码操作比较大(通常,多达几百个字节的情侣)消息块。

有很多有用的分组码和卷积多种,以及接收解码算法编码信息的DNA序列来恢复原来的各种数据。

卷积编码和Viterbi译码前向纠错技术,是一种特别适合于在其中一个已损坏的发射信号加性高斯白噪声(AWGN)的主要通道。

你能想到的AWGN信道的噪声,其电压分布也随着时间的推移,可以说是用高斯,或正常,统计分布特征,即一钟形曲线。

这个电压分布具有零均值和标准差这是一个信号与噪声比接收信号的信噪比(SNR)函数。

让我们承担起接收到的信号电平是固定的时刻。

这时如果信噪比高,噪声标准偏差小,反之亦然。

在数字通信,信噪比通常是衡量Eb /N的它代表噪声密度双面能源每比特除以之一。

卷积码通常是描述使用两个参数:码率和约束长度。

码率k/n,是表示为比特数为卷积编码器(十一)信道符号卷积编码器输出的编码器在给定的周期(N)的数量之比。

约束长度参数,钾,表示该卷积编码器的“长度”,即有多少K位阶段提供饲料的组合逻辑,产生输出符号。

K是密切相关的参数米,这表明有多少位的输入编码器周期被保留,用于编码后第一次在卷积编码器输入的出现。

的m参数可以被认为是编码器的记忆长度。

在本教程中,并在此示例的源代码,我集中精力率1 / 2卷积码。

Viterbi译码是一种两个卷积编码与解码,其他类型的算法类型的顺序解码。

matlab卷积编码与viterbi译码的实现

matlab卷积编码与viterbi译码的实现

matlab卷积编码与viterbi译码的实现MATLAB中viterbi译码算法讨论⼤家可以再评论区交流!!!MATLAB中实现viterbi译码的函数为:convenc其中:code = convenc(msg,trellis)vitdec其中:vitdec(code,trellis,tblen,opmode,dectype)code卷积编码,trellis⽹格表,tblen回溯长度,opmode:cont、term、trunc,dectype:unquant、hard、soft;本⼈最近在做⼀个关于viterbi译码算法,最终在FPGA中实现,在FPGA中最终的实现⽅案为xillinx IP核实现。

在此之前⽤MATLAB进⾏仿真验证。

matlab程序:Tre = poly2trellis(7,[133 171]);通过poly2trellis⽣成逻辑关系图,如下图所⽰。

逻辑关系图%卷积编码:msg = [0 1 0 1 1 0 1 0 1 1 1 1 0 0 1 1 0 0 1 0 1 0 0 1];code = convenc(msg,Tre);%code = [0,0,1,1,0,1,0,0,0,1,1,0,0,1,0,1,1,0,0,0,1,0,0,0,1,0,1,0,0,1,1,1,1,1,1,1,0,0,1,1,0,1,0,1,1,1,1,0];%这是通过convenc函数⽣成的卷积码%vitdec译码:%在vitdec译码过程中采⽤硬判决,通过不同的tblen和opmode来找出其中关系。

%(1) opmode = conttblen = 12;msg_dat = vitdec(code,Tre,tblen,'cont','hard');%msg_dat =[ 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 1 0 1 1 1 1 ];%通过了解到cont模式中,vitdec译码会有延迟,延迟的长度为tblen长度,所以在此对vitdec进⾏修改code_temp = [code,zeros(1,24)];msg_temp = vitdec(code_temp ,T,12,'cont','hard')msg_dat = msg_temp(13:end);%msg_dat = [ 0 1 0 1 1 0 1 0 1 1 1 1 0 0 1 1 0 0 1 0 1 0 0 1];%此时vitdec译码出来的数据和信源⼀样tblen = 18;code_temp = [code,zeros(1,24)];msg_temp = vitdec(code_temp ,T,12,'cont','hard')msg_dat = msg_temp(13:end);%msg_dat = [ 0 0 0 0 0 0 0 1 0 1 1 0 1 0 1 1 1 1 0 0 1 1 0 0];%此时vitdec译码出来的数据和信源在后⾯最后⼀位不⼀样%(2) opmode = termtblen = 12;msg_dat = vitdec(code,Tre,tblen,'term','hard');%msg_dat = [0 1 0 1 1 0 1 0 1 1 1 1 0 0 1 1 1 0 0 0 0 0 0 0];%此时vitdec译码出来的数据和信源⼀样前16位和信源⼀样后⾯的就出错了tblen = 18;msg_dat = vitdec(code,Tre,tblen,'term','hard');%msg_dat = [0 1 0 1 1 0 1 0 1 1 1 1 0 0 1 1 1 0 0 0 0 0 0 0];%此时vitdec译码出来的数据和信源⼀样前16位和信源⼀样后⾯的就出错了%(3)opmode = trunctblen = 12;msg_dat = vitdec(code,Tre,tblen,'trunc','hard');%msg_dat = [ 0 1 0 1 1 0 1 0 1 1 1 1 0 0 1 1 0 0 1 0 1 0 0 1];%此时vitdec译码出来的数据和信源⼀样tblen = 18;msg_dat = vitdec(code,Tre,tblen,'trunc','hard');%msg_dat = [ 0 1 0 1 1 0 1 0 1 1 1 1 0 0 1 1 0 0 1 0 1 0 0 1];%此时vitdec译码出来的数据和信源⼀样总结:以上通过⽐较tblen和opmode模式的不同对产⽣的结果,其中cont和trunc的模式总结起来就是cont有tblen延迟,但是trunc没有。

卷积码的维特比译码

卷积码的维特比译码

卷积码的维特比译码卷积编码器自身具有网格构造,基于此构造我们给出两种译码算法:Viterbi 译码算法和BCJR 译码算法。

基于某种准那么,这两种算法都是最优的。

1967 年,Viterbi 提出了卷积码的Viterbi 译码算法,后来Omura 证明Viterbi 译码算法等效于在加权图中寻找最优途径问题的一个动态规划〔Dynamic Programming〕解决方案,随后,Forney 证明它实际上是最大似然〔ML,Maximum Likelihood〕译码算法,即译码器选择输出的码字通常使接收序列的条件概率最大化。

BCJR 算法是1974 年提出的,它实际上是最大后验概率〔MAP,Maximum A Posteriori probability〕译码算法。

这两种算法的最优化目的略有不同:在MAP 译码算法中,信息比特错误概率是最小的,而在ML 译码算法中,码字错误概率是最小的,但两种译码算法的性能在本质上是一样的。

由于Viterbi 算法实现更简单,因此在实际应用比较广泛,但在迭代译码应用中,例如逼近Shannon 限的Turbo 码,常使用BCJR 算法。

另外,在迭代译码应用中,还有一种Viterbi 算法的变种:软输出Viterbi 算法〔SOV A,Soft-Output Viterbi Algorithm〕,它是Hagenauer 和Hoeher 在1989 年提出的。

为了理解Viterbi 译码算法,我们需要将编码器状态图按时间展开〔因为状态图不能反映出时间变化情况〕,即在每个时间单元用一个分隔开的状态图来表示。

例如〔3,1,2〕非系统前馈编码器,其生成矩阵为:G(D)=[1+D1+D21+D+D2]〔1〕图1 〔a〕〔3,1,2〕编码器〔b〕网格图〔h=5〕假定信息序列长度为h=5,那么网格图包含有h+m+1=8 个时间单元,用0 到h+m=7 来标识,如图1〔b〕所示。

假设编码器总是从全0 态S0 开始,又回到全0 态,前m=2 个时间单元对应于编码器开始从S0“启程〞,最后m=2 个时间单元对应于向S0“返航〞。

动态规划:卷积码Viterbi译码算法

动态规划:卷积码Viterbi译码算法

动态规划:卷积码的Viterbi译码算法学院:网研院姓名:xxx 学号:xxx 一、动态规划原理动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法。

动态规划算法通常用于求解具有某种最优性质的问题。

在这类问题中,可能会有许多可行解,每一个解都对应于一个值,我们希望找到具有最优值的解。

动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。

与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。

若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。

如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。

动态规划程序设计是对解最优化问题的一种途径、一种方法,而不是一种特殊算法。

不象搜索或数值计算那样,具有一个标准的数学表达式和明确清晰的解题方法。

动态规划程序设计往往是针对一种最优化问题,由于各种问题的性质不同,确定最优解的条件也互不相同,因而动态规划的设计方法对不同的问题,有各具特色的解题方法,而不存在一种万能的动态规划算法,可以解决各类最优化问题。

二、卷积码的Viterbi译码算法简介在介绍维特比译码算法之前,首先了解一下卷积码编码,它常常与维特比译码结合使用。

(2,1,3)卷积码编码器是最常见的卷积码编码器,在本次实验中也使用了(2,1,3)卷积码编码器,下面介绍它的原理。

(2,1,3)卷积码是把信源输出的信息序列,以1个码元为一段,通过编码器输出长为2的一段码段。

该码段的值不仅与当前输入码元有关,而且也与其之前的2个输入码元有关。

如下图所示,输出out1是输入、第一个编码器存储的值和第二个编码器存储的值逻辑加操作的结果,输出out2是输入和第二个编码器存储的值逻辑加操作的结果。

卷积码编码及其Viterbi译码的实现

卷积码编码及其Viterbi译码的实现
关键词 卷 积 码 ; iri 码 ;G P 软判 决 ; aa Vt b译 e 3P; M tb l
’ 9 12 I 1 .2 ’ N 文献 标 识 码 A 中 图分 类 号
Th mp e n a i n o n ou in lEn o i g a tr iDe o ng e I lme t to fCo v l to a c d n nd Vie b c d i
A s r c T e c dn f o v l t n c d d pe n3 y tm a d V tr i e o ig o / aec n ouin l e e aeds u s di i b ta t h o ig o n oui o e a o td i G s s n i b c dn f 2 rt o v lt a d r i se n t s c o e e d 1 o c c h p p r o h a e o e l i g t e s s m i ih r e iin y w t h a l y t ’ r r n c ,s rio a ,d t v r o n d a e .F rt e s k f rai n y t n hg e f c c i t e sne s s m S p f ma e u vv rp t z h e e h e e o h a o ef wi a a l g n d cs n p r r p i z d i e s s m i lm nain. h e ut o pi z t n s o a o e s s m r r c d e iin ya e e i o at ae o t e t y t mpe e tt i s mi nh e o T er s l f t a i h w t t t t y t p f m ̄ e a fce c r a o mi o h bh h e e o n i rv d t s ic se h i lt n Sr s l ,w ih m y p o ie sg i c trfrn e i y t i p e nain. mp o e .I a o d su ss te s l muai ’ e ut o s hc a rvd inf a ee c sse m lme tt in e n m o

卷积码编码与译码

卷积码编码与译码

例: (n, k, N) = (3, 1, 3)卷积码编码器方框图设输入信息比特序列是bi-2 bi-1 bi bi+1,则当输入bi时,此编码器输出3比特ci di ei,输入和输出的关系如下:
实际应用时常用的卷积码是(2,1,7)卷积码例如:IEEE 802.11a、DVB-T的内码;(2,1,7)卷积码的编码器,如图:
(3, 1, 3)卷积码 设现在的发送信息位为1101,为了使图中移存器的信息位全部移出,在信息位后面加入3个“0”,故编码后的发送序列为111 110 010 100 001 011 000。并且假设接收序列为111 010 010 110 001 011 000,其中第4和第11个码元为错码。 由于这是一个(n, k, N) = (3, 1, 3)卷积码,发送序列的约束度N = 3,所以首先需考察nN = 9比特。第1步考察接收序列前9位“111 010 010”。由此码的网格图可见,沿路径每一级有4种状态a, b, c和d。每种状态只有两条路径可以到达。故4种状态共有8条到达路径。 现在比较网格图中的这8条路径和接收序列之间的汉明距离。
4

现在将到达每个状态的两条路径的汉明距离作比较,将距离小的一条路径保留,称为幸存路径。若两条路径的汉明距离相同,则可以任意保存一条。这样就剩下4条路径了,即表中第2, 4, 6和8条路径。
第2步继续考察接收序列的后继3个比特“110”。计算4条幸存路径上增加1级后的8条可能路径的汉明距离。结果如下表。 表中最小的总距离等于2,其路径是abdc+b,相应序列为111 110 010 100。它和发送序列相同,故对应发送信息位1101。 按照表中的幸存路径画出的网格图示于下图中。
序号
路径
对应序列

_2_1_7_卷积编码及其维特比译码算法的软件实现

_2_1_7_卷积编码及其维特比译码算法的软件实现

第4卷 第6期信息与电子工程Vo1.4,No.6 2006年12月INFORMATION AND ELECTRONIC ENGINEERING Dec.,2006 文章编号:1672-2892 (2006)06-0467-03(2,1,7)卷积编码及其维特比译码算法的软件实现刘少阳,邹永(国防科技大学电子科学与工程学院,湖南长沙 410073)摘要:提出了一种(2,1,7)卷积编码及其维特比(Viterbi)译码的软件实现方案,在Matlab环境中应用软件技术实现了(2,1,7)卷积码的Viterbi译码器功能。

测试证明,该Viterbi译码算法在低信噪比下的误码率仍能达到10-6。

关键词:卷积编码;维特比译码;Matlab中图分类号:TN957.51+3 文献标识码:ASoftware Implementation of (2,1,7) Convolutional Coding andIts Viterbi Decoding AlgorithmLIU Shao-yang,ZOU Yong(School of Electronic Science and Engineering,National University of Defense Technology,Changsha Hunan 410073,China)Abstract: A software scheme of (2,1,7) convolutional coding and Viterbi decoding technology is presented,which implements Viterbi decoder function of (2,1,7) convolutional code in the Matlab.According to the test, the BER(Bit Error Rate)of Viterbi algorithm can still reach 10-6in the lowSNR( Signal-to-Noise Ratio).Key words: convolutional coding;Viterbi decoding;Matlab1 引言卷积码是由Elias于1955年提出的。

卷积 维特比译码 c语言

卷积 维特比译码 c语言

卷积维特比译码c语言卷积码和维特比(Viterbi)译码是两种在通信系统中常用的编码和解码技术。

卷积码是一种线性分组码,它通过将输入信息序列与一组预定的约束条件进行卷积运算来生成编码序列。

而维特比译码是一种高效的解码算法,用于从接收到的信号中恢复出原始的编码序列。

下面是一个简单的C语言示例,演示了如何实现卷积编码和维特比译码。

请注意,这只是一个基本的示例,实际的实现可能会更复杂,并且需要更多的错误处理和优化。

c复制代码:#include <stdio.h>#include <stdlib.h>#define N 4#define K 2#define G 2// 卷积编码函数void convolutional_encode(int input[K], int code[N]) {int i, j;for (i = 0; i < N; i++) {code[i] = 0;}for (i = 0; i < K; i++) {code[i] = input[i];}for (i = K; i < N; i++) {code[i] = (code[i - 1] ^ code[i - 2]) & G;}}// 维特比译码函数void viterbi_decode(int received[N], int output[K]) {int branch_metric[N][2];int path_metric[N];int max_metric, new_max_metric;int max_path, new_max_path;int i, j, k;for (i = 0; i < N; i++) {path_metric[i] = abs(received[i] - 0); // 初始化路径度量branch_metric[i][0] = abs(received[i] - 0); // 初始化分支度量branch_metric[i][1] = abs(received[i] - G); // 初始化分支}for (i = 0; i < N; i++) {output[i] = 0; // 初始化输出序列}for (i = 0; i < N; i++) {if (branch_metric[i][0] > branch_metric[i][1]) {output[i] = 0; // 选择分支0作为当前的最优路径path_metric[i] = branch_metric[i][0]; // 更新路径度量} else {output[i] = 1; // 选择分支1作为当前的最优路径path_metric[i] = branch_metric[i][1]; // 更新路径度量}if (path_metric[i] > max_metric) {max_metric = path_metric[i]; // 记录最大路径度量max_path = i; // 记录最大路径度量对应的路径值} else if (path_metric[i] == max_metric) { // 如果当前路径度量与最大路径度量相等,则选择路径值较小的路径作为最优路径new_max_metric = path_metric[i]; // 记录新的最大路径度量new_max_path = i; // 记录新的最大路径度量对应的路} else if (path_metric[i] < max_metric && path_metric[i] > new_max_metric) { // 如果当前路径度量比新记录的最大路径度量要小,但是比之前的最大路径度量要大,则更新新的最大路径度量和对应的路径值new_max_metric = path_metric[i]; // 更新新的最大路径度量new_max_path = i; // 更新新的最大路径度量对应的路径值} else if (path_metric[i] < max_metric && path_metric[i] < new_max_metric) { // 如果当前路径度量比新记录的最大路径度量要小,但是比之前的最大路径度量要小,则更新新的最大路径度量和对应的路径值,同时更新最优路径为新记录的最大路径对应的路径值和对应的分支值new_max_metric = new_max_metric; // 更新新的最大路径度量不变new_max_path = i; // 更新新的最大路径度量对应的路径值为当前路径。

基于维特比算法的卷积码译码实验

基于维特比算法的卷积码译码实验

基于维特比算法的卷积码译码实验摘要:本文主要简述了卷积码的编码过程,以及维特比算法译码的主要原理,是将接收到的编码序列与所有可能的发送序列作比较,选出汉明距离最小的一个序列作为译码输出。

本文根据维特比算法译码原理在matlab编写了程序仿真,对(2,1,7)卷积码数据进行加高斯白噪声,对比不同信噪比下的维特比译码误比特率。

关键词:卷积码;维特比;误比特率1引言卷积码是一种非分组码,它在1955年被伊利亚斯提出的卷积码在编码时是把k个比特的信息段编写成n个比特的码组,但是其监督码元不仅与当前编码比特信息有关,还与前面(N-1)个比特有关,N为卷积码的编码约束度,卷积码通常记为(n,k,N)[1]。

根据卷积码的特性,它更适合用于前向纠错,对于许多实际情况下它的效果好于分组码,并且运算简单,它尤其适合用在被高斯白噪声所干扰的传输信道[2]。

本文主要探索的是(2,1,7)卷积码的译码算法。

2卷积码的编码原理卷积码的编码器的主要由移位寄存器、模2加法器组成。

如图1[3]所示,为(2,1,7)卷积码的编码示意图,其卷积码的生成多项式的八进制表示为(133,171),八进制133转化为二进制为1011011,其中1比特的位置即代表那个移位寄存器的值作为模2加法器的输入,即生成多项式133描述的是图1中模2加法器输出Y,与此同理,生成多项式171描述的是模2加法器输出X。

至于生成多项式为什么是133和171,这其中涉及到编码的检错纠错能力问题、编码的复杂程度等因素,本文不深入探索这个。

很显然,共需要6个移位寄存器,和两个模2加法器来完成编码。

初始状态时,编码器的移位寄存器的值为0。

如待编码的信息序列为11,当第一个数据从最左端进去时,输出X的值为1,输出Y的值为1。

移位寄存器最右边的值不要了,然后把剩下的移位寄存器的值往右边移动一位,再把数据1放在移位寄存器的最左边。

然后再输入第二位待编码数据1,同理输出X值为0,输出Y的值为1。

卷积码-Viterbi译码

卷积码-Viterbi译码

卷积码-Viterbi译码卷积码在一个二进制分组码(n,k)当中,包含k个信息位,码组长度为n,每个码组的(n-k)个校验位仅与本码组的k个信息位有关,而与其它码组无关。

为了达到一定的纠错能力和编码效率(=k/n),分组码的码组长度n通常都比较大。

编译码时必须把整个信息码组存储起来,由此产生的延时随着n的增加而线性增加。

为了减少这个延迟,人们提出了各种解决方案,其中卷积码就是一种较好的信道编码方式。

这种编码方式同样是把k个信息比特编成n个比特,但k和n通常很小,特别适宜于以串行形式传输信息,减小了编码延时。

与分组码不同,卷积码中编码后的n个码元不仅与当前段的k个信息有关,而且也与前面(N-1)段的信息有关,编码过程中相互关联的码元为nN个。

因此,这N时间内的码元数目nN通常被称为这种码的约束长度。

卷积码的纠错能力随着N 的增加而增大,在编码器复杂程度相同的情况下,卷段积码的性能优于分组码。

另一点不同的是:分组码有严格的代数结构,但卷积码至今尚未找到如此严密的数学手段,把纠错性能与码的结构十分有规律地联系起来,目前大都采用计算机来搜索好码。

下面通过一个例子来简要说明卷积码的编码工作原理。

正如前面已经指出的那样,卷积码编码器在一段时间内输出的n位码,不仅与本段时间内的k位信息位有关,而且还与前面m段规定时间内的信息位有关,这里的m=N-1通常用(n,k,m)表示卷积码(注意:有些文献中也用(n,k,N)来表示卷积码)。

图1就是一个卷积码的编码器,该卷积码的n = 2,k = 1,m = 2,因此,它的约束长度nN = n×(m+1) = 2×3 = 6。

图1 (2,1,2)卷集码编码器在图1中,与为移位寄存器,它们的起始状态均为零。

、与、、之间的关系如下:(1)假如输入的信息为D = [11010],为了使信息D全部通过移位寄存器,还必须在信息位后面加3个零。

表1列出了对信息D进行卷积编码时的状态。

卷积码编码和维特比译码的性能对比

卷积码编码和维特比译码的性能对比

卷积码编码和维特比译码的性能对比1.引言卷积码的编码器是由一个有k位输入、n位输出,且具有m位移位寄存器构成的有限状态的有记忆系统,通常称它为时序网络。

编码器的整体约束长度为v,是全部k个移位寄存器的长度之和。

具有这样的编码器的卷积码称作[n,k,v]卷积码。

对于一个(n,1,v)编码器,约束长度v等于存储级数m.卷积码是由k个信息比特编码成n(nk)比特的码组,编码出的n比特码组值不仅与当前码字中的k个信息比特值有关,而且与其前面v个码组中的v*k个信息比特值有关。

卷积码有三种译码方式:序列译码、门限译码和概率译码。

其中,概率译码依据最大似然译码原理在全部可能路径中求取与接收路径最相像的一条路径,具有最佳的纠错性能,维特比译码是概率译码中极重要的一种方式。

序列译码和门限译码则不肯定能找出与接收路径最相像的一条路径。

不同于维特比译码,门限译码与序列译码所需的计算量是可变的且对于给定信息分组的最终判决仅仅基于(m+1)个接收分组,而不是基于整个接收序列。

与维特比译码所使用的对数似然量度不同,序列译码所使用的量度为Fano量度。

在接收序列受扰严峻的状况下,序列译码的计算量大于维特比译码所需的固定计算量,虽然序列译码要求的平均计算次数通常小于维特比译码。

在采纳并行处理的状况下,维特比译码的速度会优于序列译码。

在同样码率和存储级数的条件下,门限译码的性能比维特比译码低大约3dB.维特比译码的数据输出方式有硬判决及软判决两种方式,本文选取生成多项式为561,753的(2,1,8)卷积码对硬判决的性能进行分析,并依据维特比译码的原理以及卷积码的特性,对卷积码编码和维特比译码过程在加性高斯白噪声(AWGN)信道下进行仿真,并且依据仿真结果对维特比译码(硬判决)的结果进行分析。

由于卷积码的生成可以看做一个马尔科夫过程,因此,不同状态间的转移概率对描述这个过程有极关键的作用。

本文则基于MATLAB对不同状态间的转移概率进行求解,从而更精确地分析维特比译码的性能。

卷积编码和维特比译码的FPGA实现的开题报告

卷积编码和维特比译码的FPGA实现的开题报告

卷积编码和维特比译码的FPGA实现的开题报告一、选题背景卷积编码和维特比译码在通信领域得到了广泛应用,能够有效抵御噪声、降低误码率,是数字通信和卫星通讯等领域中常用的信道编码技术。

在数字信号处理领域,FPGA作为重要的计算平台,具有高速、低功耗等诸多优势。

因此,使用FPGA实现卷积编码和维特比译码算法具有非常重要的现实意义。

二、研究目的本课题旨在通过FPGA实现卷积编码和维特比译码算法,探究其在通讯领域的应用。

具体目标如下:1.实现卷积编码和维特比译码算法的FPGA硬件电路设计;2.分析FPGA实现卷积编码和维特比译码算法的优点和局限性;3.优化FPGA的硬件电路设计,提高卷积编码和维特比译码算法的运算速度和实时性。

三、研究内容和方法1.卷积编码和维特比译码算法的原理研究:了解卷积编码的实现过程,掌握卷积编码器的结构和编码方式,并进一步了解卷积编码的特点和应用场合;了解维特比译码的实现过程,掌握维特比译码器的结构和译码方式,并进一步了解维特比译码的特点和应用场合。

2.卷积编码和维特比译码算法的FPGA硬件电路设计:基于Xilinx Vivado软件平台,进行硬件电路设计,将卷积编码和维特比译码算法实现在FPGA上;实现卷积编码和维特比译码器的硬件电路设计,包括状态寄存器的设计与模块、拓扑控制模块以及输入输出模块的设计等。

3.性能分析和优化:对卷积编码和维特比译码算法的FPGA实现进行性能测试,并对测试结果进行分析和优化;优化FPGA的硬件电路设计,提高卷积编码和维特比译码的运算速度和实时性,同时减少计算资源的消耗,提高系统效率。

四、预期结果和意义本项目成功实现了卷积编码和维特比译码算法在FPGA硬件电路上的实现,并对其性能进行了深入研究和优化,将极大地促进数字通信和卫星通讯等领域的技术发展。

本研究有助于进一步推动FPGA技术的创新和发展,提高系统的运算速度和实时性,在促进通讯技术和工程实践上具有重要意义。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

卷积码编码维特比译码实验设计报告SUN一、实验目的掌握卷积码编码和维特比译码的基本原理,利用了卷积码的特性, 运用网格图和回溯以得到译码输出。

二、实验原理1.卷积码是由连续输入的信息序列得到连续输出的已编码序列。

其编码器将k个信息码元编为n个码元时,这n个码元不仅与当前段的k个信息有关,而且与前面的(m-1)段信息有关(m为编码的约束长度)。

2.一般地,最小距离d表明了卷积码在连续m段以内的距离特性,该码可以在m个连续码流内纠正(d-1)/2个错误。

卷积码的纠错能力不仅与约束长度有关,还与采用的译码方式有关。

3. 维特比译码算法基本原理是将接收到的信号序列和所有可能的发送信号序列比较,选择其中汉明距离最小的序列认为是当前发送序列。

卷积码的Viterbi 译码是根据接收码字序列寻找编码时通过网格图最佳路径的过程,找到最佳路径即完成了译码过程,并可以纠正接收码字中的错误比特。

4.所谓“最佳”, 是指最大后验条件概率:P( C/ R) = max [ P ( Cj/ R) ] , 一般来说, 信道模型并不使用后验条件概率,因此利用Beyes 公式、根据信道特性出结论:max[ P ( Cj/ R) ]与max[ P ( R/ Cj) ]等价。

考虑到在系统实现中往往采用对数形式的运算,以求降低运算量,并且为求运算值为整数加入了修正因子a1 、a2 。

令M ( R/ Cj) = log[ P ( R/ Cj) ] =Σa1 (log[ P( Rm/ Cmj ) ] + a2) 。

其中, M 是组成序列的码字的个数。

因此寻找最佳路径, 就变成寻找最大M( R/ Cj) , M( R/ Cj) 称为Cj 的分支路径量度,含义为发送Cj 而接收码元为R的似然度。

5.卷积码的viterbi译码是根据接收码字序列寻找编码时通过网格图最佳路径的过程,找到最佳路径即完成了译码过程并可以纠正接收码字中的错误比特。

三、实验代码#include<stdio.h>#include "Conio.h"#define N 7#include "math.h"#include <stdlib.h>#include<time.h>#define randomize() srand((unsigned)time(NULL))encode(unsigned int *symbols, /*编码输出*/unsigned int *data, /*编码输入*/unsigned int nbytes, /*nbytes=n/16,n为实际输入码字的数目*/unsigned int startstate /*定义初始化状态*/)////////////////////////////////////////////////////////////////////////////卷积码编码///////////////////////////////////////////////////////////////////////////////{unsigned int j;unsigned int input,a1=0,a2=0,a3=0,a4=0,a5=0,a6=0;for(j=0;j<nbytes;j++){input=*data;data++;*symbols = input^a1^a2^a3^a6; //c1(171)symbols++;*symbols = input^a2^a3^a5^a6; //c2(133)symbols++;a2=a1;a1=input;}return 0;}int trandistance(int m, int state1, int state2)/*符号m与从state1到state2时输出符号的汉明距离,如果state1无法到state2则输出度量值为100*/{int sym,sym1,sym2;sym1=((state2>>1)&1)^(state2&1)^(state1&1);sym2=((state2>>1)&1)^(state1&1);sym=(sym1<<1) | sym2;if ( ((state1&2)>>1)==(state2&1))c=((m&1)^(sym&1))+(((m>> 1)&1)^((sym >> 1)&1));elsec=10000;return(c);}int traninput(int a,int b) /*状态从a到b时输入卷积码的符号*/{int c;c=((b&2)>>1);return(c);}int tranoutput(int a,int b) /*状态从a到b时卷积码输出的符号*/{int c,s1,s2;s1=(a&1)^((a&2)>>1)^((b&2)>>1);s2=(a&1)^((b&2)>>1);c=(s1<<1)|s2;return(c);}////////////////////////////////////////////////////////////////////////////维特比译码///////////////////////////////////////////////////////////////////////////////void viterbi(int initialstate, /*定义解码器初始状态*/int *viterbiinput, /*解码器输入码字序列*/int *viterbioutput /*解码器输出码字序列*/){struct sta /*定义网格图中每一点为一个结构体,其元素包括*/{int met; /*转移到此状态累计的度量值*/int value; /*输入符号*/struct sta *last; /*及指向前一个状态的指针*/};struct sta state[4][N];struct sta *g,*head;int i,j,p,q,t,r,u,l;for(i=0;i<4;i++) /* 初始化每个状态的度量值*/for(j=0;j<N;j++)state[i][j].met=0;for(l=0;l<4;l++){state[l][0].met=trandistance(*viterbiinput,initialstate,l);state[l][0].value=traninput(initialstate,l);state[l][0].last=NULL;}viterbiinput++; /*扩展第一步幸存路径*/for(t=1;t<N;t++){for(p=0;p<4;p++){state[p][t].met=state[0][t-1].met+trandistance(*viterbiinput,0,p);state[p][t].value=traninput(0,p);state[p][t].last=&state[0][t-1];for(q=0;q<4;q++){if(state[q][t-1].met+trandistance(*viterbiinput,q,p)<state[p][t].met){state[p][t].met=state[q][t-1].met+trandistance(*viterbiinput,q,p);state[p][t].value=traninput(q,p);state[p][t].last=&state[q][t-1];}}}viterbiinput++;} /*计算出剩余的幸存路径*/r=state[0][N-1].met; /*找出n步后度量值最小的状态准备回溯路由*/g=&state[0][N-1];for(u=N;u>0;u--) /*向前递归的找出最大似然路径*/{*(viterbioutput+(u-1))=g->value;g=g->last;}/* for(u=0;u<8;u++)*(viterbioutput+u)=state[u][2].met; */ /*此行程序可用于检测第n列的度量值*/}void decode(unsigned int *input, int *output,int n){int viterbiinput[100];int j;for(j=0;j<n+2;j++){viterbiinput[j]=(input[j*2]<<1)|input[j*2+1];}viterbi(0,viterbiinput,output);}void main(){unsigned intencodeinput[100],wrong[10]={0,0,0,0,0,0,0,0,0,0},encodeoutput[100];int n=5,i,m,j=0,decodeinput[100],decodeoutput[100];randomize();for(i=0; i<n; i++)encodeinput[i]=rand()%2;encodeinput[n]= encodeinput[n+1]=0;encode(encodeoutput,encodeinput,n+2,0);printf("the input of encoder is :\n"); //信息源输入的信息码(随机产生)for(i=0;i<n; i++)printf("%2d",encodeinput[i]);printf("\n");printf("the output of encoder is :\n"); //编码之后产生的卷积码for(i=0;i<(n+2)*2;i++){printf("%2d",encodeoutput[i]);if(i%20==19)printf("\n");}printf("\n");printf("please input the number of the wrong bit\n"); //信道传输收到干扰而产生的错误码scanf("%d",&m);printf("please input the positions of the wrong bit(0-9)\n"); for(i=0;i<m;i++){scanf("%d",&wrong[m]);if(encodeoutput[wrong[m]]==0)encodeoutput[wrong[m]]=1;elseencodeoutput[wrong[m]]=0;}printf("the input of decoder is :\n");for(i=0;i<(n+2)*2;i++){printf("%2d",encodeoutput[i]);if(i%20==19)printf("\n");}printf("\n");decode(encodeoutput,decodeoutput,n+2);printf("the output of decoder is :\n");for(i=0;i<n;i++)printf("%2d",decodeoutput[i]);printf("\n");for(i=0;i<n;i++){if(encodeinput[i]!=decodeoutput[i])j++;}printf("the number of incorrect bit is:%d\n",j);}四、实验总结(1)了解实验原理,分析实验所占数组变量很重要,也是相对考虑较多的;(2)对于读写文件,通过本实验更加熟悉;(3)记录实验程序最佳路径是本实验的难点;。

相关文档
最新文档