当前位置: 代码迷 >> 综合 >> verilog实现串行通讯协议(serial communications protocols)
  详细解决方案

verilog实现串行通讯协议(serial communications protocols)

热度:86   发布时间:2023-12-15 11:30:20.0

此博客为个人博客,不涉及商业用途,仅提供学习参考,内容均来自个人原创以及互联网转载和摘录。
此博客上带有原创标识的文章、图片、文件等,未经本人允许,不得用于商业用途以及传统媒体。
本文首发于CSDN,版权所有,禁止转载。
如需转载,请在评论区留言或私信申请,经同意后可转载,否则属于侵权行为

原博客链接:https://blog.csdn.net/qq_38305370
原博主昵称:城外南风起
————————————————

最近在做HDLBits的串行通讯协议(serial communications protocols)部分。记录在此。

目录

  • Serial receiver
  • Serial receiver and datapath
  • Serial receiver with parity checking

Serial receiver

原题目:

In many (older) serial communications protocols, each data byte is sent along with a start bit and a stop bit, to help the receiver delimit bytes from the stream of bits. One common scheme is to use one start bit (0), 8 data bits, and 1 stop bit (1). The line is also at logic 1 when nothing is being transmitted (idle).

Design a finite state machine that will identify when bytes have been correctly received when given a stream of bits. It needs to identify the start bit, wait for all 8 data bits, then verify that the stop bit was correct. If the stop bit does not appear when expected, the FSM must wait until it finds a stop bit before attempting to receive the next byte.

波形demo:

在这里插入图片描述
本题实现时设置了12个状态,分别为8个位状态BIT0至BIT7,4个描述状态DONE、STOP、IDLE、ERROR。
在波形中标注如下:

在这里插入图片描述

需要明确的逻辑是:当前的状态和当前的in没有关系,只和当前周期的上升沿时刻的in信号以及前一个状态有关。这里没有START状态,因为只要在BIT0状态前,接收器就是空转(IDLE)状态,不需要进行区分。

实现代码:

module top_module(input clk,input in,input reset,    // Synchronous resetoutput done
); parameter	BIT0 = 4'b0000, BIT1 = 4'b0001, BIT2 = 4'b0010, BIT3 = 4'b0011, BIT4 = 4'b0100, BIT5 = 4'b0101, BIT6 = 4'b0110, BIT7 = 4'b0111,DONE = 4'b1000, STOP = 4'b1001, IDLE = 4'b1010, ERROR = 4'b1011;reg [3:0] state, next_state;// State transition logic (combinational)always @(*) begin// State transition logiccase(state)IDLE: next_state = in ? IDLE : BIT0;BIT0: next_state = BIT1;BIT1: next_state = BIT2;BIT2: next_state = BIT3;            BIT3: next_state = BIT4;BIT4: next_state = BIT5;BIT5: next_state = BIT6;BIT6: next_state = BIT7;BIT7: next_state = STOP;STOP: next_state = in ? DONE : ERROR;ERROR: next_state = in ? IDLE : ERROR;DONE: next_state = in ? IDLE : BIT0;default: next_state = IDLE;endcaseend// State flip-flops (sequential)always @(posedge clk) beginif(reset) beginstate <= IDLE;endelse begin            state <= next_state;            endendassign done = (state == DONE);endmodule

Serial receiver and datapath

原题目:

Now that you have a finite state machine that can identify when bytes are correctly received in a serial bitstream, add a datapath that will output the correctly-received data byte. out_byte needs to be valid when done is 1, and is don’t-care otherwise.

Note that the serial protocol sends the least significant bit first.

波形demo见题目链接。从波形可以看出数据遵循LSB传输。

本题只是在Serial receiver的基础上加上了数据输出。

与verilog实现鼠标协议PS/2 mouse protocol的实现方法类似。注意在时序逻辑中获取数据即可。

此处给出代码:

