Verilog 的UART实现(一)

因为后面有项目需要实现CPLD和FPGA的UART功能,所以这里记录了最近尝试开发的UART通讯的功能。

基本的思想是:通过CPU和CPLD的进行UART通讯,能够配置和dumpCPLD 的信息。

先上TOP层代码

module testcpld
(
	//input 		  a,
	input 		  rst_n,
	input        x_clk,
	output reg [1:0]   led,
	input rs232_rx,
	output rs232_tx
	
);

 localparam  TIME1MHZ_DIV     = 40000_000; 
  localparam  TIME1MHZ_DIV2     = 40000_000; 

//mypll __ (.CLKI( ), .CLKOP( ));


 reg[1:0]  led_temp=2'b10;
 reg[1:0]  led_temp1;
 wire sys_clk;
 assign	sys_clk =x_clk;
 //defparam OSCH_inst.NOM_FREQ = "38.00";
//OSCH OSCH_inst( 
     //.STDBY(1'b0), // 0=Enabled, 1=Disabled // also Disabled with Bandgap=OFF
	 //.OSC(sys_clk),
	 //.SEDSTDBY()
	 //); // this signal is not required if not // using SED
	 
	 
	wire rx_en,tx_en;

wire [7:0] rx_d,tx_d;
wire [3:0] rx_num,tx_num;
wire rx_sel_data,tx_sel_data;	
	 
reg baudset=1;	 
	


bps_rx bps_rx1(
    .sys_clk (sys_clk),
    .rst_n(rst_n), 
    .rx_en(rx_en),    //input 
    .baudset(baudset),    //input           	
    .rx_num(rx_num),        //output 
    .rx_sel_data(rx_sel_data)   //output 
    );
	 
bps_tx bps_tx1(
    .sys_clk (sys_clk),
    .rst_n(rst_n), 
    .tx_en(tx_en),    //input
    .baudset(baudset),      //input         	
    .tx_num(tx_num),         //output 
    .tx_sel_data(tx_sel_data)  //output 
    );
	 

