ASYS2开发板初学记录(2)——Verilog程序编写
2017-12-26
注:win10系统+软件Xilinx_ISE14.7+开发板BASYS2
关键词:
FPGA
BASYS2
Xilinx_ISE
Verilog
紧接着上篇,填第一个坑:Verilog程序。
大学数电课学了Verilog,略有意思。
于是第一次就奉献在了Basys2上面。
写程序之前画一个流程图是非常方便整理思路的,(但是后来想想,对于Verilog这种硬件描述语言,流程图并不实用,波形时序图 似乎更能表达这里面的逻辑)
懒得改成时序图了,就把流程图贴出来吧:
(废话结束,祭出神器:Processon,可在线编辑各种脑图)
目的:
我做的是一个遥控机械手,遥控器5个信号输入分别控制5个手指,另外加第6个信号输入实现5个手指一起运动的动作组,用来按摩,没错。
硬件:
1》遥控器:富斯i10商品控,玩过航模的应该很清楚,这款遥控器支持10通道PWM信号输出,以及PPM信号输出。(这次使用PWM信号,因为简单,实在太简单。)
2》机械手:5个舵机,一个舵机控制一个手指。
原理:
遥控器的10个通道输出PWM波形,示波器真是个好东西,于是发现:每个通道的PWM波形为20ms一个周期,占空比5% (1ms)到10% (2ms)。
而舵机的控制需要的PWM信号输入也刚好是20ms一个周期,占空比5% (1ms)到10% (2ms)的PWM波形,也就是说,舵机直接遥控器的接收机就可以遥控了,压根没有开发板什么事,固定翼飞机就是玩的。可是不能这么没追求啊,我们要按摩啊!这就需要开发板处理6个通道的信号输入,输出5个信号。
每个CLK上升沿检测ch6通道信号,如果为高就进入自动按摩模式,5个手指一个个依次合拢,再依次张开的循环。如果为低,就进入遥控模式,5个通道遥控5个手指的位置。遥控器只有2个摇杆,输出4个模拟量,外加1个辅助通道,输出1个数字量。
程序流程图
不知是否能看清,所以截图了细节在下面:
完整程序如下:
`timescale 1ns / 1ps
//
// Company:
// Engineer: William Yu
//
// Create Date: 22:44:03 12/23/2017
// Design Name:
// Module Name: tele_pwm
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module tele_pwm(
input wire clk,
input wire reset,
input wire ch1,
input wire ch2,
input wire ch3,
input wire ch4,
input wire ch5,
input wire ch6,
output reg pwmout1,
output reg pwmout2,
output reg pwmout3,
output reg pwmout4,
output reg pwmout5,
output wire [3:0] ledout
);
// ----------- counter --------------
reg [26:0] counter;
always @(posedge clk)
begin
if (reset)
counter <= 0;
else
counter <= counter + 1;
end
// ----------- led check --------------
assign ledout = counter[26:23]; // 将counter的高4位传给led_out以降低频率,看到led灯闪烁 //167ms左右
// ----------- pwm input and output --------------
reg ch6_flag=0;
reg dance_en=0;
reg [19:0] counter20ms_2=0; //20ms=20ns* 1000 000 //10^6 < 2^20
reg [31:0] counter8s = 0; //8s= 20ns* 400 000 000 //400 000 000 < 2^32 //仿真检查刚开始的状态
//reg [31:0] counter8s = 100000001;//仿真检查2s之后的状态
//reg [31:0] counter8s = 200000001;//仿真检查4s之后的状态
//reg [31:0] counter8s = 300000001;//仿真检查4s之后的状态
always @(posedge clk)
begin
// ----------- tele --------------
if(dance_en == 0)begin
if (ch1) //pwm1
pwmout1<=1;
else
pwmout1<=0;
if (ch2) //pwm2
pwmout2<=1;
else
pwmout2<=0;
if (ch3) //pwm3
pwmout3<=1;
else
pwmout3<=0;
if (ch4) //pwm4
pwmout4<=1;
else
pwmout4<=0;
if (ch5) //pwm4
pwmout5<=1;
else
pwmout5<=0;
end
// ----------- dance --------------
else begin
counter8s <= counter8s+1;
///[A]1s动作组
if(counter8s < 50000000 )begin //1s=20ns * 50 000 000
counter20ms_2 <= counter20ms_2 + 1;
///高脉冲
if(counter20ms_2 > 100000)begin//2ms=20ns*100 000
pwmout1<=0;
end
else begin
pwmout1<=1;
end
///低脉冲
if(counter20ms_2 > 50000)begin//1ms=20ns*50 000
pwmout2<=0;
pwmout3<=0;
pwmout4<=0;
pwmout5<=0;
end
else begin
pwmout2<=1;
pwmout3<=1;
pwmout4<=1;
pwmout5<=1;
end
if(counter20ms_2>1000000) //20ms= 20ns*10^6
counter20ms_2<=0;
end
///[B]2s动作组
else if(counter8s < 100000000 )begin //2s=20ns * 100 000 000
counter20ms_2 <= counter20ms_2 + 1;
///高脉冲
if(counter20ms_2 > 100000)begin//2ms=20ns*100 000
pwmout1<=0;
pwmout2<=0;
end
else begin
pwmout1<=1;
pwmout2<=1;
end
///低脉冲
if(counter20ms_2 > 50000)begin//1ms=20ns*50 000
pwmout3<=0;
pwmout4<=0;
pwmout5<=0;
end
else begin
pwmout3<=1;
pwmout4<=1;
pwmout5<=1;
end
if(counter20ms_2>1000000) //20ms= 20ns*10^6
counter20ms_2<=0;
end
///[C]3s动作组
else if(counter8s < 150000000 )begin //3s=20ns * 150 000 000
counter20ms_2 <= counter20ms_2 + 1;
///高脉冲
if(counter20ms_2 > 100000)begin//2ms=20ns*100 000
pwmout1<=0;
pwmout2<=0;
pwmout3<=0;
end
else begin
pwmout1<=1;
pwmout2<=1;
pwmout3<=1;
end
///低脉冲
if(counter20ms_2 > 50000)begin//1ms=20ns*50 000
pwmout4<=0;
pwmout5<=0;
end
else begin
pwmout4<=1;
pwmout5<=1;
end
if(counter20ms_2>1000000) //20ms= 20ns*10^6
counter20ms_2<=0;
end
///[D]4s动作组
else if(counter8s < 200000000 )begin //4s=20ns * 200 000 000
counter20ms_2 <= counter20ms_2 + 1;
///高脉冲
if(counter20ms_2 > 100000)begin//2ms=20ns*100 000
pwmout1<=0;
pwmout2<=0;
pwmout3<=0;
pwmout4<=0;
end
else begin
pwmout1<=1;
pwmout2<=1;
pwmout3<=1;
pwmout4<=1;
end
///低脉冲
if(counter20ms_2 > 50000)begin//1ms=20ns*50 000
pwmout5<=0;
end
else begin
pwmout5<=1;
end
if(counter20ms_2>1000000) //20ms= 20ns*10^6
counter20ms_2<=0;
end
///[E]5s动作组
else if(counter8s < 250000000 )begin //5s=20ns * 250 000 000
counter20ms_2 <= counter20ms_2 + 1;
///高脉冲
if(counter20ms_2 > 100000)begin//2ms=20ns*100 000
pwmout2<=0;
pwmout3<=0;
pwmout4<=0;
end
else begin
pwmout2<=1;
pwmout3<=1;
pwmout4<=1;
end
///低脉冲
if(counter20ms_2 > 50000)begin//1ms=20ns*50 000
pwmout1<=0;
pwmout5<=0;
end
else begin
pwmout1<=1;
pwmout5<=1;
end
if(counter20ms_2>1000000) //20ms= 20ns*10^6
counter20ms_2<=0;
end
///[F]6s动作组
else if(counter8s < 300000000 )begin //6s=20ns * 300 000 000
counter20ms_2 <= counter20ms_2 + 1;
///高脉冲
if(counter20ms_2 > 100000)begin//2ms=20ns*100 000
pwmout3<=0;
pwmout4<=0;
end
else begin
pwmout3<=1;
pwmout4<=1;
end
///低脉冲
if(counter20ms_2 > 50000)begin//1ms=20ns*50 000
pwmout1<=0;
pwmout2<=0;
pwmout5<=0;
end
else begin
pwmout1<=1;
pwmout2<=1;
pwmout5<=1;
end
if(counter20ms_2>1000000) //20ms= 20ns*10^6
counter20ms_2<=0;
end
///[G]7s动作组
else if(counter8s < 350000000 )begin //7s=20ns * 350 000 000
counter20ms_2 <= counter20ms_2 + 1;
///高脉冲
if(counter20ms_2 > 100000)begin//2ms=20ns*100 000
pwmout4<=0;
end
else begin
pwmout4<=1;
end
///低脉冲
if(counter20ms_2 > 50000)begin//1ms=20ns*50 000
pwmout1<=0;
pwmout2<=0;
pwmout3<=0;
pwmout5<=0;
end
else begin
pwmout1<=1;
pwmout2<=1;
pwmout3<=1;
pwmout5<=1;
end
if(counter20ms_2>1000000) //20ms= 20ns*10^6
counter20ms_2<=0;
end
///[H]8s动作组
else begin //8s
counter20ms_2 <= counter20ms_2 + 1;
///高脉冲无
///低脉冲
if(counter20ms_2> 50000)begin//1ms=20ns*50 000
pwmout1<=0;
pwmout2<=0;
pwmout3<=0;
pwmout4<=0;
pwmout5<=0;
end
else begin
pwmout1<=1;
pwmout2<=1;
pwmout3<=1;
pwmout4<=1;
pwmout5<=1;
end
if(counter20ms_2>1000000) //20ms= 20ns*10^6
counter20ms_2<=0;
//8s溢出循环
if(counter8s > 400000000) //8s= 20ns* 400 000 000
counter8s<=0;
end
end
end
// ----------- check ch6 --------------
reg [16:0] ch6_counter = 0; //ch6_counter在1ms到2ms之间, 2ms=20ns* 100 000 //10^5 < 2^17
reg [19:0] counter20ms=0; //20ms=20ns* 1000 000 //10^6 < 2^20
always @(posedge clk)
begin
if(counter20ms>1000000)begin //一个clk是20ns,10^6是20ms
counter20ms<=0;
ch6_counter<=0;end
else
counter20ms <= counter20ms +1;
if (ch6) begin
ch6_counter<=ch6_counter+1;
if (ch6_counter > 75000) //1.5ms=75000 * 20ns
ch6_flag <= 1;
else ch6_flag <=0;
end
end
reg [19:0] counter_ch6_flag=0;
always @(posedge clk)
begin
if(ch6_flag)
dance_en<=1;
else begin //记录ch6低电平持续时间是否持续超过2ms,超过则认为已经拉低
counter_ch6_flag<=counter_ch6_flag+1;
if(counter_ch6_flag>1000000)
begin
dance_en<=0;
counter_ch6_flag<=0;
end
end
end
endmodule
结束。
(2017-12-24–William Yu)