module top_module(input clk,input in,input reset,    // Synchronous resetoutput [7:0] out_byte,output done
); //parameter	BIT0 = 4'b0000, BIT1 = 4'b0001, BIT2 = 4'b0010, BIT3 = 4'b0011, BIT4 = 4'b0100, BIT5 = 4'b0101, BIT6 = 4'b0110, BIT7 = 4'b0111,DONE = 4'b1000, STOP = 4'b1001, IDLE = 4'b1010, ERROR = 4'b1011;reg [3:0] state, next_state;// State transition logic (combinational)always @(*) begin// State transition logiccase(state)IDLE: next_state = in ? IDLE : BIT0;BIT0: next_state = BIT1;BIT1: next_state = BIT2;BIT2: next_state = BIT3;            BIT3: next_state = BIT4;BIT4: next_state = BIT5;BIT5: next_state = BIT6;BIT6: next_state = BIT7;BIT7: next_state = STOP;STOP: next_state = in ? DONE : ERROR;ERROR: next_state = in ? IDLE : ERROR;DONE: next_state = in ? IDLE : BIT0;default: next_state = IDLE;endcaseend// State flip-flops (sequential)reg bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7;always @(posedge clk) beginif(reset) beginstate <= IDLE;endelse begincase(state)BIT0: bit0 <= in;BIT1: bit1 <= in;BIT2: bit2 <= in;BIT3: bit3 <= in;BIT4: bit4 <= in;BIT5: bit5 <= in;BIT6: bit6 <= in;BIT7: bit7 <= in;endcasestate <= next_state;            endendassign done = (state == DONE);assign out_byte = {bit7, bit6, bit5, bit4, bit3, bit2, bit1, bit0};endmodule

Serial receiver with parity checking

原题目:

We want to add parity checking to the serial receiver. Parity checking adds one extra bit after each data byte. We will use odd parity, where the number of 1s in the 9 bits received must be odd. For example, 101001011 satisfies odd parity (there are 5 1s), but 001001011 does not.

Change your FSM and datapath to perform odd parity checking. Assert the done signal only if a byte is correctly received and its parity check passes. Like the serial receiver FSM, this FSM needs to identify the start bit, wait for all 9 (data and parity) bits, then verify that the stop bit was correct. If the stop bit does not appear when expected, the FSM must wait until it finds a stop bit before attempting to receive the next byte.

You are provided with the following module that can be used to calculate the parity of the input stream (It’s a TFF with reset). The intended use is that it should be given the input bit stream, and reset at appropriate times so it counts the number of 1 bits in each byte.

Note that the serial protocol sends the least significant bit first, and the parity bit after the 8 data bits.

波形demo见题目链接。

本题只是在Serial receiver and datapath的基础上加上了奇校验。所以需在BIT7后增加一个校验状态VER,在VER状态时利用异或检验1的奇偶个数。

实现代码:

module top_module(input clk,input in,input reset,    // Synchronous resetoutput [7:0] out_byte,output done
); //// Modify FSM and datapath from Fsm_serialdataparameter	BIT0 = 4'b0000, BIT1 = 4'b0001, BIT2 = 4'b0010, BIT3 = 4'b0011, BIT4 = 4'b0100, BIT5 = 4'b0101, BIT6 = 4'b0110, BIT7 = 4'b0111,DONE = 4'b1000, STOP = 4'b1001, IDLE = 4'b1010, ERROR = 4'b1011, VER = 4'b1100;reg [3:0] state, next_state;    // State transition logic (combinational)always @(*) begin// State transition logiccase(state)IDLE: next_state = in ? IDLE : BIT0;BIT0: next_state = BIT1;BIT1: next_state = BIT2;BIT2: next_state = BIT3;            BIT3: next_state = BIT4;BIT4: next_state = BIT5;BIT5: next_state = BIT6;BIT6: next_state = BIT7;BIT7: next_state = VER;VER: next_state = STOP;STOP: next_state = in ? DONE : ERROR;ERROR: next_state = in ? IDLE : ERROR;DONE: next_state = in ? IDLE : BIT0;default: next_state = IDLE;endcaseend// State flip-flops (sequential)reg bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7,odd;always @(posedge clk) beginif(reset) beginstate <= IDLE;endelse begin            case(state)BIT0: bit0 <= in;BIT1: bit1 <= in;BIT2: bit2 <= in;BIT3: bit3 <= in;BIT4: bit4 <= in;BIT5: bit5 <= in;BIT6: bit6 <= in;BIT7: bit7 <= in;VER: odd <= ^out_byte[7:0]^in;endcase            state <= next_state;            endendassign done = (state == DONE && odd);assign out_byte = {bit7, bit6, bit5, bit4, bit3, bit2, bit1, bit0};// New: Add parity checking.endmodule

————————————————
感谢您的阅读,如果您有收获,请给我一个三连吧!
如果您觉得这还不够,可以点击 打赏 按钮,告诉我: 你币有了!

  相关解决方案