BASYS2开发板初学记录(2)——Verilog程序编写
2017-12-29 14:38
477 查看
ASYS2开发板初学记录(2)——Verilog程序编写
2017-12-26注:win10系统+软件Xilinx_ISE14.7+开发板BASYS2
关键词:
FPGABASYS2
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)
相关文章推荐
- BASYS2开发板初学记录(1)——使用流程
- 用Verilog HDL编写的8位跑马灯程序,附Basys2--ucf仿真程序
- BASYS2开发板初学记录(4)——引脚约束
- u-boot 程序执行流程记录(am335x 开发板)
- Head First Java (第二版)学习记录 5 - 编写程序 DotCom 初级游戏
- 基于黑金开发板的秒表verilog hdl程序
- 64位win7下使用C_API编写mysql程序的错误及解决办法记录
- 编写一个学生信息系统的菜单程序,在菜单其中的增加记录的菜单选项中实现对一条学生记录的录入,记录中需要有学号、姓名、性别,年龄籍贯等字段,要求用最合适的控件录入。
- Verilog编写的Uart程序
- c#如何使用socket发送一条记录再接收一条记录,服务器端及客户端如何编写,初学。。最好有代码,谢谢!
- 程序员面试金典——解题总结: 9.18高难度题 18.9随机生成一些数字并传入某个方法。编写一个程序,每当收到新数字时,找出并记录中位数。
- 程序编写(个人记录)
- 初学python-练习_4使用python编写本地登录程序(带注册)
- FPGA 使用verilog 编写的AD tlc549 测试程序,数码管做显示,本程序已验证
- 编写文件搜索小程序:1. 输入绝对路径以及搜索关键字,2. 搜索指定路径下(包括子文件夹)中名称包含关键字的所有文件并打印出,3. 将当前操作记录日志
- hta编写的消费记录程序
- 初学C时,用C编写的一个送给女朋友的小程序
- 记录我很久以前登报的一篇文章(用DELPHI编写CCI程序)
- //编写程序使学生的档案记录按照学号从小到大进行排序
- 编写高质量代码改善C#程序的157个建议——建议70:避免在调用栈较低的位置记录异常