串口控制PWM(频率、占空比可调)

top模块

`timescale 1ns / 1ps
module top(
	input 	sys_clk,
	input 	rst_n,
	input 	rx,
	output 	tx,
	output	reg	led,
	output	pwm
    );
	wire	BaundClk_x16;
	wire  [7:0] DataCon;
	wire 	TxFlag;
	wire	[15:0]	period_data;
	wire	[15:0]	h_time_data;
	wire	pwm_en;

clkdiv u_clkdiv(
	.sys_clk(sys_clk),
	.rst_n(rst_n),
	.clk_out(BaundClk_x16)
);
	
rx_module u_rx(
	.Clk16x(BaundClk_x16), 						
	.rst_n(rst_n), 							
	.rx(rx), 							
	.DataReady(TxFlag), 		
	.DataOut(DataCon)	
);

tx_module u_tx(
	.Clk16x(BaundClk_x16), 					
	.rst_n(rst_n), 					
	.TransEn(TxFlag), 				
	.DataToTrans(DataCon), 	
	.tx(tx) 					
);

pwm_register u_pwm_register(
	.rst_n(rst_n),
	.sysclk(sys_clk),
	.rx_data(DataCon),
	.rx_data_ready(TxFlag),
	.period(period_data),
	.h_time(h_time_data),
	.pwm_en(pwm_en)	
    );
	 
pwm_gen u_pwm_gen(

	.rst_n(rst_n),
	.sysclk(sys_clk),
	.en(pwm_en),
	.period(period_data),
	.h_time(h_time_data),
	.pwm(pwm)
);

always@(negedge rst_n , posedge TxFlag)
	begin
		if (!rst_n)
			led <= 1'd0;
		else
			if(TxFlag)
				led <= ~led;
	end
	
endmodule

波特率频率产生模块

`timescale 1ns / 1ps
//输出16倍的波特率
	module clkdiv(
	input 			sys_clk,
	input 			rst_n,
	output   reg	clk_out
);
	reg 	[7:0]	counter;
	parameter		BaudRate = 115200;
	parameter		SysClk	= 15360000;
	localparam		BaudACC	= SysClk / BaudRate/16/2-1;	//计数50次翻转
	
	always @(posedge sys_clk or negedge rst_n)
	begin
		if (!rst_n)
			begin
				clk_out <= 0;
				counter <= 0;
			end
		else	if (counter == BaudACC)
			begin	
				clk_out <= ~clk_out;
				counter <= 8'd0;
			end 
		else 
				counter <= counter + 1 ;
	end 			
endmodule 

串口接受模块

`timescale 1ns / 1ps
module rx_module(
	//input SysClk, 							/* system topest clock */
	input Clk16x, 							/* sample clock,16×115200 */
	input rst_n, 							/* glabol reset signal */
	input rx, 								/* serial data in */
	output reg		 	DataReady, 		/* a complete byte has been received */
	output reg	[7:0] DataOut			//output reg	[7:0] DataReceived 	/* Bytes received */
);
reg 	[7:0] cnt;
reg	[7:0] DataReceived;
//---------------------------------------------
/* 捕获rx的下降沿,即起始信号 */
reg trigger_r0;
wire neg_tri;

assign neg_tri = trigger_r0 & ~rx;
always@(posedge Clk16x or negedge rst_n)
begin
	if(!rst_n)
		trigger_r0<=1'b0;
	else
		trigger_r0<=rx;
end
//---------------------------------------------
/* counter control */
reg cnt_en;
always@(posedge Clk16x or negedge rst_n)
begin
	if(!rst_n)
		cnt_en<=1'b0;
	else if(neg_tri==1'b1) /*如果捕获到下降沿,则开始计数*/
		cnt_en<=1'b1;
	else if(cnt==8'd152)
		cnt_en<=1'b0;
end
//---------------------------------------------
/* counter module ,对采样时钟进行计数 */
always@(posedge Clk16x or negedge rst_n)
begin
	if(!rst_n)
		cnt<=8'd0;
	else if(cnt_en)
		cnt<=cnt+1'b1;
	else
		cnt<=8'd0;
end
//---------------------------------------------
/* receive module */
reg StopBit_r;
always@(posedge Clk16x or negedge rst_n)
begin
	if(!rst_n)
		begin
			DataReceived<=8'b0;
		end
	else if(cnt_en)
		case(cnt)
			8'd24: DataReceived[0] <= rx; /*在各个采样时刻,读取接收到的数据*/
			8'd40: DataReceived[1] <= rx;
			8'd56: DataReceived[2] <= rx;
			8'd72: DataReceived[3] <= rx;
			8'd88: DataReceived[4] <= rx;
			8'd104: DataReceived[5] <= rx;
			8'd120: DataReceived[6] <= rx;
			8'd136: DataReceived[7] <= rx;
			default:DataReceived <= DataReceived;
		endcase
end

always@(posedge Clk16x or negedge rst_n)
begin
	if(!rst_n)
		DataReady<=1'b0;
	else if (cnt==8'd152)
		begin
			DataReady<=1'b1; //接收到停止位后,给出数据准备好标志位
			DataOut	<=DataReceived;
		end
	else
		DataReady<=1'b0;
end
endmodule

串口发送模块

`timescale 1ns / 1ps
module tx_module(
	input Clk16x, 					/* transmit clock,16×115200 */
	input rst_n, 					/* glabol reset signal */
	input TransEn, 				/* transmit enable */
	input [7:0] DataToTrans, 	/* Data prepared for transmitting */

	output reg BufFull, 			/* Data buffer is full */
	output reg tx 					/* serial data out */
);
reg [7:0] cnt;
//----------------------------------------------
/* TransEn上升沿捕获 */
reg TransEn_r;
wire pos_tri;
always@(posedge Clk16x or negedge rst_n)
	begin
		if(!rst_n)
			TransEn_r <= 1'b0;
		else
			TransEn_r <= TransEn;
	end
