verilog学习总结及练习

1、一个程序模块有多个initial和always过程块,每个initial和always说明语句在仿真一开始同时立即开始执行。initial语句只执行一次,always语句则是不断循环往复的执行,所以initial过程快比较适合做变量的初始化。一个模块中可以有多个initial模块,它们都是并行运行的,initial块常用于测试文件和虚拟模块的编写。
2、mealy状态机与moore状态机的区别?
前者的输出不但取决于状态还取决于输出。moore状态机只与 当前状态有关。
3、复位信号的边沿跳变与时钟信号的要错开。

4、verilog中的begin和end类似c语言中的{},即每个分支条件下的语句只要超过一句就要加上begin end,每个模块的起始和结尾也要加上。
5、建议使用独热编码

学习了好几天了,做一些小练习(最近快放五一假了,心态有点飘哈哈)
题目一:
1、设计一个周期性产生二进制序列01001011001的序列产生器。

//确定外特性以及输入与输出
module Gen(
 input clk,input rstn,output reg dout
);
reg [4:0] c_s,n_s;
//第一个always块表示触发器内逻辑
always@(posedge clk or negedge rstn)
begin
if(!rstn)
c_s<=0;
else
c_s<=n_s;//将当前状态值存储在d触发器给到下一状态值
end
//第二个always表示状态转化逻辑 
always@(c_s)
begin
case(c_s)
0: n_s = 1;
1: n_s = 2;
...//简略
10:n_s=0;
default:n_s=0;
endcase
end
//第三个always块表示输出逻辑
always@(*)//敏感表怕漏写输入信号可以用*表示
always@(c_s)
begin
case(c_s)
0: dout =0;
1: dout = 1;
...//简略
10:dout=1;
default:dout=0;
endcase
end
endmodule    

总结:这是一个简单的时序逻辑电路,即由两个组合逻辑电路和一个d触发器组成的。这是一个moore状态机

题目二
2、设计一个密码锁,依次输入9、3、1即密码正确,发送一个正脉冲

//首先还是确定外特性,输入输出等等  在草稿纸上画出状态转移图
module lock(input clk,input rst,output reg result)
reg [3:0] key ;//定义一个四位的key
reg [4:0] c_s,n_s;

//第一个always块  还是写状态寄存器内部
always@(posedge clk or negedge rst)//如果想偷懒就都写成*号
begin  
if(!rst)
c_s<=2`b0;
else
c_s = n_s;
end
//第二个always块写状态转移逻辑
always@(c_s or key)
begin
case(c_s)
2`b00: if(key ==4`d9)
n_s = 2`b01;
else n_s = 2`b00;
2`b01: if(key==4`d3)
n_s=2`b10;
else
n_s=2`b00;
2`b10:
n_s=2`b00;
default:n_s=2`b00;
endcase
end
//第三个always块写输出逻辑
always@()
begin
case (c_s)
2`b10:
  begin
   if(key==4`d1)
   result =1`b1;
   else
     result =1`b0;
  end
     default :result =1`b0;
endcase
end
endmodule

总结:这是一个melay状态机,因为它的输出不止与状态有关,而且还与输入有关

题目三(复杂时序逻辑设计)
3、设计一个针对两个运动员的时钟秒表,输入只有时钟和按键,每按下一次key,会产生一个高电平的脉冲。假设key已做过防抖动和脉冲宽度处理。
key的主要功能是,按第一下开始计时,并显示计数值。第一个运动员到达终点时按下第二下key,这个时候秒表需要记下第一个运动员的时间,并继续输出计数值,第二个运动员到达终点后按下第三下key停止计数,输出计数值为第二个运动员的成绩,再按就是第一个运动员的成绩,再按一个清0.

//第一步确定外特性
module watch(input clk,input rst,output reg count,input key)
reg  counter1,counter2;
reg start1,start2,sel;
reg [3:0] current_state,next_state;

always @(posedge clk or negedge rst) begin
if(!rst) count1<=4'd0;
else begin
if (start1)
count1<=count1+1;
else if (clear)
count1<=4'd0;
end
end
 //一般复位信号与时钟信号要错开触发 即一高一低
 always @(posedge clk or negedge rst) begin
if(!rst) count2<=4'd0;
else begin
if (start2)
count2<=count2+1;
else if (clear)
count2<=4'd0;
end
end
ays @(posedge clk or negedge rst)
begin
if(!rst)
current_state<=3'b0;
else
current_state<=next_state; 
end
//
always @(*) begin
case(current_state)
3'b000: begin
if(key==1'b1) begin //第一次按下按键,开始计时
next_state<=3'b001; {start1,start2,clear,sel}=4'b1100; end
else begin
next_state<=3'b000; {start1,start2,clear,sel}=4'b0000; end
end
3'b001: begin
if(key==1'b1) begin //第二次按下,计数器一停止,计数器二开始
next_state<=3'b010; {start1,start2,clear,sel}=4'b0100; end
else begin
next_state<=3'b001; {start1,start2,clear,sel}=4'b1100; end
end 
3'b010:begin
if(key==1`b1)begin//第三次按下按键,停止计数,输出计数器二的值
next_state<=3'b011; {start1,start2,clear,sel}=4'b0000; end
else begin
next_state<=3'b010; {start1,start2,clear,sel}=4'b0100; end
3'b011:begin
if(key==1`b1)begin//第四次按下按键,输出计数器1的值
next_state<=3'b100;{start1,start2,clear,sel}=4'b0001;end
else begin
next_state<=3'b011; {start1,start2,clear,sel}=4'b0000; end
3'b100:begin
if(key==1`b1)begin//第五次按下按键,计数器清空
next_state<=3'b000;{start1,start2,clear,sel}=4'b0010;end
else begin
next_state<=3'b100; {start1,start2,clear,sel}=4'b0001; end

end

 //输出逻辑
always @(*)
begin
if (sel)
count<=count1;
else
count<=count2;
end
//

总结:显然这是一个milay状态机,输出与输入密切相关,而且在状态转换逻辑里面也插入了一部分输出逻辑的任务

发布了29 篇原创文章 · 获赞 8 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_42542969/article/details/89524382