Verilog中的时钟分频

前几天做一个project,实验内容如下

实验十五 摩尔状态机序列检测器(*****)1) 设计“1101”序列检测的状态转换图;2) 设计一个 8 位并转串输出模块 par2ser。该器件有 8 位输入 d[7:0],1 位输出 q,另有一个 clk 端,一个 set 端。set端上升沿将 8位输入锁存到逻辑右移移位寄存器中。3) 调用并转串输出模块,使用Verilog HDL语言的行为描述方式实现一个摩尔状态机,能检测一个8位的二进制数据中是否存在“1101”序列,如果检测到该序列则指定的LED灯亮;4) 综合、实现、生成bit流,下载到Nexys4开发板进行验证;

这个需要一个分频模块

因为basys3默认的时钟频率为100MHZ,也就是周期为10^-8s,这个下板是不会成功的,在我的理解就是时钟的变化太快,就算下板了我们用肉眼也不会看出任何变化的,所以需要分频。

分频模块如下

module clock_div(set3, clock, clk_out);
//I/O口声明
input clock, set3; //输入时钟
output reg clk_out; //输出时钟
reg[30:0]cnt;
always@(posedge clock)
begin
if(set3)
begin
cnt <= 30’d000;
clk_out <= 0;
end
if(cnt == 30’d50000000)//10^8分频
begin
cnt <= 30’d000;
clk_out <= ~clk_out;
end
else cnt <= cnt + 1’d1;
end
endmodule

在这里clock为输入时钟,clk_out为输出时钟,前面已经提到默认的时钟周期为10^-8,要让输出时钟clk_out周期是1秒,即clk_out每50000000变一次。这就是上面的分频模块所干的事。

当时写的右移并转串模块

module par2ser(clk_out, set2, d, q);//右移并转串
input clk_out;
input set2;//set2 = 1则把d中的值读到data_buff中
input [7:0] d;//输入的8个序列
output reg q;//存储右移出来的一位
reg [7:0] data_buff;
// reg[2:0] cnt; //用来计数,实现并转串
always @(posedge clk_out or posedge set2)
begin
if(set2)begin
q<=1’b0;
data_buff<=d;//就存储了八个输入
end
else
begin
data_buff <= data_buff>>1;
q<=data_buff[0];
end
end
endmodule

状态机(fsm)模块(Moore)

module check(clk_out, w, set, z);
input clk_out, set, w; //set->复位
output reg z;//z = 1说明检测到1101了
reg [3:0] cur, next;
parameter S0 = 4’b0000;
parameter S1 = 4’b0001;
parameter S2 = 4’b0010;
parameter S3 = 4’b0011;
parameter S4 = 4’b0100;
always @(posedge clk_out or posedge set)
begin
if(set)
begin cur <= S0;next <= S0;end//一定要有一个复位过程
else
begin
case(cur)
S0: next = (w1)?S1:S0;
S1: next = (w
1)?S1:S2;
S2: next = (w1)?S3:S0;
S3: next = (w
1)?S4:S2;
S4: next = (w==1)?S1:S2;
default: next = S0;
endcase
cur <= next;
end
end
always@(set or cur)
begin
if(set) z = 0;
else
case(cur)
S0 : z = 0;
S1 : z = 0;
S2 : z = 0;
S3 : z = 0;
S4 : z = 1;
default : z = 0;
endcase
end
endmodule

调用模块

module diaoyong(clock, set3, set2, set, d, z);
input set3, set2, set, clock;
input[7:0]d;
output z;
wire q, clk_out;
clock_div u3(.clock(clock), .clk_out(clk_out), .set3(set3));//这里掉了u3
par2ser u1(.clk_out(clk_out),.set2(set2),.d(d),.q(q));
check u2(.clk_out(clk_out),.set(set),.w(q),.z(z));
endmodule
这个当时是下板成功的,这个分频我搞了两天吧,一直卡到分频上
其实严格来说我的并转串模块是有问题的,没有实现标准意义上的并转串模块,下面是我重写的并转串模块

重写的并转串模块

module par2ser(clk_out, clr, d, q);//右移并转串
input clk_out;
input cl;//将data_buff中的值置为0,这样的话输出也就为0了
input [7:0] d;//输入的8个序列
output reg q;//存储右移出来的一位
reg [2:0]cnt = 3’b000;
reg [7:0] data_buff;
// reg[2:0] cnt; //用来计数,实现并转串
always @(posedge clk_out or posedge set2)
begin
if(clr)begin
data_buff <= 4’b0;
cnt = 3’b000;
end
else if(cnt > 0)
begin
data_buff[6:0] <= data_buff[7:1];
cnt = cnt - 1;
end
else if(cnt == 3’b000)
begin
cnt <= 3’b111;
data_buff <= d;//就存储了八个输入
end
q <= data_buff[0]; //这样的话就可以向右移动并且出来的是一个了
end
endmodule

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值