目录
一、实验目的
1. 掌握同步有限状态机的设计方法。
2. 采用状态机的设计方法,设计实现带倒计时的交通灯控制电路。
二、实验环境
1. 装有ModelSim和Vivado的计算机。
2. Sword实验系统。
三、实验任务
1. 理解交通灯控制系统的应用要求,采用状态机设计方法,实现带倒计时的交通灯控制系统设计,并在ModelSim上实现功能仿真。
2. 生成FPGA设计文件,下载到Sword实验系统上验证电路功能。
四、实验原理与实验步骤
1. 实验原理
有限状态机是时序电路的通用模型,任何时序电路都可以表示为有限状态机。
状态机的基本结构如下图所示。
在一些应用中,通常希望产生任意的状态序列,并且每个状态停留任意时间。采用状态机的设计思想实现。交通灯控制系统就是其中的一个实例。
现要求东西大街和南北大街的交通灯亮灭状态如下表所示。 各个状态的延时时间如表1所示。
状态 |
南北大街 |
东西大街 |
时延(s) |
0 |
绿 |
红 |
9 |
1 |
黄 |
红 |
3 |
2 |
红 |
绿 |
9 |
4 |
红 |
黄 |
3 |
表1 交通灯状态表
2. 实验步骤
(1)根据表1,确定交通灯状态转移图,采用可综合设计风格设计状态机代码。
如果倒计时9~1,就把count初值设置为1
如果倒计时8~0,就把count初值设置为0,count<8,count<2
(2)编写测试模块,完成modelsim下电路的功能仿真,验证电路功能。
100001(21h)
100010(22h)
001100(0ch)
010100(14h)
(3)建立完成I/O引脚分配。
系统时钟为100MHz,从提供的clkdiv引出clkdiv[24](频率为6Hz)状态机的输入时钟。
用SW[0]做为clr信号。
用LED[5:3]做为东西大街红黄绿灯,以LED[2:0]做为南北大街红黄绿灯。
下板的是将分成C1和状态寄存器两个模块
(3)生成FPGA文档,并下载到实验板上物理运行,检查设计结果。在Led等状态修改的同时,数码管可以显示倒计时时间。
五、实验思考
1、总结自己设计中,倒计时时间输出的实现方法。
用counter=sec-count来实现倒计时
2、课堂给出的交通灯例子是将生成下一个状态的组合逻辑C1与状态寄存器写在一个always块中,试将其分成C1和状态寄存器两个模块。并尝试下板。
(提示:由于状态转移是在C1中通过判断对时钟的计数个数count来确实是否转移,如果要转移到下一个状态,count需要清零。但同时在状态寄存器模块中,每次来一个clock上升沿,需要对count进行加1的操作。此时就会出现在C1和状态存储器中都对count赋值,如果下板会出现类似multi-driven的提示。该如何处理,可以想一想试一试。)
代码
TOP.v
`timescale 1ns / 1ps
module TOP(input wire clk_100mhz,
// I/O:
input wire[15:0]SW,
output wire led_clk,
output wire led_clrn,
output wire led_sout,
output wire LED_PEN,
output wire seg_clk,
output wire seg_clrn,
output wire seg_sout,
output wire SEG_PEN
);
wire[31:0]Div;
wire[15:0]LED_DATA;
wire CK;
wire[63:0] disp_data;
wire[5:0] out;
wire[3:0] counter;
traffic2_2 U1(Div[24],SW[0],out,counter);
shumaguan U3(disp_data[63:56],counter);
clk_div U8(clk_100mhz,1'b0,SW[2],Div,CK);
assign disp_data[55:0]=56'hffffffffffffff;
P2S #(.DATA_BITS(64),.DATA_COUNT_BITS(6))
P7SEG (clk_100mhz,
1'b0,
Div[20],
disp_data,
seg_clk,
seg_clrn,
seg_sout,
SEG_PEN
);
LED_P2S #(.DATA_BITS(16),.DATA_COUNT_BITS(4))
PLED (clk_100mhz,
1'b0,
Div[20],
LED_DATA,
led_clk,
led_clrn,
led_sout,
LED_PEN
);
assign LED_DATA = ~{out[0],out[1],out[2],out[3],out[4],out[5],1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0};
endmodule
trafic2_2.v
module traffic2_2(
input wire clk,
input wire clr,
output reg [5:0]lights,
output reg [3:0]counter
);
reg[1:0] pstate,nstate;
reg [4:0]count;
parameter s0=2'b00,s1=2'b01,s2=2'b10,s3=2'b11;
parameter sec9=8,sec3=2;
always @(posedge clk or posedge clr)
begin
if(clr==1)
begin
//state<=s0;
pstate<=s0;
count<=0;
end
else
begin
if(pstate==s0 | pstate==s2)
if(count<sec9)
count<=count+1;
else
begin
pstate<=nstate;
count<=0;
end
else if(pstate==s1 | pstate==s3)
if(count<sec3)
count<=count+1;
else
begin
pstate<=nstate;
count<=0;
end
end
end
//C1
always@(*)
begin
case(pstate)
s0: nstate=s1;
s1: nstate=s2;
s2: nstate=s3;
s3: nstate=s0;
default nstate<=s0;
endcase
end
//C2
always @(*)
begin
case (pstate)
s0: begin lights=6'b100001;counter=sec9-count;end
s1: begin lights=6'b100010;counter=sec3-count;end
s2: begin lights=6'b001100;counter=sec9-count;end
s3: begin lights=6'b010100;counter=sec3-count;end
default begin lights=6'b100001;counter=sec9-count;end
endcase
end
endmodule
shumaguan.v
module shumaguan(out,in);
output[7:0] out;
input[3:0] in;
reg[7:0] out;
always@(in)
begin
case(in)
4'b0000: out=8'b00000011;
4'b0001: out=8'b10011111;
4'b0010: out=8'b00100101;
4'b0011: out=8'b00001101;
4'b0100: out=8'b10011001;
4'b0101: out=8'b01001001;
4'b0110: out=8'b01000001;
4'b0111: out=8'b00011111;
4'b1000: out=8'b00000001;
4'b1001: out=8'b00001001;
4'b1010: out=8'b00010001;
4'b1011: out=8'b11000001;
4'b1100: out=8'b01100011;
4'b1101: out=8'b10000101;
4'b1110: out=8'b01100001;
4'b1111: out=8'b01110001;
default: out=8'b0;
endcase
end
endmodule
clk_div.v
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 17:19:38 07/17/2012
// Design Name:
// Module Name: clk_div
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module clk_div(input clk,
input rst,
input SW2,
output reg[31:0]clkdiv,
output Clk_CPU
);
// Clock divider-时钟分频器
always @ (posedge clk or posedge rst) begin
if (rst) clkdiv <= 0; else clkdiv <= clkdiv + 1'b1; end
assign Clk_CPU = (SW2)? clkdiv[24] : clkdiv[0];
endmodule