目录
【实验一】设计一个交通红绿灯控制器模块,实现主干道和支路之间红绿黄灯的信号转换
【实验要求】
- 实验内容与原理说明(包括框图、逻辑表达式和真值表)。
- 实验模块程序代码(设计模块Design Block)和激励代码(激励模块Test Bench)。
- 仿真波形图。
- 综合得到的门级电路图,所用器件的型号以及设计模块所占用该型器件的资源情况。
- 实验结果分析及思考。
- 每一次报告用Word文档提交,文件名:姓名_班级_第几次实验_学号。
【实验软件工具】
- QuartusII;
- ModelSim SE.
【实验一】设计一个交通红绿灯控制器模块,实现主干道和支路之间红绿黄灯的信号转换
1. 实验内容与原理说明
本实验实现一个交通信号灯的控制模块,实现主干道和支路之间的红绿黄灯的信号转换。假设LIGHT1为主路信号灯,LIGHT2为支路信号灯,每一个信号灯循环周期为50s。20s,H为绿灯,F为红灯。5s,H为黄灯,F为红灯。20s,H为红灯,F为绿灯。5s,H为红灯,F为黄灯。
通过分析交通灯控制电路的要求可知,系统主要由传感器、时钟脉冲产生器
定时器、控制器及译码器构成,传感器S在有车辆通过时发出一个高电平信号。
可知交通灯的系统框图如下:

可以得到其ASM图如下:

根据交通灯控制单元的ASM图, ASM图中的状态框与状态图中的状态相对应,判断框中的条件是状态转换的输入条件,条件输出框与控制单元状态转换的输出相对应。状态图是描述状态之间的转换,例如在S,状态,如果条件TL·S=1时,系统状态转移到ST,同时输出状态转换信号S1。如果TL·S=0,则系统保持在S0状态。
当交通灯控制电路处于不同工作状态时,交通信号灯按一定的规律与之对应,各状态与信号灯的关系如表5.4.2所示。表中用1表示灯亮,用0表示灯灭。
可以得到信号灯与控制器状态编码表如下:

2. 实验模块程序代码和激励代码
(1)设计模块代码
//定义状态 `define S0 2'b00//主绿支红 `define S1 2'b01//主黄支红 `define S2 2'b11//主红支绿 `define S3 2'b10//主红支黄 //定义trafficLight控制程序 module trafficLight(CLK,S,rst,HR,HG,HY,FR,FG,FY,timeH,timeL); input CLK,S,rst; output[3:0] timeH; output[3:0] timeL; reg[3:0] timeH; reg[3:0] timeL; output reg HR,HG,HY,FR,FG,FY; wire TL,TS,TY; reg ST; reg[1:0] CState,NState; //时序模块的描述 always@(posedge CLK or negedge rst) begin if(~rst) {timeH,timeL}<=8'h00; else if(ST) {timeH,timeL}<=8'h00; else if((timeH==5)&(timeL==9)) begin {timeH,timeL}<={timeH,timeL}; end else if(timeL==9) begin timeH<=timeH+1; timeL<=0; end else begin timeH<=timeH; timeL<=timeL+1; end end assign TY=(timeH==0)&(timeL==4); assign TS=(timeH==2)&(timeL==9); assign TL=(timeH==5)&(timeL==9); //定义三种输出时间输出标志 //描述状态机状态转换 always@(posedge CLK or negedge rst) begin if(~rst) CState<=`S0; else CState<=NState; end //分别对四种状态进行描述 always@(S or CState or TL or TS or TY) begin case(CState) `S0:begin NState=(TL&&S)?`S1:`S0; ST=(TL&&S)?1:0; end `S1:begin NState=(TY)?`S2:`S1; ST=(TY)?1:0; end `S2:begin NState=(TS||~S)?`S3:`S2; ST=(TS||~S)?1:0; end `S3:begin NState=(TY)?`S0:`S3; ST=(TY)?1:0; end endcase end //将状态转换译码 always@(CState) begin case(CState) `S0:begin {HG,HY,HR}=3'b100; {FG,FY,FR}=3'b001; end `S1:begin {HG,HY,HR}=3'b010; {FG,FY,FR}=3'b001; end `S2:begin {HG,HY,HR}=3'b001; {FG,FY,FR}=3'b100; end `S3:begin {HG,HY,HR}=3'b001; {FG,FY,FR}=3'b010; end endcase end endmodule
(2)激励模块代码
// Verilog Test Bench template for design : trafficLight // // Simulation tool : ModelSim (Verilog) // `timescale 1 ps/ 1 ps module trafficLight_vlg_tst(); // constants // general purpose registers reg eachvec; // test vector input registers reg CLK; reg S; reg rst; // wires wire HG; wire HR; wire HY; wire FG; wire FR; wire FY; wire [3:0] timeH; wire [3:0] timeL; // assign statements (if any) trafficLight i1 ( // port map - connection between master ports and signals/registers .CLK(CLK), .HG(HG), .HR(HR), .HY(HY), .FG(FG), .FR(FR), .FY(FY), .S(S), .rst(rst), .timeH(timeH), .timeL(timeL) ); initial begin rst<=0;S<=0;CLK<=0; #10 rst<=1; #100 S<=1; #3000 $stop; end always #5 CLK<=~CLK; endmodule
3. 波形仿真图

