多努力就有多特殊(neverforever)——仌
目标
将串行输入的曼彻斯特码解码输出。
基础时钟:25MHz
复位:有无外部复位逻辑复位输入两种情况。
数据传输速率:5M bit/s
编码规则: “01”:1 “10”:0
辅助逻辑信号:故障定位报警。
分析
由时钟频率和数据传输速率可知,1bit数据持续5个clock,每2bit数据译码一次。对串行输入的数据i_data进行采样时,尽量在数据的中间采样。使用一个模10计数器cnt,每计数5个采样一次,即1bit,每计数10个译码一次。
如何知道从i_data的哪一位,即什么时候开始译码?
需要检测译码起始位,比如0110,两个1后面必为0,或者两个0后面必为1,因此可通过检测到连续2bit的0或者1来确定起始译码位,即连续的两次采样的i_data相同,则译码信号ready_sig置1。这里可以将连续的两次采样存在一个2bit寄存器tmp里。
如何尽量在数据的中间取值?
需要写完testbench仿真后调节计数器采样的位置,实际工程中会给出同步的数据译码位。
异步复位,同步释放 || 上电复位
有的会会有外部复位按钮,但外部复位是异步的,释放时存在亚稳态问题,因此需要通过寄存器的2级延迟完成同步释放解决亚稳态问题。
当没有外部复位按钮时,就需要上电自动复位,即FPGA上电之后延迟一定时间后自动复位,即初始化,从而使器件正常工作。其与外部复位是或的关系。
记得点赞收藏哦,异步复位同步释放和上电复位是你早晚要解决的问题。而且其他地方你找不到两者或关系的代码。
代码及注释
module manchester_decode(
input i_rst ,
input i_clk ,//25MHz
output rst_sync_out ,//外部复位
output reg [2:0] cntr_rst ,//上电复位
output reg rst_sys ,//external reset || power—on reset
input i_data ,
output reg [3:0] cnt , //计数器
output reg clk_samp , //采样脉冲
output reg conv_sig , //译码脉冲
output reg [1:0] tmp , //存储连续2bit的i_data
output reg ready_sig , //译码开始信号
output reg fail_sig , //误码信号
output reg o_data
);
parameter cntr_bit1 = 3; //第一个采样脉冲
parameter cntr_bit2 = 8; //第二个采样脉冲
parameter cntr_rst_max = 7; //上电复位的延迟时间
/* external reset:asynchronous reset and synchronous release */
rst_sync rst_sync0(
.i_clk ( i_clk ),
.rst_async ( i_rst ),
.rst_sync ( rst_sync_out )
);
/* external reset || power—on reset */
always@(posedge i_clk)
begin
if(rst_sync_out)
begin
rst_sys <= 1;
cntr_rst <= 0;
end
else if(cntr_rst<cntr_rst_max)
begin
rst_sys <= 1;
cntr_rst <= cntr_rst + 1;
end
else
rst_sys <= 0;
end
/* sampling pulse: clk_samp , decode pulse:conv_sig */
always@(posedge i_clk)
begin
if(rst_sys)
begin
clk_samp <= 0;
conv_