1、CPLD程序设计实验,2018年11月16日星期五,实验目的,了解CPLD的程序设计的特点 学习verilog HDL设计 掌握编程到下载的操作流程,实验仪器与材料,Xilinx ISE6.2 001181092实验板 5V稳压电源 JTAG下载线,实验原理及准备知识,XC95108器件结构(第二章) Xilinx ISE(软件环境)的使用(第四章) Verilog HDL代码设计(第三章),Part I,组合逻辑电路在CPLD上的实现,实验简述,本实验要求填充完成4段功能相同(七段译码显示)的代码,掌握Verilog HDL代码编写基本知识。 熟悉ISE代码设计界面,综合并下载到实验板上验证
2、编写代码的正确性。 比较该4段代码的Fit Report。,电路的不同描述方式,结构化描述方式 数据流描述方式 行为描述方式(逻辑函数式) 行为描述方式(case语句),结构化描述方式,module mux4_1(out, in1,in2,in3,in4,cntrl1,cntrl2);output out;input in1, in2,in3,in4,cntrl1,cntrl2;wire notcntrl1,notcntrl2,w,x,y,z; not(notcntrl1, cntrl1);not(notcntrl2,cntrl2);and(w,in1,notcntrl1,notcntrl2)
3、;and(x,in2,notcntrl1,cntrl2);and(y,in3,cntrl1,notcntrl2);and(z,in4,cntrl1,cntrl2);or(out,w,x,y,z); endmodule,4选1数据选择器的电路描述,行为描述方式(case语句描述),module mux4_1(out, in1,in2, in3,in4,cntrl1,cntrl2);output out;input in1,in2,in3,in4,cntrl1,cntrl2;reg out1; /只有register型变量能够在always语句中赋值always(in1 or in2 or in3
4、 or in4 or cntrl1 or cntrl2)begin case(cntrl1,cntrl2)2b00: out1=in1;2b01: out1=in2;2b10: out1=in3;2b11: out1=in4;default: out1=2bx;endcaseendout=out1; endmodule,结构化描述方式,01 module strushow(key, seg7led, bit4sel); /模块框架,模块名(输入输出端口列表) 02 input 3:0 key;/输入信号声明,key是4位矢量,下标30 03 output 7:0 seg7led; /输出信号声
5、明,seg7led是8位矢量,下标70 04 _; /输出信号声明,bit4sel是4位矢量,下标30 05 wire w1x1x, w11xx, wxx11, wx01x, wx110, wx101, wx010, wx111, wx100, wx001, w00x1, w000x, w0001; /声明线型变量w1x1x等13个 06 _;/声明线型4位矢量nky,下标3到0 07 not not0(nky0, key0); /nky0等于key0的非 08 not not1(nky1, key1); /nky1等于key1的非 09 _; /nky2等于key2的非 10 not not
6、3(nky3, key3); /nky3等于key3的非 11 and and1x1x(w1x1x, key3, key1); / w1x1x =key3key1 12 and and11xx(w11xx, key3, key2); / w11xx =key3key2 13 _; / wxxll =key1key0 14 and andx01x(wx01x, nky2, key1); / wx01x =key2key1 15 and andx110(wx110, key2, key1, nky0);/wx110=key2key1nky0 16 _;/wx101=key2nky1key0 17
7、and andx010(wx010, nky2, key1, nky0);/wx010=nky2key1nky0 18 and andx111(wx111, key2, key1, key0);/wx111=key2key1key0 19 _;/wx100=key2nky1nky0; 20 and andx001(wx001, nky2, nky1, key0);/wx001=nky2nky1key0 21 and and00x1(w00x1, nky3, nky2, key0);/w00x1=nky3nky2key0 22 _;/w000x=nky3nky2nky1; 23 and and0
8、001(w0001, nky3, nky2, nky1, key0);/* w0001=nky3nky2nky1key0*/ 24 nor nora(seg7led0, w0001, w1x1x, wx110, wx100);/* seg7led0=w0001, w1x1x, wx110, wx100四项的或非*/ 25 nor norb(seg7led1, w1x1x, wx110, wx101); /* seg7led1=w1x1x, wx110, wx101三项的或非*/ 26 _;/seg7led2=wllxx, wx010二项的或非 27 nor nord(seg7led3, wx1
9、11, wx100, wx001);/* seg7led3=wx111, wx100, wx001三项的或非*/ 28 nor nore(seg7led4, wx101, wx100, key0);/* seg7led4=wx101, wx100, key0三项的或非*/ 29 _;/seg7led5=w00x1, wx01x, wxx11三项的或非*/ 30 nor norg(seg7led6, w000x, wx111);/ seg7led6=w000x, wx111二项的或非 31 assign bit4sel=4b0; / 连续赋值语句,bit4sel设置为全0,4个数码管全部显示 3
10、2 endmodule / 模块结束,数据流描述方式,01 module flowshow(key, seg7led, bit4sel); /模块框架,模块名(输入输出端口列表) 02 input 3:0 key; /输入信号声明,key是4位矢量,下标30 03 _ ;/输出信号声明,seg7led是7位矢量,下标60 04 output 3:0 bit4sel; /输出信号声明,bit4sel是4位矢量,下标30 05 wire w1x1x, w11xx, wxx11, wx01x, wx110, wx101, wx010, wx111, wx100, wx001, w00x1, w000
11、x, w0001; 06 _ ;/设置线型4位矢量nky,下标3,2,1,0 07 assign nky0 = key0; /nky0等于key0的非 08 _ ; /nky1等于key1的非 09 assign nky2 = key2; /nky2等于key2的非 10 assign nky3 = key3; /nky3等于key3的非 11 assign w1x1x = key3 / 连续赋值语句,bit4sel设置为全0,4个数码管全部显示 32 endmodule,行为描述方式(逻辑函数式),01 module todoshow(key, seg7led, bit4sel); /模块框
12、架,模块名(输入输出端口列表) 02 _; /输入信号声明,key是4位矢量,下标30 03 output 6:0 seg7led; /输出信号声明,seg7led是7位矢量,下标60 04 output 3:0 bit4sel; /输出信号声明,bit4sel是4位矢量,下标30 05 reg w1x1x, w11xx, wxx11, wx01x, wx110, wx101, wx010, wx111, wx100, wx001, w00x1, w000x, w0001; 06 reg 3:0 nky; 07 _;/声明寄存器矢量seg7,下标6到0; 08 _;/一个行为描述体由任意的ke
13、y变化触发产生 09 begin 10 nky = key;/将key3:0全部取反,赋给nky3:0 11 _;/w1x1x = key3 key1; 12 w11xx = key3 /seg7led是线型矢量,seg7是寄存器型矢量需赋值 34 endmodule,行为描述方式(case语句),01 _;/模块头,模块名dateshow,输入输出根据0203行填写 02 input 3:0 key; /输入信号声明,key是4位矢量,下标30 03 output 7:0 seg7led; /输出信号声明,seg7led是7位矢量,下标60 04 output 3:0 bit4sel; /输
14、出信号声明,bit4sel是4位矢量,下标30 05 reg 7:0 seg_reg; /内部寄存器变量声明,seg_reg是7位矢量,下标60 06 always/一个始终有效产生行为描述体 07 begin 08 case(key) 09 _; /当key=0的时候,seg_reg赋值8hc0 10 4h1:seg_reg = 8hf9; /当key=1的时候,seg_reg赋值8hf9 11 4h2:seg_reg = 8ha4; /当key=2的时候,seg_reg赋值8ha4 12 4h3:seg_reg = 8hb0; /当key=3的时候,seg_reg赋值8hb0 13 _;
15、/当key=4的时候,seg_reg赋值8h99 14 4h5:seg_reg = 8h92; /当key=5的时候,seg_reg赋值8h92 15 4h6:seg_reg = 8h82; /当key=6的时候,seg_reg赋值8h82 16 4h7:seg_reg = 8hf8; /当key=7的时候,seg_reg赋值8hf8 17 _; /当key=8的时候,seg_reg赋值8h80 18 4h9:seg_reg = 8h90; /当key=9的时候,seg_reg赋值8h9019 20 endcase 21 end 22 _; /seg_reg是寄存器型,seg7led是线型,s
16、eg_reg赋值给seg7led 23 assign bit4sel=4b0; /连续赋值语句,bit4sel设置为全0,4个数码管全部显示 24 endmodule,显示的结果:初始状态为8888;当四个键都按下时,显示0000;以下类推。,管脚配置,综合下载,最简化的3大步骤 编写代码配置管脚下载 在该3步骤基础上逐渐熟悉其它操作 选中不同的资源文件,有不同的对应操作可用,如选中ucf文件时,下载操作不可见! 接插JTAG线要注意,关闭电脑状态进行! 实验板,先接电源线,后接信号线,Fit Report,图中是共阳极数码管,用低电平驱动,Fit Report,Fit Report中有Fit
17、之后器件内资源使用情况,如可以观察乘积项、宏单元、功能块、寄存器、引脚的使用情况,比较fit结果有助于指导良好的代码编写习惯的养成。,Part II,时序逻辑电路在CPLD上的实现,实验简述,掌握多种进制计数器的代码实现 掌握数码管动态显示的原理与代码实现 掌握代码器件的实例化和ECS原理图输入方式,计数器,最高位50%占空比的二进制计数器的实现 十进制计数器的实现 二十四进制计数器的实现,最高位50%占空比的二进制计数器的实现,实验板上晶振频率为11.0592MHz,采用21位加计数器,从21h179000到21h87000(注:最高位进位丢弃),从而最高位可获得50%占空比的0.1秒脉冲。
18、,参考代码,1 module cp100ms(clk, cp,shifter); 2 input clk; /11.0592MHz 3 output cp; /提供50%占空比的0.1s脉冲 4 output 1:0shifter; /提取可供动态显示位轮巡的编码数据 5 reg 20:0 count; /内部申请21位寄存器,实现大分频 6 7 always(_) /clk下降沿触发行为 8 begin 9 if _; /如果count现态等于16进制数86FFF, 10 _; /count次态赋值16进制数179000; 11 else 12 _; /count次态为现态加1; 13 en
19、d 14 15 assign _; /位count20是q=50%的reg型,cp引脚是wire型 16 assign _; /位count1615赋给shifter,用于数码管位选 endmodule,十进制计数器的实现,1 module cnt10(clk, cnt); 2 input clk;/时钟输入,这段代码具有通用性,使用2次 3 output 3:0 cnt; /十进制技术输出 4 reg 3:0 cnt; /输出端寄存器型声明 5 6 always(_) /clk下降沿触发行为 7 begin 8 if _; /如果cnt现态等于9,次态置0 9 else _; / cnt次态
20、为现态加1 10 end 11 endmodule,24进制计数器的实现,1 module cnt24(clk,cnt24h, cnt24l); 2 input clk; /时钟输入,这段代码具有通用性, 3 output 3:0 cnt24h, cnt24l;/十进制技术输出 4 reg 3:0 cnt24h, cnt24l; /输出端寄存器型声明 5 6 always(_) /clk下降沿触发行为 7 begin 8 if _/如果cnt24=23, 9 _ /cnt24=0 10 else if _ /如果cnt24低位=9 11 begin 12 _ /低位复位到0 13 _/高位加1
21、 14 end 15 else _ /低位加1 16 end 17 endmodule,4位4选1数据选择电路,module mux4of16(shifter,in16,out4); /根据显示位编码input 1:0 shifter;/决定当前显示位的编码数据input 15:0 in16; /in16是需要送到数码管显示的所有数据output 3:0 out4; /选中送显的数据reg 3:0 out4; always begincase (shifter)2b00: _;/in16中的3:0送给输出端2b01: _; /in16中的7:4送给输出端2b10: _; /in16中的11:8
22、送给输出端2b11: _; /in16中的15:12送给输出端endcase end endmodule,数码管动态显示,1 module DynSevenDrv(shifter, key, seg7led, bit4sel); 2 input 1:0 shifter; /决定当前显示位的编码数据 3 input 3:0 key; /数码管显示的数值 4 output 7:0 seg7led; /显示段码 5 output 3:0 bit4sel; /位选通信号 6 reg 7:0 seg7led; 7 reg 3:0 bit4sel; 8 9 always 10 begin 11 case(
23、key) /对需要显示的数据进行7段译码 12 4h0: _ 13 4h1: _ 14 4h2: _ 15 4h3: _ 16 4h4: _ 17 4h5: _ 18 4h6: _ 19 4h7: _ 20 4h8: _ 21 4h9: _ 22 default: _; 23 endcase 24 end 25 26 always(shifter) 27 begin 28 case (shifter) 29 2b00: _/选通b0位,注意:低电平有效 30 2b01: _/选通b1位,注意:低电平有效 31 2b10: _/选通b2位,注意:低电平有效 32 2b11: _/选通b3位,注意
24、:低电平有效 33 endcase 34 end 35 endmodule,数码管动态显示,利用视觉暂留的原理,可以利用少量的地址线实现较多的数码位显示。 刷新频率信号源;刷新频率。,代码实例化和原理图输入,原理图中的电路模块可以使用软件提供的,也可以由用户制作。实例化后的文件扩展名*.sym。 模块连线可以采用连线方式,也可以采用netname标注的逻辑连线方式(和protel相似)。注意输入输出端的设定。 绘好后可用工具栏电路检查按钮检查。 绘制好的电路图模块在ISE中可以阅读其转换代码。,ECS原理图输入,Part III,CPLD上系统电路的实现,实验简述,实现1个3选手抢答电路,有倒
25、计时显示、加分显示 学习状态转换图输入方式 进一步学习代码输入方式和原理图输入方式。,状态转换图,其它模块,DecCnt倒计数器 预置数选择电路 秒脉冲电路CpSec OnePulse秒脉冲清零信号生成电路 adder加法器电路,DecCnt倒计数器,输出TimeOver信号:计数到0时TimerOver给出倒计时结束信号 倒计时显示数据 Time3:0。 输入 系统复位RESET 秒脉冲Cp1Sec:由于该脉冲高电平开始,所以上升沿触发计数。 预置数加载信号Pulse100n:脉冲宽度一个晶振CP周期,约100ns的窄脉冲 预置数TLD3:0,参考代码,module DecCnt(Cp1Se
26、c, Pulse100n, TimeLD, TimeOver, Timer); input Cp1Sec,Pulse100n; input 3:0TimeLD; output 3:0Timer; output TimeOver; reg 3:0 Timer; always(posedge Cp1Sec or posedge Pulse100n) begin if _/如果是Pulse100n上升沿,load预置数Timer=TimeLD; else _/倒计时减1 end assign _/ 当Timer 全0时,TimeOver=1; endmodule,预置数选择电路,输出 预置数TLD3
27、:0:例如抢答可设置5秒,回答设置7秒。 输入选择控制信号CompeteTime、Play1AnsTime、Play2AnsTime,参考代码,module mux4of8(MainLED,Play1LED,Play2LED,out4); input MainLED,Play1LED,Play2LED; output 3:0 out4; reg 3:0 out4; always(MainLED,Play1LED,Play2LED) begin case (MainLED,Play1LED,Play2LED) 3b011: _/ 3b101: _/ 3b110: _/ default: _/ e
28、ndcase end endmodule,秒脉冲电路,输出 秒脉冲Cp1Sec,占空比50% 数码管轮显控制信号shifter1:0 输入 振荡源输出脉冲clk11M; 秒脉冲复位信号Pulse100n:为了保证送给DecCnt计数的秒脉冲完整性,在抢答、回答倒计时开始时对秒脉冲复位; 秒脉冲输出使能信号DownCntEn:由低电平有效,驱动发光二极管亮的三个信号MainLED,Play1LED,Play2LED相与得到,低电平有效,可以输出秒脉冲,高电平时,仅输出高电平。,参考代码,module CpSec(CLK, enCnt, Pulse100n, Cp1Sec, shifter); i
29、nput CLK, enCnt, Pulse100n; output Cp1Sec; output 1:0shifter; reg 23:0 count; always(negedge CLK or posedge Pulse100n) begin if _/如果清零信号,count立即复位 else if (enCnt) /不允许倒计时计数 if _/在count23翻转到0之前,将其复位 else _/自加1,用于分时生成动态扫描数码管信号 else /允许倒计时计数 if _/在count完成1s分频时,将其复位 else _ /自加1, end assign Cp1Sec=_;秒脉冲信
30、号取自 assign shifter=_;动态扫描数码管信号取自 endmodule,秒脉冲清零信号生成电路,输出 Pulse100n:用于置数、清零的窄脉冲 输入 clk11M:11M振荡信号 AnyLedOn:窄脉冲所需要的源。,参考代码,module OnePulse(CLK, AnyLedOn, Pulse); input CLK, AnyLedOn; output Pulse; reg 1:0count; always(negedge CLK or negedge AnyLedOn) begin if _/灯亮了 if _/小计数器高位为0时,自加1 else _;/维持 else
31、_;/ 复位为0 end assign Pulse=_;/根据图判断,哪儿具有符合条件的窄脉冲? endmodule,adder加法器电路,Reset进行加法器的复位,在选手回答灯亮时,按动addkey键可给对应选手加分。,参考代码,module adder(RESET, AddScore,Play1,Play2, P1Score,P2Score); input RESET; input Play1,Play2,AddScore; output 3:0P1Score,P2Score; reg 3:0P1Score,P2Score; always(negedge RESET or negedge AddScore) begin if (RESET=0) /复位,所有选手得分清零 _ _ _ _ else/根据亮灯情况,给相应选手加分 _ _ _ _ end endmodule,ECS电路图输入,