📄 serial.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 + -