4.门级电路图

设计模块所占用器件的资源情况如下所示:

【实验二】设计一个小轿车尾灯控制器模块(以书中的例子)
1. 实验内容与原理说明
汽车尾灯发出的信号主要是给后面行驶汽车的司机看的,通常汽车驾驶室有刹车开关(HAZ)、左转弯开关(LEFT)和右转弯开关(RIGHT),司机通过操作这
3个开关给出车辆的行驶状态。假设在汽车尾部左、右两侧各有3个指示灯,分别用LA、LB、LC、RA、RB、RC表示,如图5.4.1所示。这些灯的亮、灭规律如下:
1)汽车正常行驶时,尾部两侧的6个灯全部熄灭。
2)刹车时,汽车尾灯工作在告警状态,6个灯按一定频率闪烁。
3)左转弯时,左侧3个灯轮流顺序点亮,其规律如图5.4.2a所示,右侧灯全灭。
4)右转弯时,右侧3个灯轮流顺序点亮,其规律如图5.4.2b所示,左侧灯全灭。
假设电路的输入时钟信号为CP,CP的频率对应于汽车尾灯所要求的闪烁频率。试根据上述要求设计出一个时钟同步的状态机来控制汽车的尾灯。
选择Moore状态机设计该电路,则尾灯的亮、灭直接由状态译码就可以得到。由设计要求可知:汽车左转弯时,右边的灯不亮而左边的灯依次循环点亮,即0个、1个、2个或3个灯亮,分别用L、L、L、L表示,状态机在4个状态中循环。同理,汽车右转弯时,状态机也会在4个状态中循环,即左边灯不亮而右边的灯有0个、1个、2个或3个灯亮,分别用R、R、R、R,表示。由于L和R,都表示6个灯不亮,所以合起来用IDLE表示。
状态机一旦左循环或者右循环开始后,如果刹车信号HAZ有效,状态机不会立即响应,而是必须等到左(或右)循环完成后才会进入告警状态。经过改进且具有这一特性的状态图如下图所示。

由于电路的输出信号较多,不便于写在状态图中,所以单独列出输出逻辑真值表,如下表所示。

