ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于FPGA的曼彻斯特编码器设计:VHDL实现与QUARTUS II验证

基于FPGA的曼彻斯特编码器设计:VHDL实现与QUARTUS II验证 简介这份毕业设计文档面向电子信息工程、通信工程等专业的本科生与FPGA初学者围绕基于FPGA的曼彻斯特编码器设计展开可用于课程设计参考、毕设选题借鉴或数字通信编码的学习。文档完整呈现了课题背景与意义、曼彻斯特编码理论与方法、M序列原理与实现并将系统划分为分频、M序列产生和编码三个模块分频模块采用上下沿同时计数实现输入时钟的5分频M序列模块调用QUARTUS II的LPM模块以原理图方式设计编码模块则用VHDL语言编写最终联调仿真后下载至ALTERA DEII平台实现10MHz速率的编码输出。资源包内含1个doc文档约740KB结构完整、图文并茂适合作为毕设写作与工程实现的对照材料。目前已有298人学习可帮助读者快速理解自定时码的同步优势、伪随机序列生成思路以及FPGA模块化设计流程。1. 从一条串行链路的时钟恢复说起做 FPGA 通信接口的人迟早会撞上同一个问题单根信号线上传数据接收端怎么知道每一位的边界在哪。如果直接发 NRZ 码连续几个 0 或 1 会让接收端的时钟恢复电路失去参考位同步漂移采样点跑偏。曼彻斯特编码就是为这个场景生的——它把时钟信息嵌进数据本身每个比特周期中间必有一次电平跳变上升沿代表一种逻辑值下降沿代表另一种。代价是带宽翻倍换来的是接收端可以用一个简单的边沿检测就把位时钟抠出来。这篇讲的是基于 FPGA 的曼彻斯特编码器设计属于典型的数字逻辑课程设计和毕业作品选题。它不复杂但麻雀虽小涉及编码规则、状态机、时钟分频、复位同步、Testbench 验证、时序约束最后还要在 QUARTUS II 里综合到 DE 系列开发板上用 SignalTap 抓波形。用 VHDL 写还是 Verilog 写都行本文以 VHDL 为主线因为多数高校课程用 VHDL 教学QUARTUS II 对两者的支持没有差别。适合正在做课设、毕设或者第一次接触 FPGA 串行接口的人。2. 曼彻斯特编码规则与 FPGA 实现选型2.1 两种编码约定IEEE 802.3 与 G.E. Thomas曼彻斯特编码有两种约定差别就在0和1对应哪种跳变。IEEE 802.3 以太网用的是低到高跳变表示逻辑 1高到低跳变表示逻辑 0。G.E. Thomas 约定正好反过来。两种都对关键是收发两端必须一致。做课设时老师一般不会指定我建议选 IEEE 802.3因为查资料时以太网相关的参考多遇到问题好对照。一个比特周期被分成两半。以 802.3 为例发逻辑 1前半周期为低后半周期为高发逻辑 0前半周期为高后半周期为低。这样每个比特周期中点必然有一次跳变接收端检测这个跳变就能对齐位边界。2.2 为什么用状态机而不是纯组合逻辑最直觉的写法是用一个 2 倍波特率的时钟组合逻辑直接输出。但这样有两个问题一是输出会随输入异步变化产生毛刺二是复位和使能不好控制。常见做法是用一个有限状态机在 2 倍频时钟下跑每个状态停留半个比特周期。状态定义如下表状态含义输出电平IDLE空闲高空闲电平S0_L发送 0 的前半周期高S0_H发送 0 的后半周期低S1_L发送 1 的前半周期低S1_H发送 1 的后半周期高状态机在 2 倍波特率时钟驱动下每来一个时钟沿切换一次状态输出随之变化。这样每个比特占两个时钟周期中点跳变自然产生。2.3 时钟分频与波特率参数假设系统时钟 50 MHz目标波特率 1 Mbps那么 2 倍频时钟需要 2 MHz分频系数为 50M / 2M 25。分频器用一个计数器实现-- 时钟分频50MHz - 2MHz分频系数 25 process(clk, rst_n) variable cnt : integer range 0 to 24; begin if rst_n 0 then cnt : 0; clk_2m 0; elsif rising_edge(clk) then if cnt 24 then cnt : 0; clk_2m not clk_2m; -- 翻转产生 2MHz else cnt : cnt 1; end if; end if; end process;这里用变量而非信号做计数器避免每次赋值产生一个时钟延迟。分频系数 系统时钟频率 / (2 × 波特率)。改波特率时只改这个常数即可。注意clk_2m是分频出来的时钟直接用它驱动状态机在 QUARTUS II 里会报时钟不是全局时钟的警告后面时序约束章节会讲怎么处理。提示分频系数必须是整数。如果系统时钟和波特率不能整除需要用小数分频或换系统时钟频率否则波特率会有误差长时间传输会累积偏移。3. VHDL 编码器核心模块与 Testbench 验证3.1 实体声明与端口定义先定接口。编码器需要系统时钟、复位、一个数据有效信号、一个待发送比特输出曼彻斯特码流和一个发送完成指示。library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity manchester_encoder is port ( clk : in std_logic; -- 系统时钟 50MHz rst_n : in std_logic; -- 低有效复位 din : in std_logic; -- 待编码比特 din_vld : in std_logic; -- 输入有效 dout : out std_logic; -- 曼彻斯特码输出 dout_vld : out std_logic -- 输出有效 ); end manchester_encoder;端口命名用_n后缀表示低有效复位这是业界惯例。din_vld用来握手只有它为高时din才被采样避免空闲时误编码。3.2 状态机实现与关键信号架构体里放分频器、状态机和输出寄存器。核心状态机如下architecture rtl of manchester_encoder is signal clk_2m : std_logic; signal state : std_logic_vector(1 downto 0); constant IDLE : std_logic_vector(1 downto 0) : 00; constant S0_L : std_logic_vector(1 downto 0) : 01; constant S0_H : std_logic_vector(1 downto 0) : 10; constant S1_L : std_logic_vector(1 downto 0) : 11; signal dout_r : std_logic; begin -- 分频进程略见 2.3 节 process(clk_2m, rst_n) begin if rst_n 0 then state IDLE; dout_r 1; dout_vld 0; elsif rising_edge(clk_2m) then case state is when IDLE dout_r 1; if din_vld 1 then if din 0 then state S0_L; else state S1_L; end if; dout_vld 1; end if; when S0_L dout_r 1; -- 0 的前半周期为高 state S0_H; when S0_H dout_r 0; -- 0 的后半周期为低 state IDLE; dout_vld 0; when S1_L dout_r 0; -- 1 的前半周期为低 state S1_H; when S1_H dout_r 1; -- 1 的后半周期为高 state IDLE; dout_vld 0; when others state IDLE; end case; end if; end process; dout dout_r; end rtl;状态机在clk_2m上升沿切换。IDLE 时输出保持高电平收到有效数据后根据din进入对应分支。每个数据比特占两个clk_2m周期即一个比特周期。dout_vld在发送期间拉高方便下游模块判断何时采样。注意这里din是在clk_2m域采样的如果din来自系统时钟域需要先做跨时钟域同步否则会有亚稳态风险。简单做法是打两拍。3.3 Testbench 编写与波形检查验证是毕设里最容易糊弄也最该认真做的部分。写一个 Testbench给几个典型序列全 0、全 1、交替 0101、随机序列。-- Testbench 片段 stim_proc: process begin rst_n 0; wait for 100 ns; rst_n 1; wait for 50 ns; -- 发送 0 din 0; din_vld 1; wait for 1000 ns; -- 1Mbps 下 1 比特 1000ns -- 发送 1 din 1; wait for 1000 ns; -- 发送 0 din 0; wait for 1000 ns; din_vld 0; wait; end process;在 ModelSim 里跑这个 Testbench观察dout波形。发 0 时应该看到先高后低发 1 时先低后高每个比特周期中点有跳变。如果波形不对先查分频系数对不对再查状态机有没有卡在某个状态。常见错误是复位没接好状态机停在 IDLE 不动。4. QUARTUS II 综合、引脚分配与 SignalTap 抓波形4.1 工程建立与综合设置打开 QUARTUS II新建工程选对器件型号。DE 系列开发板常见的是 Cyclone IV EP4CE 系列具体型号看板子上的丝印。工程建好后把 VHDL 文件加进去顶层实体设为manchester_encoder。综合前检查两处设置一是Assignments - Settings - Compiler Settings里优化目标选Balanced课设不需要面积优先二是EDA Tool Settings - Simulation里选 ModelSim路径指对。综合后看 Compilation Report 里的 Warning重点看有没有时钟不是全局时钟和组合逻辑环路。4.2 引脚分配与下载引脚分配在Assignments - Pin Planner里做。至少分配四个系统时钟、复位、数据输入、编码输出。时钟引脚必须接开发板上的专用时钟输入脚不能随便选普通 IO否则时钟质量差。信号方向分配建议clk输入专用时钟输入引脚rst_n输入按键引脚din输入拨码开关或按键dout输出LED 或扩展 IO分配完重新综合然后打开 Programmer 下载。下载器用 USB-Blaster 兼容的即可。下载后如果 LED 没反应先确认复位按键有没有松开再看时钟引脚分配对不对。4.3 用 SignalTap 抓内部波形板级调试最有效的手段是 SignalTap。在 QUARTUS II 里打开Tools - SignalTap Logic Analyzer添加要观察的信号state、dout_r、din、din_vld。采样时钟选clk_2m采样深度设 1K 够用。设置触发条件为din_vld上升沿这样能抓到一次完整发送过程。下载后按复位然后拨动输入开关SignalTap 会捕获波形。对照 3.3 节的预期波形检查如果state跳转顺序不对说明状态机逻辑有问题如果dout_r有毛刺检查是不是用了组合逻辑输出。提示SignalTap 会占用片上 RAM采样深度别设太大否则综合可能报资源不够。调试完记得在综合前把 SignalTap 文件移除不然会一直占资源。5. 时序约束、亚稳态处理与编码器进阶技巧5.1 给分频时钟加时序约束分频出来的clk_2m不是全局时钟QUARTUS II 默认按普通信号处理时序分析不会覆盖它驱动的逻辑。正确做法是在 SDC 文件里加约束# 创建分频时钟约束 create_generated_clock -name clk_2m -source [get_ports clk] \ -divide_by 25 [get_pins clk_div|clk_2m_reg]-divide_by 25对应分频系数。加了这条约束后TimeQuest 才会分析clk_2m域的建立保持时间。如果报告有违例说明分频逻辑或状态机路径太长需要插流水线或降低波特率。5.2 输入信号的亚稳态处理din如果来自异步源比如外部按键或另一块板子直接进clk_2m域采样会有亚稳态。标准做法是打两拍同步process(clk_2m, rst_n) begin if rst_n 0 then din_sync1 0; din_sync2 0; elsif rising_edge(clk_2m) then din_sync1 din; din_sync2 din_sync1; end if; end process;用din_sync2替代原来的din参与状态机判断。两拍同步能把亚稳态概率降到可忽略代价是两个时钟周期延迟对编码器功能没影响。5.3 从编码器扩展到完整收发链路编码器只是发送端。要做完整链路还需要接收端解码器检测边沿、恢复位时钟、采样中点、还原数据。解码器可以用一个边沿检测电路加一个计数器实现计数器在边沿到来时清零计到半个比特周期时采样。收发两端联调时建议先用同一块板子回环测试把dout直接接到解码器输入确认编解码一致后再上外部链路。另一个实用技巧是加一个发送 FIFO。当上层数据速率不均匀时FIFO 能缓冲数据编码器按固定波特率从 FIFO 取数避免上层等待。FIFO 深度根据上层突发长度定一般 16 到 64 深够用。用 QUARTUS II 的 MegaWizard 生成一个同步 FIFO接在编码器前面即可。本文还有配套的精品资源点击获取
返回列表