有限状态机是指输出取决于过去输入部分和当前输入部分的时序逻辑电路。有限状态机又可以认为是组合逻辑和寄存器逻辑的一种组合。状态机特别适合描述那些发生有先后顺序或者有逻辑规律的事情,其实这就是状态机的本质。状态机就是对具有逻辑顺序或时序规律的事件进行描述的一种方法
在实际的应用中根据状态机的输出是否与输入条件相关,可将状态机分为两大类,即摩尔 (Moore)型状态机和米勒 (Mealy) 型状态机。
修改了一下,加了输入输出端口,以及触发条件
module test(red,amber,green ,able);
input able;
output red,amber,green;
reg clock,red,amber,green;
parameter on=1,off=0,red_tics=350,green_tics=200,amber_tics=30;
//交通灯初始化
initial red=off;
initial amber=off;
initial green=off;
//交通灯控制时序
always
wait(able)
begin
red=on;//开红灯
light(red,red_tics);//调用等待任务
green=on;//开绿灯
light(green,green_tics);//等待
amber=on;//开黄灯
light(amber,amber_tics);//等待
end
//定义交通灯开启时间的任务
task light;
output color;
input [31:0]tics;
begin
repeat(tics)
@(posedge clock);
color=off;
end
endtask
always
begin
#100 clock=0;
#100 clock=1;
end
endmodule
module pwm(sys_clk, led,led1);
input sys_clk; // 系统时钟
output led; // 输出 PWM信号
output reg led1; // 输出寄存器位 led1
reg PWM; // 定义寄存器位 PWM
reg [25:0] count; // 定义26位计数器 count
//LED亮度分为254个级别
reg [7:0] light; // 定义8位寄存器 它的值 0000_0000 到 1111_1111共255个
// 估计 0000_0000 代表无亮度,所以亮度分254个级别
//计数器
always@(posedge sys_clk)
count<=count+1; // 每经过一个系统时钟上升沿,26位计数器count加一
//级别跳变,跳变速度可由count[n]调节
always@(posedge count[16])begin // 计数器count的第16位 作为时钟上升沿,即count[15:0]
// 从16'h0000计数到 16'hffff共 65536个系统时钟脉冲
light<=light-1; // 每经过一个上升沿(65536个系统时钟脉冲), // 8位亮度寄存器减一,即亮度降一个级别
led1<=~led1; // 同时,led1寄存器位的值翻转一次
end
//PWM频率:clk从0计到17'h1FFFF为一个周期
always@(sys_clk)
if(count[16:0] < {light,9'b0}) // 如果计数器count[16:9] 小于 light亮度值,PWM 为0
PWM<=0;
else // 计数器count[16:9] 大于 light亮度值,PWM 为1
PWM<=1;
assign led=PWM; // 将PWM值输出给 led 端口
endmodule
// led1是每次发生亮度级别跳变时,改变一次状态,点亮或者熄灭
// led是 PWM输出,亮度渐变的过程,由亮变暗,由暗变亮
// 级别跳变可以通过 count[n]中n的数值来改变,n 越大,渐变越慢
always @(posedge spi_clk or negedge reset )
begin
if(cmd==2'b10)
begin
if(~reset)
begin
shifter_wr<=32'b0;
mosi<=1'bz;
wr_count<=1'b0;
end
else if (wr_count<=6'h1f)
begin
#2;
mosi<=shifter_wr[6'h1f-wr_count];
wr_count<=wr_count+6'h1;
end
else if (wr_count==6'h20)
wr_count<=6'b0;
end
end
用 quartus 160 编译,没啥问题,可以通过。
可能你编译用的verilog版本选用2001的试试吧。
verilog编译选用 verilog-2001,如下图:
还有最好这样写:
always @(posedge spi_clk or negedge reset )begin
if(~reset)
begin
shifter_wr<=32'b0;
mosi<=1'bz;
wr_count<=1'b0;
end
else
if(cmd == 2'b10)
begin
if (wr_count<=6'h1f)
begin
#2;
mosi<=shifter_wr[6'h1f-wr_count];
wr_count<=wr_count+6'h1;
end
else if (wr_count==6'h20)
wr_count<=6'b0;
end
end
把 if(cmd == 2'b10) 判断条件写在复位条件之后,不然会报错。
很高兴回答你的问题!
如果以下回答合适,请采纳;如果不恰当,继续讨论。谢谢!
该题本质上是有限状态机的设计问题。令所要完成的功能要求包含四种模式,分别是①从左到右点亮,②从右到左点亮,③从两边到中间点亮,④从中间到两边点亮。要求四种模式依次切换,循环执行。
令clk为led流水灯(共计12个LED灯)的驱动时钟要求低频,如1Hz,rst为上升沿复位信号(异步)。则所实现的Verilog HDL代码部分如下:
module led_run(clk,led,rst);
input clk; //clk with low frequency like 1Hz
input rst; //system reset signal
output [11:0] led; //denotes 12 leds,
reg [11:0] led;
reg [2:0] state; //state variable,internal signals
reg [5:0] count; //control signals of the state diagram,internal signals
always @(posedge clk or posedge rst) //the state diagram
if (rst)
begin
state <= 3'b000;
count <= 6'b000000;
end
else
case(state)
详细代码见附件。
该代码的仿真波形如下图所示(注led低电平为亮,高电平为灭)
module HDLC(RXD,RXCLK,RXSET,TXCLK,TXD,TXDS); //module 头,verilog 95风格
input RXD; //输入信号
input RXCLK; //输入时钟
input RXSET; //输入的复位信号
output[7:0]TXD; //输出的数据,8bit
reg [7:0]TXD; //输出寄存器
output[2:0]TXDS; //输出信号
reg [2:0]TXDS; //输出寄存
output TXCLK; //输出的时钟
reg TXCLK; //输出时钟寄存
reg RXD_D1; //输入的数据寄存器。单比特
reg RXD_D2;
reg RXD_D3;
reg RXD_D4;
reg RXD_D5;
reg RXD_D6;
reg RXD_D7;
reg RXD_D8; //输入的数据寄存器。单比特
//在接收rxclk下,每个时候域接收rxd数据,寄存一级
always @(posedge RXCLK or negedge RXSET)
if(!RXSET)
RXD_D1<=1'b0;
else RXD_D1<=RXD;
//在接收rxclk下,每个时候域接收rxd数据,寄存二级,即打两拍
always @(posedge RXCLK or negedge RXSET)
if(!RXSET)
RXD_D2<=1'b0;
else RXD_D2<=RXD_D1;
//寄存三级,即打三拍
always @(posedge RXCLK or negedge RXSET)
if(!RXSET)
RXD_D3<=1'b0;
else RXD_D3<=RXD_D2;
always @(posedge RXCLK or negedge RXSET)
if(!RXSET)
RXD_D4<=1'b0;
else RXD_D4<=RXD_D3;
always @(posedge RXCLK or negedge RXSET)
if(!RXSET)
RXD_D5<=1'b0;
else RXD_D5<=RXD_D4;
always @(posedge RXCLK or negedge RXSET)
if(!RXSET)
RXD_D6<=1'b0;
else RXD_D6<=RXD_D5;
always @(posedge RXCLK or negedge RXSET)
if(!RXSET)
RXD_D7<=1'b0;
else RXD_D7<=RXD_D6;
//寄存8级,即打8拍,
always @(posedge RXCLK or negedge RXSET)
if(!RXSET)
RXD_D8<=1'b0;
else RXD_D8<=RXD_D7;
///////////////////////////////////////////////////////////////////
////////////////////search for 01111110 indacation/////////////////
///////////////////////////////////////////////////////////////////
reg [2:0]l_cs,l_ns; //定义2个3bit的状态信号,当前态l_cs,下一个状态l_ns
//3bit的原因在于需要选择的数据为0~7,只需3bit
parameter s_hunt=3'd0,s0=3'd1,s1=3'd2,s2=3'd3,s3=3'd4,s4=3'd5,s5=3'd6,s6=3'd7;
//定义初始态s_hunt=0’
//否则选择将下一个状态l_ns赋给当前态l_cs
always @(posedge RXCLK or negedge RXSET)
if(!RXSET)
l_cs<=s_hunt;
else l_cs<=l_ns;
//下面的状态机用于寻找序列"0111111"
//如果找到当前的要寻找的输入数,则跳入到下一个状态,否则跳到s0态,开始新一轮的寻找,
//通过这种方法寻找到所需要的序列“01111110”
always @(l_cs or RXD)
case(l_cs)
s_hunt:begin
if(RXD==1'b0)
l_ns=s0;
else l_ns=s_idle;
end
s0:begin
if(RXD==1'b1)
l_ns=s1;
else l_ns=s0;
end
s1:begin
if(RXD==1'b1)
l_ns=s2;
else l_ns=s0;
end
s2:begin
if(RXD==1'b1)
l_ns=s3;
else l_ns=s0;
end
s3:begin
if(RXD==1'b1)
l_ns=s4;
else l_ns=s0;
end
s4:begin
if(RXD==1'b1)
l_ns=s5;
else l_ns=s0;
end
s5:begin
if(RXD==1'b1)
l_ns=s6;
else l_ns=s0;
end
s6:l_ns=s_idle;
endcase
//定义了寄存器SE_ind,
//该部分逻辑为组合逻辑,当找到所需要找的序列“01111110”时,输出SE_ind为1,否则为0;
//该信号相当于一个指示信号。是否找到所需的序列
reg SE_ind;
always @(l_cs or RXD)
if(l_cs==s6 && RXD==1'b0)
SE_ind=1'b1;
else SE_ind=1'b0;
以上就是关于verilog 状态机怎么用的全部的内容,包括:verilog 状态机怎么用的、verilog 程序问题,初学者,请见谅,程序代码如下、有一段程序不懂,求详解啊!verilog的等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)