2. 实验模块程序代码和激励代码
(1)设计模块代码
`define IDEL 3'b001//均不亮 `define LR3 3'b100//均亮 `define L1 3'b011//左侧亮一个灯 `define L2 3'b010//左侧亮两个灯 `define L3 3'b000//左侧亮三个灯 `define L1 3'b011//左侧亮一个灯 `define R1 3'b101//右侧亮一个灯 `define R3 3'b110//右侧亮两个灯 `define R2 3'b111//右侧亮三个灯 module carLight(RST,CLK,LEFT,RIGHT,HAZ,RA,RB,RC,LA,LB,LC); input RST,CLK,LEFT,RIGHT,HAZ; output reg RA,RB,RC,LA,LB,LC; reg[2:0] CState,NState; always@(posedge CLK or negedge RST) begin if(~RST) CState<=`IDEL; else CState<=NState; end always@(CState or LEFT or RIGHT or HAZ) begin case(CState) `IDEL:begin if(LEFT&RIGHT|HAZ) NState=`LR3; else if(LEFT&(~HAZ)&(~RIGHT)) NState=`L1; else if((~LEFT)&(~HAZ)&RIGHT) NState=`R1; else NState=`IDEL; end `L1:begin if(~(LEFT|HAZ)) NState=`IDEL; else if(LEFT&(~HAZ)&(~RIGHT)) NState=`L2; else NState=`LR3; end `L2:begin if(~(LEFT|HAZ)) NState=`IDEL; else if(LEFT&(~HAZ)&(~RIGHT)) NState=`L3; else NState=`LR3; end `L3:begin if((~LEFT)&(~HAZ)|(~RIGHT)&(~HAZ)) NState=`IDEL; else NState=`LR3; end `R1:begin if(~(RIGHT|HAZ)) NState=`IDEL; else if(RIGHT&(~HAZ)&(~LEFT)) NState=`R2; else NState=`LR3; end `R2:begin if(~(RIGHT|HAZ)) NState=`IDEL; else if(RIGHT&(~HAZ)&(~LEFT)) NState=`R3; else NState=`LR3; end `R3:begin if((~LEFT)&(~HAZ)|(~RIGHT)&(~HAZ)) NState=`IDEL; else NState=`LR3; end `LR3:begin if((~LEFT)&(~HAZ)|(~RIGHT)&(~HAZ)) NState=`IDEL; else NState=`LR3; end endcase end //状态译码过程 always@(CState) begin case(CState) `IDEL:begin {LC,LB,LA,RA,RB,RC}=6'b000_000; end `L1:begin {LC,LB,LA,RA,RB,RC}=6'b001_000; end `L2:begin {LC,LB,LA,RA,RB,RC}=6'b011_000; end `L3:begin {LC,LB,LA,RA,RB,RC}=6'b111_000; end `R1:begin {LC,LB,LA,RA,RB,RC}=6'b000_100; end `R2:begin {LC,LB,LA,RA,RB,RC}=6'b000_110; end `R3:begin {LC,LB,LA,RA,RB,RC}=6'b000_111; end `LR3:begin {LC,LB,LA,RA,RB,RC}=6'b111_111; end endcase end endmodule
(2)激励模块代码
`timescale 1 ps/ 1 ps module carLight_vlg_tst(); // constants // general purpose registers reg eachvec; // test vector input registers reg CLK; reg HAZ; reg LEFT; reg RIGHT; reg RST; // wires wire LA; wire LB; wire LC; wire RA; wire RB; wire RC; // assign statements (if any) carLight i1 ( // port map - connection between master ports and signals/registers .CLK(CLK), .HAZ(HAZ), .LA(LA), .LB(LB), .LC(LC), .LEFT(LEFT), .RA(RA), .RB(RB), .RC(RC), .RIGHT(RIGHT), .RST(RST) ); initial begin RST<=0;CLK<=0;LEFT<=0;RIGHT<=0;HAZ<=0; #10 RST<=1; #30 LEFT<=1;HAZ<=0;RIGHT<=0; #90 LEFT<=0;HAZ<=0;RIGHT<=0; #30 LEFT<=0;HAZ<=0;RIGHT<=1; #90 LEFT<=0;HAZ<=0;RIGHT<=0; #30 LEFT<=1;HAZ<=0;RIGHT<=0; #30 LEFT<=1;HAZ<=0;RIGHT<=1; #30 LEFT<=0;HAZ<=0;RIGHT<=0; #30 LEFT<=0;HAZ<=0;RIGHT<=1; #30 LEFT<=1;HAZ<=0;RIGHT<=1; #30 LEFT<=0;HAZ<=0;RIGHT<=0; #30 LEFT<=0;HAZ<=1;RIGHT<=0; #30 LEFT<=0;HAZ<=0;RIGHT<=0; $stop; end always #5 CLK<=~CLK; endmodule
3. 波形仿真图

4.门级电路图

设计模块所占用器件的资源情况如下所示:

【实验三】设计一个10层楼的电梯控制器模块
1. 实验内容与原理说明
要求:(1) 以按键的时间先后优先级进行设计;
或者 (2) 以楼层最短位置先后优先级进行设计.
由题意可知,因为每层楼设有上下两个按钮,其中1层只能有上楼请求,10层只能有下楼请求,同一层不能既有上楼请求又有下楼请求。上楼或下楼请求被响应后对应位清零。当有其中一层的按钮按下时,电梯前往;根据时间优先级,可以设置先按下的请求先响应;根据位置优先级,可以设置距离近的请求先响应。可以设置clk,reset,up1-up9,down2-down10共计20个端口,用来输入时钟信号、复位信号和每层楼的上下请求。
有限状态机共stopon1,dooropen,doorclose,wait1, wait2, wait3, wait4, up, down, stop十个状态,分别对应停在一楼、开门、关门、等待(共4s)、上、下、停止十个工作状态。

由上分析,可以绘制其仿真的状态图如下:

整体仿真的流程图如下:

2. 实验模块程序代码和激励代码
(1)设计模块代码
module Lift(CLK,RESET,up,down,button,pos); //定义时钟和复位信号 input CLK,RESET; //定义10位上、下楼请求信号和选择的楼层输入信号 input [10:1] up,down,button; //4位的当前楼层的输出信号 output reg [3:0] pos; reg [3:0] P; //定义10位的电梯需要停下开门的楼层的信号 reg [10:1] FLOOR; //定义上下楼指示信号 reg up_down; //定义tmp为楼层指示信号,flag为非同相的请求 reg tmp,flag; integer temp; //使用one-hot码编码的状态指示信号 reg [8:0] CState,NState; parameter S0=9'b000000001,S1=9'b000000010,S2=9'b000000100,S3=9'b000001000,S4=9'b000010000,S5=9'b000,S6=9'b00,S7=9'b0,S8=9'b;//使用独热码对状态进行编码 //定义状态转换代码段 always@(posedge CLK or negedge RESET) begin if(~RESET) CState<=S0;//复位到S0 else CState<=NState;//调整到下一个状态 end //定义状态转换条件模块 always@(RESET or CState or up_down or up or down or button or P or flag) begin //若复位信号有效 if(~RESET) begin up_down=0;//将上升下降信号复位 FLOOR=10'b0;//将要开门的楼层的指示信号复位 P=4'b0001;//复位在1楼 flag=0;//复位为没有非同向请求 end else begin//若复位信号无效,开始正常运行 if(flag==0)//如果没有非同向请求 FLOOR=up_down?down|button:up|button; //在上楼时,要开门的楼层就是有上楼请求信号的楼层和电梯内要去的楼层. case(CState) S0://定义停驻状态 begin pos=P; //输出当前所在的楼层位置 if(FLOOR==10'b0) NState=S0; //如果要开门的楼层信号为空,则次态仍为等待状态 else begin //如果要开门的楼层的信号不为空,也就是在运行或有请求信号 if(up_down==0) begin//如果正在上升 if(P==4'b1010) up_down=1;//在10楼时,由于无法上升,因此将模式改为下降 else begin//若非顶层 case(P) 4'b0001: tmp=FLOOR[2] | FLOOR[3] | FLOOR[4] | FLOOR[5] | FLOOR[6] | FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10];//如果要去当前层以上的任意一层,tmp为1 4'b0010: tmp=FLOOR[3] | FLOOR[4] | FLOOR[5] | FLOOR[6] | FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10]; 4'b0011: tmp=FLOOR[4] | FLOOR[5] | FLOOR[6] | FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10]; 4'b0100: tmp=FLOOR[5] | FLOOR[6] | FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10]; 4'b0101: tmp=FLOOR[6] | FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10]; 4'b0110: tmp=FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10]; 4'b0111: tmp=FLOOR[8] | FLOOR[9] | FLOOR[10]; 4'b1000: tmp=FLOOR[9] | FLOOR[10]; 4'b1001: tmp=FLOOR[10]; endcase if(tmp==0) begin FLOOR=down|button; case(P) 4'b0001: tmp=FLOOR[2] | FLOOR[3] | FLOOR[4] | FLOOR[5] | FLOOR[6] | FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10]; 4'b0010: tmp=FLOOR[3] | FLOOR[4] | FLOOR[5] | FLOOR[6] | FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10]; 4'b0011: tmp=FLOOR[4] | FLOOR[5] | FLOOR[6] | FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10]; 4'b0100: tmp=FLOOR[5] | FLOOR[6] | FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10]; 4'b0101: tmp=FLOOR[6] | FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10]; 4'b0110: tmp=FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10]; 4'b0111: tmp=FLOOR[8] | FLOOR[9] | FLOOR[10]; 4'b1000: tmp=FLOOR[9] | FLOOR[10]; 4'b1001: tmp=FLOOR[10]; endcase if(tmp==0) up_down=1; else begin flag=1; up_down=0; end end end end else begin if(P==4'b0001) up_down=0; else begin case(P) 4'b1010: tmp=FLOOR[9] | FLOOR[8] | FLOOR[7] | FLOOR[6] | FLOOR[5] | FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1]; 4'b1001: tmp=FLOOR[8] | FLOOR[7] | FLOOR[6] | FLOOR[5] | FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1]; 4'b1000: tmp=FLOOR[7] | FLOOR[6] | FLOOR[5] | FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1]; 4'b0111: tmp=FLOOR[6] | FLOOR[5] | FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1]; 4'b0110: tmp=FLOOR[5] | FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1]; 4'b0101: tmp=FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1]; 4'b0100: tmp=FLOOR[3] | FLOOR[2] | FLOOR[1]; 4'b0011: tmp=FLOOR[2] | FLOOR[1]; 4'b0010: tmp=FLOOR[1]; endcase if(tmp==0) begin FLOOR=up|button; case(P) 4'b1010: tmp=FLOOR[9] | FLOOR[8] | FLOOR[7] | FLOOR[6] | FLOOR[5] | FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1]; 4'b1001: tmp=FLOOR[8] | FLOOR[7] | FLOOR[6] | FLOOR[5] | FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1]; 4'b1000: tmp=FLOOR[7] | FLOOR[6] | FLOOR[5] | FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1]; 4'b0111: tmp=FLOOR[6] | FLOOR[5] | FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1]; 4'b0110: tmp=FLOOR[5] | FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1]; 4'b0101: tmp=FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1]; 4'b0100: tmp=FLOOR[3] | FLOOR[2] | FLOOR[1]; 4'b0011: tmp=FLOOR[2] | FLOOR[1]; 4'b0010: tmp=FLOOR[1]; endcase if(tmp==0) up_down=0; else begin flag=1; up_down=1; end end end end NState=S1; end end S1: NState=S2; S2: NState=S3; S3: NState=S4; S4: begin if(up_down==0) NState=S5; else NState=S6; end S5: begin if(FLOOR==10'b0) NState=S0; else begin P=P+1; if(flag==1) begin: B1 integer i; temp=0; for(i=10;i>0&&temp==0;i=i-1) if(FLOOR[i]==1) temp=i; if(P==temp) begin flag=0; up_down=1; NState=S0; end else NState=S7; end else begin if(FLOOR[P]) NState=S0; else NState=S7; end end end S6: begin if(FLOOR==10'b0) NState=S0; else begin P=P-1; if(flag==1) begin:B2 integer i; temp=0; for(i=1;i<11&&temp==0;i=i+1) if(FLOOR[i]==1) temp=i; if(P==temp) begin flag=0; up_down=0; NState=S0; end else NState=S8; end else begin if(FLOOR[P]) NState=S0; else NState=S8; end end end S7: NState=S5; S8: NState=S6; endcase end end endmodule
(2)激励模块代码
// Verilog Test Bench template for design : Lift // // Simulation tool : ModelSim (Verilog) // `timescale 1 ps/ 1 ps module Lift_vlg_tst(); // constants // general purpose registers reg eachvec; // test vector input registers reg CLK; reg RESET; reg [10:1] button; reg [10:1] down; reg [10:1] up; // wires wire [3:0] pos; // assign statements (if any) Lift i1 ( // port map - connection between master ports and signals/registers .CLK(CLK), .RESET(RESET), .button(button), .down(down), .pos(pos), .up(up) ); always begin CLK=1'b0; #5 CLK=1'b1; #5; end initial begin RESET=1'b0; #10 RESET=1'b1; #790 $stop; end initial begin up=10'b0; #10 up=10'b0000010001; #40 up=10'b0000010000; #160 up=10'b0; end initial begin down=10'b0; #210 down=10'b; #180 down=10'b0; #60 down=10'b0; #120 down=10'b0000; #40 down=10'b0; end initial begin button=10'b0; #10 button=10'b0000001000; #140 button=10'b0; #20 button=10'b00; #140 button=10'b0; #40 button=10'b0000; #200 button=10'b0; #20 button=10'b0000000001; #180 button=10'b0; end endmodule
3. 波形仿真图