uart_rx uart_rx1(
    .sys_clk (sys_clk),
    .rst_n(rst_n), 
	.uart_rx(rs232_rx),    //input
	.rx_num(rx_num),        //input
	.rx_sel_data(rx_sel_data),  //input
    .rx_en(rx_en),             //output
	.tx_en(tx_en),             //output
	.rx_d(rx_d)                //output

);

	uart_tx uart_tx1(
    .sys_clk (sys_clk),
    .rst_n(rst_n), 
	.uart_tx(rs232_tx),         //output
	.tx_num(tx_num),         //input
	.tx_sel_data(tx_sel_data), //input
	.tx_d(rx_d)               //input

); 
	 
	 always @(rx_d)
	
	case(rx_d)
	8'h31:
	begin
       	  // led = 2'b01;   
           led_temp<=2'b01; 
	end
	8'h32:
	begin
       	   //led = 2'b10; 
		   led_temp<=2'b10; 
	end  
	8'h41:
	begin
        	//   led = 2'b00; 
			   led_temp<=2'b00; 
	end  
	8'h61:
	begin
      	 //  led = 2'b11;
		   led_temp<=2'b11; 
	end  
	
	default:
	     led_temp<=led_temp1;
	
      	 
	endcase
	 
	 always @(posedge sys_clk or negedge rst_n)
	begin
    	if(rst_n==1'b0)
		
    		led	<= 2'b0;
    	else 
    	    begin
			led<=led_temp;
			led_temp1<=led_temp;
    	    end
    end
	 


endmodule

上rx的波特率设置代码


module bps_rx(
    input               sys_clk,
    input               rst_n, 
    input               rx_en,    
    input            baudset,              	
    output reg [3:0]    rx_num,
    output reg          rx_sel_data

);

reg [12:0]bsp_div;
reg [12:0]bsp_div_2;
reg flag;


    always @(baudset)
	begin 
	case(baudset)
	0:
	begin
       bsp_div    <= 13'd5208;
       bsp_div_2  <= 13'd2604;
	end
	1:
	begin
       bsp_div    <= 13'd434;
       bsp_div_2  <= 13'd217;
	end  
	
	default:
	begin
       bsp_div    <= 13'd5208;
       bsp_div_2  <= 13'd2604;
	end
	endcase
	
	end
	
	always @(posedge sys_clk or negedge rst_n)
	begin
    	if(rst_n==1'b0)
		
    		flag	<= 0;
    	else if(rx_en==1)
		   flag	<= 1;
		else if (rx_num == 4'd10)
    	    flag	<= 0;
    	
    end
	
	reg [12:0]  cnt;
	
	always @(posedge sys_clk or negedge rst_n)
	begin
    	if(rst_n==1'b0)
		
    		cnt	<= 13'd0;
    	else if (cnt<bsp_div && flag)
		   cnt	<= cnt+1'b1;
		else 
    	    cnt	<= 13'd0;
    	
    end
	
	always @(posedge sys_clk or negedge rst_n)
	begin
    	if(rst_n==1'b0)
		
    		rx_num	<= 4'd0;
    	else if (rx_sel_data && flag)
		   rx_num	<= rx_num+1'b1;
		else if (rx_num==4'd10)
    	    rx_num	<= 4'd0;
    	
    end
	
	
	always @(posedge sys_clk or negedge rst_n)
	begin
    	if(rst_n==1'b0)
		
    		rx_sel_data	<= 1'b0;
    	else if (cnt==bsp_div_2)
		   rx_sel_data	<= 1'b1;
		else 
    	    rx_sel_data	<= 1'b0;
    	
    end
	
	endmodule
	

TX的波特率设置代码


module bps_tx(
    input               sys_clk,
    input               rst_n, 
    input               tx_en,    
    input            baudset,              	
    output reg [3:0]    tx_num,
    output reg          tx_sel_data

);

reg [12:0] bsp_div,bsp_div_2;
reg flag;


    always @(baudset)
	begin 
	case(baudset)
	0:
	begin
       bsp_div    <= 13'd5208;
       bsp_div_2  <= 13'd2604;
	end   
	1:
	begin
       bsp_div    <= 13'd434;
       bsp_div_2  <= 13'd217;
	end   
	default:
	begin
       bsp_div    <= 13'd5208;
       bsp_div_2  <= 13'd2604;
	end
	endcase
	
	end
	
	always @(posedge sys_clk or negedge rst_n)
	begin
    	if(rst_n==1'b0)		
    		flag	<= 0;
    	else if (tx_en)
		   flag	<= 1;
		else if (tx_num ==4'd10)
    	    flag	<= 0;    	
    end
	
	reg [12:0]  cnt;
	
	always @(posedge sys_clk or negedge rst_n)
	begin
    	if(rst_n==1'b0)
		
    		cnt	<= 13'd0;
    	else if (cnt<bsp_div && flag)
		   cnt	<= cnt+1'b1;
		else 
    	    cnt	<= 13'd0;
    	
    end
	
	always @(posedge sys_clk or negedge rst_n)
	begin
    	if(rst_n==1'b0)
    		tx_num	<= 4'd0;
    	else if (tx_sel_data && flag)
		   tx_num	<= tx_num+1'b1;
		else if (tx_num==4'd10)
    	    tx_num	<= 4'd0;
    end
	
	
	always @(posedge sys_clk or negedge rst_n)
	begin
    	if(rst_n==1'b0)
    		tx_sel_data	<= 1'b0;
    	else if (cnt==bsp_div_2)
		   tx_sel_data	<= 1'b1;
		else 
    	    tx_sel_data	<= 1'b0;
    end
	
	endmodule
	

rx代码


module uart_rx(
    input               sys_clk,
    input               rst_n, 
    input               uart_rx,   
    input	[3:0]       rx_num, 
	input               rx_sel_data,
	output           rx_en,
	output reg          tx_en,             	
    output reg [7:0]    rx_d
);

reg in_data_1,in_data_2;


always @(posedge sys_clk or negedge rst_n)
	begin
    	if(rst_n==1'b0)
		begin
    		in_data_1	<= 1'b1;
			in_data_2	<= 1'b1;
	    end
    	else
		begin
    		in_data_1	<= uart_rx;
			in_data_2	<= in_data_1;
	    end
    end

assign rx_en=in_data_2&(~in_data_1);

reg [7:0]  rx_d_r;

always @(posedge sys_clk or negedge rst_n)
	begin
    	if(rst_n==1'b0)
		begin
    		rx_d_r	<= 8'd0;
			rx_d	<= 8'd0;
	    end
		
    	else if(rx_sel_data)
		case(rx_num)
		0:;
		1:rx_d_r[0]<= uart_rx;
		2:rx_d_r[1]<= uart_rx;
		3:rx_d_r[2]<= uart_rx;
		4:rx_d_r[3]<= uart_rx;
		5:rx_d_r[4]<= uart_rx;
		6:rx_d_r[5]<= uart_rx;
		7:rx_d_r[6]<= uart_rx;
		8:rx_d_r[7]<= uart_rx;
		9:rx_d<= rx_d_r;
		default:;
		endcase		
    end

always @(posedge sys_clk or negedge rst_n)
	begin
    	if(rst_n==1'b0)
		
    		tx_en	<= 0;
    	else if(rx_num==9&&rx_sel_data)
		tx_en	<= 1;
		else
		tx_en	<= 0;	    
    end
endmodule

Tx代码


module uart_tx(
    input               sys_clk,
    input               rst_n, 
    output reg          uart_tx,   
    input	[3:0]       tx_num, 
	input               tx_sel_data,           	
    input  [7:0]    tx_d
);


always @(posedge sys_clk or negedge rst_n)
	begin
    	if(rst_n==1'b0)		
    		uart_tx	<= 1'b1;   
		
    	else if(tx_sel_data)
		case(tx_num)
		0:uart_tx<= 1'b0;
		1:uart_tx<= tx_d[0];
		2:uart_tx<= tx_d[1];
		3:uart_tx<= tx_d[2];
		4:uart_tx<= tx_d[3];
		5:uart_tx<= tx_d[4];
		6:uart_tx<= tx_d[5];
		7:uart_tx<= tx_d[6];
		8:uart_tx<= tx_d[7];
		9:uart_tx<= 1'b1;
		default:uart_tx<= 1'b1;
		endcase		
    end


endmodule

实现的效果是:

串口输出等于输入。当输入“1”,点LED1,输入“2”,点LED2,输入“a”,点LED1和LED2,输入“A”,灭LED1和LED2。输入其他字符,LED不变

编译遇到的几个问题:

1, case语句中不能直接放多个并行语句,需要用begin+end结构。

case(baudset)
    0:
    begin
       bsp_div    <= 13'd5208;
       bsp_div_2  <= 13'd2604;
    end

endcase 不是end case。 

2,baudset 作为module input,不能设置reg,需要用wire型

non-net port baudset cannot be of mode input. VERI-1325

3,case 的default 语句后, 用

default:
         led_temp<=led_temp;

不是期望的情况,不知道为什么。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值