assign pos_tri = ~TransEn_r & TransEn;
//----------------------------------------------
/*when the rising edge of DataEn comes up, load the Data to buffer*/
reg [7:0] ShiftReg;
always@(posedge pos_tri or negedge rst_n)
begin
	if(!rst_n)
		ShiftReg <= 8'b0;
	else
		ShiftReg <= DataToTrans;
end
//----------------------------------------------
/* counter control */
reg cnt_en;
always@(posedge Clk16x or negedge rst_n)
	begin
		if(!rst_n)
			begin
				cnt_en <= 1'b0;
				BufFull <= 1'b0;
			end
		else if(pos_tri==1'b1)
			begin
				cnt_en <=1'b1;
				BufFull <=1'b1;
			end
		else if(cnt==8'd160)
			begin
				cnt_en<=1'b0;
				BufFull <=1'b0;
			end
	end

//---------------------------------------------
/* counter module */
always@(posedge Clk16x or negedge rst_n)
	begin
		if(!rst_n)
			cnt<=8'd0;
		else if(cnt_en)
			cnt<=cnt+1'b1;
		else
			cnt<=8'd0;
	end

//---------------------------------------------
/* transmit module */

always@(posedge Clk16x or negedge rst_n)
	begin
		if(!rst_n)
			begin
				tx <= 1'b1;
			end
		else if(cnt_en)
			case(cnt)
				8'd0 : tx <= 1'b0;
				8'd16 : tx <= ShiftReg[0];
				8'd32 : tx <= ShiftReg[1];
				8'd48 : tx <= ShiftReg[2];
				8'd64 : tx <= ShiftReg[3];
				8'd80 : tx <= ShiftReg[4];
				8'd96 : tx <= ShiftReg[5];
				8'd112 : tx <= ShiftReg[6];
				8'd128 : tx <= ShiftReg[7];
				8'd144 : tx <= 1'b1;
			endcase
		else
			tx <= 1'b1;
	end
endmodule

串口传送PWM数据,寄存模块

`timescale 1ns / 1ps
module pwm_register(

	input rst_n,
	input sysclk,
	input [7:0] rx_data,
	input rx_data_ready,

	output reg	[15:0] period,
	output reg	[15:0] h_time,

	output reg pwm_en
    );
	
	reg[7:0] rx_reg;
	
always@(posedge rx_data_ready or negedge rst_n)
	if(!rst_n)
		begin
			rx_reg	<=	8'b0;			
		end
	else 
		begin
			rx_reg		<=	rx_data;				//帧尾
			h_time[7:0]	<=	rx_reg;				//底位
			h_time[15:8]<=	h_time[7:0];
			period[7:0]	<=	h_time[15:8];
			period[15:8]<=	period[7:0];		//高位
		end

always @ (posedge sysclk or negedge rst_n)
	begin
		if(!rst_n)
			pwm_en <= 1'b0;
		else if (rx_reg == 8'b1111_1111)
			pwm_en <= 1'b1;
		else
			pwm_en <= 1'b0;		
	end
	

endmodule

PWM产生模块

`timescale 1ns / 1ps
module pwm_gen(

input rst_n,
input sysclk,
input en,

input [15:0] period,
input [15:0] h_time,

output reg pwm

);

reg [31:0] cnt;

always @ (posedge sysclk or negedge rst_n)
begin
    if(!rst_n)
        cnt <= 0;
    else 
		begin
			if(cnt >= period - 1 )
			  cnt <= 0;
			else
			  cnt <= cnt + 1;
		end
end

always @ (posedge sysclk or negedge rst_n)
begin
    if(!rst_n)
        pwm <= 0;
    else    //rst_n = 1
    begin
        if(en == 0)
            pwm <= 0;
        else    //en = 1
        begin
            if(cnt <= h_time - 1)
                pwm <= 1;
            else
                pwm <= 0;
        end
    end
end

endmodule

发送数据HEX例如:7800(period) 3c00(h_time) FF (end)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值