4.门级电路图

设计模块所占用器件的资源情况如下所示:

【实验结果及思考】
此次实验有关有限状态机的设计,包括一个交通红绿灯控制器模块,实现主干道和支路之间红绿黄灯的信号转换,小轿车尾灯控制器模块以及设计一个10层楼的电梯控制器模块。总体来说是上学期数电中有关状态机的实际应用,但是给我思路上的启发是巨大的,帮助我从实践的角度理解Mealy状态图和Moore状态图。也帮助我捋清了状态机的设计步骤,即:
1)依据具体的设计原则,确定采用Moore状态机还是Mealy状态机。
2)分析设计要求列出状态机的所有状态,并对每一个状态进行状态编码
3)根据状态转移关系和输出函数画出状态图。
4)根据所画的状态图,采用硬件描述语言对状态机进行描述。
对状态机的各个状态赋予一组特定的二进制数称为状态编码。在状态机的编码中,我尝试了自然二进制编码、格雷编码和One-Hot编码。通过占用情况可以很明显地看出自然二进制码和格雷码的编码方案使用的触发器较少,其编码效率较高,但负责根据当前状态和状态转换条件进行译码的组合电路会比较复杂,其逻辑规模也较大,使得次态逻辑在传输过程中需要经过多级逻辑,从而影响电路的工作速度。在设计的过程中,我也在实践中复习了ASM的相关知识。通过ASM图设计数字系统,可以很容易将语言描述的设计问题变成时序流程图的描述。根据时序流程图就可以得到电路的状态图和输出函数,从而得出相应的硬件电路。在设计的过程中体会到了它的便利之处。
同时,这次实验让我懂得了理论与实际相结合是很重要的,只有上课所学到的理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论、验证结论,才能真正提高自己的实际动手和独立思考的能力。在设计的过程中遇到问题,通过查阅资料、查阅手册及共同讨论的方式,最终解决了遇到的难关。
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/218737.html原文链接:https://javaforall.net
