uart-verilog HDL

接收模块:

`define VERIFY_EVEN 2'b00
`define VERIFY_ODD	2'b01
`define VERIFY_NONE 2'b10

module uart_rx(
	i_clk,		//系统时钟输入
	i_clk_rx,	//移位时钟输入
	i_rx_data,	//串行数据输入
	i_verify_mode,//校验模式(允许:奇校验、偶校验、无校验)输入
	i_rst_n,	//复位输入
	i_ce_n,		//允许传输输入
	i_clear_int_n,//清除中断输入
	o_rx_int,	//接收中断输出
	o_data	,	//数据输出,在中断有?时可被读取
	o_err		//传输出错标志位
);

	input i_clk;
	input i_clk_rx;
	input i_rx_data;
	input [1:0] i_verify_mode;
	input i_rst_n;
	input i_ce_n;
	input i_clear_int_n;
	output o_rx_int;
	output [7:0] o_data;
	output o_err;

	reg [7:0] r_data;
	reg [3:0] r_num;
	
	reg [1:0] r_verify_mode;
	reg r_err;	
	reg r_start;
	//写控制寄存器进程,确认何时开启传输
	always @(posedge i_clk) begin
		if(!i_rst_n | r_err) begin	//复位或传输发生错误则终止传输
			r_verify_mode <= `VERIFY_NONE;
			r_start <= 0;
		end else if(i_clk_rx && !i_rx_data && r_num == 0) begin	//收到起始位
			r_verify_mode <= i_verify_mode ;	//每次开始传输的时候确认校验方式
			r_start<= 1;
		end else if( i_rx_data && 					//已经收到停止位,停止传输
					((r_num == 9 && r_verify_mode == `VERIFY_NONE) ||
					(r_num ==  10 && (r_verify_mode == `VERIFY_EVEN || r_verify_mode == `VERIFY_ODD) ))
					) begin
			r_verify_mode <= `VERIFY_NONE;
			r_start <= 0;
		end
	end
	
	//逻辑连接 确定允许传输信号
	wire w_start ;
	assign w_start = r_start & ~i_ce_n ;
	
	always @ (posedge i_clk) begin
		if(!i_rst_n) begin
			r_num <= 0;
			r_data <= 0;
			r_err <= 0;
		end else if(w_start && i_clk_rx) begin
			r_num <= r_num + 1;
			case (r_num) 
				0 : begin  r_data[0] <= i_rx_data ; r_err <= 0 ; end
				1 : r_data[1] <= i_rx_data ;
				2 : r_data[2] <= i_rx_data ;
				3 : r_data[3] <= i_rx_data ;
				4 : r_data[4] <= i_rx_data ;
				5 : r_data[5] <= i_rx_data ;
				6 : r_data[6] <= i_rx_data ;
				7 : r_data[7] <= i_rx_data ;
				8 : casex(r_verify_mode) 		//核对校验位、若无校验则直接核对停止位
						`VERIFY_EVEN : r_err <=  ^r_data ^ i_rx_data ;
						`VERIFY_ODD  : r_err <=  ^r_data ^ i_rx_data ;
						`VERIFY_NONE : r_err <= ~ i_rx_data ;
						default 	 : r_err <= ~ i_rx_data ;
					endcase
				9 : r_err <= ~ i_rx_data | r_err ;//检测停止位
			endcase
		end else if((r_num == 9 && r_verify_mode == `VERIFY_NONE)  ||		//传输完毕
					(r_num == 10 && (r_verify_mode == `VERIFY_EVEN || r_verify_mode == `VERIFY_ODD) )) begin
			r_num <= 0;
		end
	end
	assign o_err = r_err ;
	
	reg [7:0] r_o_data;
	reg r_o_rx_int;
	always @ (posedge i_clk) begin
		if(!i_rst_n) begin
			r_o_data <= 0;
			r_o_rx_int <= 0;
		end else if((r_num == 9 && r_verify_mode == `VERIFY_NONE)  ||		//传输完毕
					(r_num == 10 && (r_verify_mode == `VERIFY_EVEN || r_verify_mode == `VERIFY_ODD) )) begin
			if(!r_err) begin
				r_o_data <= r_data;
				r_o_rx_int <= 1;
			end else begin
				r_o_data <= 'bz;
				r_o_rx_int <= 0;
			end
		end else if(!i_clear_int_n) begin	//手动清除中断标志
			r_o_rx_int <= 0;
			r_o_data <= 'bz;
		end 
	end
	assign o_rx_int = r_o_rx_int ;
	assign o_data = r_o_data ;
	
	
endmodule


 

接收模块测试向量:

module uart_rx_tb  ; 
 
  wire  [7:0]  o_data   ; 
  wire    o_rx_int   ; 
  wire    o_err   ; 
  
  reg    i_ce_n   ; 
  reg  [1:0]  i_verify_mode   ; 
  reg    i_clear_int_n   ; 
  reg    i_rst_n   ; 
  reg    i_clk   ; 
  reg    i_rx_data   ; 
  reg    i_clk_rx   ; 
  uart_rx  
   DUT  ( 
       .o_data (o_data ) ,
      .i_ce_n (i_ce_n ) ,
      .i_verify_mode (i_verify_mode ) ,
      .o_rx_int (o_rx_int ) ,
      .i_clear_int_n (i_clear_int_n ) ,
      .i_rst_n (i_rst_n ) ,
      .i_clk (i_clk ) ,
      .o_err (o_err ) ,
      .i_rx_data (i_rx_data ) ,
      .i_clk_rx (i_clk_rx ) ); 

	  
	initial begin
		i_ce_n = 1 ;
		i_clear_int_n = 1;
		i_clk = 0;
		i_clk_rx = 0;
		i_verify_mode = 0 ;
		i_rx_data = 0;
		i_rst_n = 0;
	#200
		i_rst_n = 1;
	#50 
		i_verify_mode = 2;
	#50
		i_ce_n = 0 ;

	end
	  
	reg [3:0] cnt;
	initial cnt = 0;
	reg r_tmp;
	always @ (negedge i_clk_rx) begin
		if(cnt == 0 && !o_err) i_rx_data = 0 ;	//发送起始位
		else if(cnt>0 && cnt < 9) i_rx_data = ({$random} % 2 )^ r_tmp; //发送随机数据
		else if(cnt == 9 || cnt == 10 ) i_rx_data = 1 ;		//发送停止位
		else i_rx_data = 1 ;//发送空闲位
		r_tmp = i_rx_data;
		if(cnt <= 20 && !o_err) cnt <= cnt + 1;
		else cnt <= 0;
		
	end
	
	//清中断标志位
	always @(posedge o_rx_int) begin
		#200
			i_clear_int_n = 0;
		#100
			i_clear_int_n = 1;
	end
	
	//清错误标志位
	always @(posedge o_err) begin
		#200
			i_rst_n = 0;
		#100
			i_rst_n = 1;
	end
	
	always #50 i_clk = ~ i_clk;
	always begin
		#400 i_clk_rx = 1;
		#100 i_clk_rx = 0;
	end

endmodule

接收模块功能仿真波形:


发送模块:

/*
Uart 发送模块
*/
module uart_tx(
	i_clk,		//系统时钟输入
	i_clk_tx,	//移位时钟输入
	i_data,		//数据输入,在i_start_n有效时务必保持稳定
	i_verify_mode,//校验模式(允许:奇校验、偶校验、无校验)输入
	i_rst_n,	//复位输入
	i_start_n,	//开始传输输入
	o_tx_data,	//串行数据输出
	o_tx_int	//发送中断输出
);

	input i_clk;
	input i_clk_tx;
	input i_rst_n;
	input i_start_n;
	input [7:0] i_data;
	input [1:0] i_verify_mode;
	output o_tx_data;
	output o_tx_int;
	
	
	`define VERIFY_EVEN 2'b00
	`define VERIFY_ODD	2'b01
	`define VERIFY_NONE 2'b1x
	
	reg [7:0] r_data;
	reg [1:0] r_verify_mode;
	reg [3:0] r_num;
	reg r_start;
	//写内部寄存器进程
	//Process generates start signal for transmission
	always @(posedge i_clk) begin
		if(!i_rst_n) begin
			r_data <= 0;
			r_start<= 0;
			r_verify_mode <= 0;
		end	else if(!i_start_n) begin
			r_data <= i_data;
			r_verify_mode <= i_verify_mode;
			r_start <= 1;
		end	else if(r_num == 11) begin
			r_start <= 0;
			r_verify_mode <= 'bx;
			r_data  <= 'bx;
		end
	end
	
	//逻辑连接,在i_start_n 有效电平消失后才产生有效开始信号(开始传输)
	//Logic connection ultimate gate signal for transmission start
	wire w_start1;
	assign w_start1 = r_start &  i_start_n ;
	
	//传输数据进程
	//Process send data 
	reg r_o_tx_data;
	always @(posedge i_clk) begin
		if(!i_rst_n) begin
			r_o_tx_data <= 1;
			r_num <= 0;
		end	else if(i_clk_tx && w_start1) begin
			r_num <= r_num + 1;
			case (r_num) 
				0 : r_o_tx_data <= 0;		//Start bit '0'//发送起始位0
				1 : r_o_tx_data <= r_data[0];
				2 : r_o_tx_data <= r_data[1];
				3 : r_o_tx_data <= r_data[2];
				4 : r_o_tx_data <= r_data[3];
				5 : r_o_tx_data <= r_data[4];
				6 : r_o_tx_data <= r_data[5];
				7 : r_o_tx_data <= r_data[6];
				8 : r_o_tx_data <= r_data[7];
				9 :							//发送校验位
					casex(r_verify_mode)
						`VERIFY_EVEN	: r_o_tx_data <= ~^ r_data ;	//偶校验 r_data各位同或输出
						`VERIFY_ODD		: r_o_tx_data <=  ^ r_data ;	//奇校验 r_data各位异或输出
						`VERIFY_NONE	: r_o_tx_data <= 1;				//无校验 提前发送停止位(仅相当于多消耗1个移位时钟周期)
						default 		: r_o_tx_data <= 1 ;
					endcase
				10: r_o_tx_data <= 1 ;		//End bit '1' //发送停止位1
				default : r_o_tx_data <= 1;
			endcase
		
		end else if(r_num == 11) r_num <= 0;
	
	end
	assign o_tx_data = r_o_tx_data ;
	
	
	//传输中断产生进程
	//Process generates interrupt signal for output
	reg r_o_tx_int;
	always @(posedge i_clk) begin
		if(!i_rst_n || (w_start1 && r_num != 11)) r_o_tx_int <= 0;
		else if( w_start1 && r_num == 11) r_o_tx_int <= 1;
	end
	assign o_tx_int = r_o_tx_int ;

endmodule


 

发送模块测试向量:

module uart_tx_tb  ; 

  wire    o_tx_data   ; 
   wire    o_tx_int   ; 
 
  reg    i_clk_tx   ; 
  reg    i_rst_n   ; 
  reg  [7:0]  i_data   ; 
  reg    i_clk   ; 
  reg 	[1:0]i_verify_mode;
  reg    i_start_n   ; 
  uart_tx  
   DUT  ( 
       .o_tx_int (o_tx_int ) ,
      .i_clk_tx (i_clk_tx ) ,
      .i_rst_n (i_rst_n ) ,
	  .i_verify_mode(i_verify_mode),
      .i_data (i_data ) ,
      .i_clk (i_clk ) ,
      .o_tx_data (o_tx_data ) ,
      .i_start_n (i_start_n ) ); 
	  
	  
	initial begin
		i_rst_n = 0;
		i_clk = 0;
		i_clk_tx = 0;
		i_start_n = 1;
		i_verify_mode = 'bz;
		i_data = 'bz;
		#50
			i_data = 8'd125 ;
			i_verify_mode = 2'b11;
		#400
			i_rst_n = 1 ;
		#50
			i_start_n = 0;
		#100
			i_start_n = 1;
			i_data = 8'bz;
	end
	
	//event newtrans;
	//always @(posedge i_clk)	if(o_tx_int) -> newtrans;
	
	//always @(newtrans) begin
	always @ (posedge o_tx_int) begin
		#400 ;
		i_data = {$random} % 256 ;
		i_verify_mode  = {$random} % 4;
		#50 
			i_start_n = 0;
		#100
			i_start_n = 1;
			i_data = 8'bz;
	end
	
	
	always #50 i_clk = ~ i_clk;
	always begin
		#400 i_clk_tx = 1;
		#100 i_clk_tx = 0;
	end
	
endmodule

发送模块功能仿真波形:


速度选择模块:

/*
	波特率产生公式
	Formula generates max cnt for specified bode rate
	Fosc = 50MHz
	2 *  MaxCnt * BodeRate = Fosc
	
	BodeRate 	MaxCnt	HalfCnt
		4800    5207	2603
		9600    2603	1301
		19200   1301	650
		115200  216		108

*/
`define PARA_MAXCNT 216
`define PARA_HALFCNT 108
module speedselect (i_ce_n, i_rst_n, i_clk, o_clk);
	input i_rst_n;
	input i_clk;
	input i_ce_n;

	output o_clk;
	
	reg [12:0] r_cnt;
	
	always @(posedge i_clk) begin
		if(!i_rst_n) begin r_cnt <= 0; end
		else if(!i_ce_n) begin
			r_cnt <= (r_cnt == `PARA_MAXCNT) ? 0 : r_cnt + 1 ;
		end
	end
	
	reg r_o_clk;
	always @(posedge i_clk) begin
		if( i_rst_n &&(!i_ce_n) && r_cnt == `PARA_HALFCNT ) r_o_clk <= 1;
		else r_o_clk <= 0;
	end
	assign o_clk = r_o_clk ;
	
endmodule


 

速度选择模块测试向量:

module speedselect_tb  ; 
 
  wire    o_clk   ; 
  reg    i_ce_n   ; 
  reg    i_clk   ; 
  reg    i_rst_n   ; 
  speedselect  
   DUT  ( 
       .o_clk (o_clk ) ,
      .i_ce_n (i_ce_n ) ,
      .i_clk (i_clk ) ,
      .i_rst_n (i_rst_n ) );
	  
initial begin
	i_ce_n = 1;
	i_clk = 0;
	i_rst_n = 0;
	#100
	i_ce_n = 0;
	#100
	i_rst_n = 1;
	

end

always #50 i_clk = ~ i_clk;


endmodule

速度选择模块功能仿真波形:

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sanzhong104204

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值