⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serial.v

📁 清华大学verilog hdl源码例子
💻 V
字号:
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
//                                                       ;;
//              ICDIY - 开放矽智财                       ;;
//                                                       ;;
//      矽智财名称      : RS-232串列介面                 ;;
//      程式档名称      : serial.v                       ;;
//      实验板平台      : OPEN FPGA 3.0                  ;;
//      作者            : Albert Hu (albert@icdiy.com)   ;;
//                                                       ;;
//      (C) Copyright 2002, All Rights Reserved          ;;
//                                                       ;;
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

// 月/日/年     历史记录
// 09/05/02     开始

module  serial(

        reset,          // 重置讯号
        clock,          // 系统时脉,512KHz时约为 2404 bps
        data_in,data_out,
   //     data,           // 资料汇流排
        wr,             // 暂存器的写入控制讯号
        rd,             // 暂存器的读出控制讯号
        int_rx,         // 中断,表示收到资料
        int_tx,         // 中断,表示资料传送完成

        rx,             // 串列资料输入
        tx,             // 串列资料输出
        rts,            // 要求传送(Request To Send)
        cts             // 允许传送(Clear To Send)
);

//.........................................................

input           reset, clock, rd, wr;
//inout   [7:0]   data;
input   [7:0] data_in;
output  [7:0] data_out;

wire [7:0] data_in;
wire [7:0] data_out;

input           rx, cts;
output          tx, rts;
output          int_rx, int_tx;

//*********************************************************
//                  tx讯号的传送电路
//*********************************************************
//
// 在系统时脉为512KHz时,baud rate 约为 2404。
// 512KHz / 213 = 2403.76
// 4M / 416 =9600
// 可用到7200
//parameter baud1=8'd103;   //,212
//parameter mid_baud=8'd51; //105
parameter baud1 = 8'd77;  ///  9600 8'd155;
parameter mid_baud=8'd38;  /// 9600 8'd77

reg     [7:0]   tx_count;
wire            tx_reload = ( tx_count == baud1 );
wire       reset1=(tx_reload | reset);

always @( posedge clock or posedge reset1 )
        if( reset1 )             tx_count <= 8'b0;
       // else if( tx_reload )    tx_count <= 8'b0;
        else                    tx_count <= tx_count + 1;

// 8位元的资料加上1个start bit.............................

reg             cts_q;
reg     [3:0]   tx_bit;

//shift 的条件 
wire            tx_shift = cts_q & ( tx_count == 8'd0  )
                                 & ( tx_bit   <  4'd10 );

always @( posedge clock or posedge reset )
        if( reset )             tx_bit <= 4'd10;      //刚reset不会被shift
        else if( wr )           tx_bit <= 4'd0;
        else if( tx_shift )     tx_bit <= tx_bit + 1;

reg             tx;
reg     [8:0]   tx_buffer;

always @( posedge clock or posedge reset )
        if( reset )             tx <= 1;
        else if( tx_shift )     tx <= tx_buffer[0];

// 等待外部的cts配合流量控制...............................
//
// 8位元资料开始传送之後即不再检查cts,直到下一次传送为止。

wire            cts_reset = reset | wr | ( tx_bit == 4'd10 );

always @( posedge clock or posedge cts_reset )
        if( cts_reset ) cts_q <= 0;
        else            cts_q <= cts_q | ( ~cts );

//*********************************************************
//                资料暂存器的写入介面
//*********************************************************
//
// 8位元的资料加上1个start bit

always @( posedge clock )
        if( wr )
                tx_buffer <= { data_in, 1'b0 };  //data
        else if( tx_shift )
                tx_buffer <= { 1'b1, tx_buffer[8:1] };

// 资料传送完成後产生int_tx讯号,在新资料写入之後释放。

reg             int_tx;
wire            int_tx_reset = reset | wr;

always @( posedge clock or posedge int_tx_reset )
        if( int_tx_reset ) int_tx <= 0;
        else               int_tx <= ( tx_bit == 4'd10 );

//*********************************************************
//                rx讯号的取样与接收电路
//*********************************************************
//
// 侦测rx讯号的转态点,做为取样的同步。
// 在系统时脉为512KHz时,baud rate 约为 2404。
// 512KHz / 213 = 2403.76

//assign rts = 0;
 assign rts = cts;

reg             rx_q;

always @( posedge clock or posedge reset )
        if( reset )     rx_q <= 0;
        else            rx_q <= rx;

reg     [7:0]   sync_count;
wire            sync_reload = (    rx_q   & ( ~rx ) )
                            | ( ( ~rx_q ) &    rx )
                            | ( sync_count == baud1 );

always @( posedge clock or posedge reset )
        if( reset )             sync_count <= 8'd0;
        else if( sync_reload )  sync_count <= 8'd0;
        else                    sync_count <= sync_count + 1;

// 在讯号中点进行资料取样..................................
//
// 当start bit移到rx_buffer[0]时,重置rx_buffer。

reg     [8:0]   rx_buffer;
wire            sample =
                ( ~rx_buffer[0] ) | ( sync_count == mid_baud);//8'd106 );
wire    [8:0]   rx_shift = ( rx_buffer[0] ) ?
                { rx, rx_buffer[8:1] } : 9'b11111111_1;

always @( posedge clock or posedge reset )
        if( reset )             rx_buffer <= 9'b11111111_1;
        else if( sample )       rx_buffer <= rx_shift;

// 当start bit移到rx_buffer[8]时,表示8-bit资料接收完成,
// 将内容存放到rx_reg。

reg     [7:0]   rx_reg;

always @( posedge clock )
        if( ~rx_buffer[0] ) rx_reg <= rx_buffer[8:1];

//*********************************************************
//                资料暂存器的读取介面
//*********************************************************
//
// 侦测rd讯号的释放,做为中断讯号的重置。

reg             rd_q;

always @( posedge clock or posedge reset )
        if( reset )     rd_q <= 0;
        else            rd_q <= rd;
//data


assign data_out = ( rd ) ? rx_reg : 8'hzz;//8'hzz;

// 资料接收完成时产生int_rx讯号,在读取之後释放。

reg             int_rx;
wire            int_rx_reset = reset | ( ( ~rd_q ) & rd );

always @( posedge clock or posedge int_rx_reset )
        if( int_rx_reset )
                int_rx <= 0;
        else    int_rx <= int_rx | ( ~rx_buffer[0] );

//*********************************************************

endmodule

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -