写在前面
承接本系列上文。整理一些简单的根据时序图编写Verilog代码的实例,帮助新手学习,老手巩固。每次更新两题,根据难度会挑选一些进行讲解。
题目09
题目09答案
题目和08类似
module test09 (
input clk, // Clock
input en1, // Clock Enable
input rst_n, // Asynchronous reset active low
output reg dout
);
wire add_cnt;
wire end_cnt;
reg flag;
reg [3:0] cnt ;
assign add_cnt = flag ==1;
assign end_cnt = add_cnt && cnt== 14-1;
wire low_flag = add_cnt && (cnt== 1-1||cnt== 6-1||cnt== 10-1||cnt== 13-1);
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt <= 0;
end
else if(add_cnt)begin
if(end_cnt)
cnt <= 0;
else
cnt <= cnt + 1;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
flag <=0;
end
else if(en1==1)begin
flag <=1;
end
else if(end_cnt==1)begin
flag <=0;
end
else begin
flag <=flag;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n == 1'b0)begin
dout<= 0;
end
else if(low_flag==1)begin
dout<= 0;
end
else if(add_cnt==1)begin
dout<= 1;
end
else begin
dout<= 0;
end
end
endmodule
测试结果:
题目10
题目10答案
最简单的思路通前文的设计方法,对应的计数值设置低输出的flag
版本1
module test10 (
input clk, // Clock
input en1, // Clock Enable
input rst_n, // Asynchronous reset active low
output reg dout
);
wire add_cnt;
wire end_cnt;
reg flag;
reg [3:0] cnt ;
assign add_cnt = flag ==1;
assign end_cnt = add_cnt && cnt== 12-1;
wire low_flag = add_cnt && (cnt== 1-1||cnt== 3-1
||cnt== 4-1||cnt==7-1||cnt== 8-1 ||cnt==9-1);
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt <= 0;
end
else if(add_cnt)begin
if(end_cnt)
cnt <= 0;
else
cnt <= cnt + 1;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
flag <=0;
end
else if(en1==1)begin
flag <=1;
end
else if(end_cnt==1)begin
flag <=0;
end
else begin
flag <=flag;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n == 1'b0)begin
dout<= 0;
end
else if(low_flag==1)begin
dout<= 0;
end
else if(add_cnt==1)begin
dout<= 1;
end
else begin
dout<= 0;
end
end
endmodule
仿真结果:
同时我们观察到这里离波形变化呈现规律性,也可以采用计数器进行设计。同样也可以采用状态机。
计数器版本
module test10_1 (
input clk, // Clock
input en1, // Clock Enable
input rst_n, // Asynchronous reset active low
output reg dout
);
reg [5-1: 0] x;
reg [5-1: 0] y;
wire add_cnt;
wire end_cnt;
reg flag;
reg [3:0] cnt ;
assign add_cnt = flag ==1;
assign end_cnt = add_cnt && cnt== x+y-1;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt <= 0;
end
else if(add_cnt)begin
if(end_cnt)
cnt <= 0;
else
cnt <= cnt + 1;
end
end
wire add_cnt1;
wire end_cnt1;
reg [3:0] cnt1 ;
assign add_cnt1 = end_cnt;
assign end_cnt1 = add_cnt1 && cnt1== 3-1;
wire high_flag = add_cnt && cnt== x-1;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt1 <= 0;
end
else if(add_cnt1)begin
if(end_cnt1)
cnt1 <= 0;
else
cnt1 <= cnt1 + 1;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
flag <=0;
end
else if(en1==1)begin
flag <=1;
end
else if(end_cnt1==1)begin
flag <=0;
end
else begin
flag <=flag;
end
end
always @(*)begin
if(cnt1==0)begin
x<=1;
y<=1;
end
else if(cnt1==1)begin
x<=2;
y<=2;
end
else begin
x<=3;
y<=3;
end
end
reg dout_r;
always @(posedge clk or negedge rst_n)begin
if(rst_n == 1'b0)begin
dout_r<= 0;
end
else if(high_flag==1)begin
dout_r<= 1;
end
else if(end_cnt==1)begin
dout_r<= 0;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
dout<=0;
end
else begin
dout<=dout_r;
end
end
endmodule
状态机版本
module test10_2 (
input clk, // Clock
input en1, // Clock Enable
input rst_n, // Asynchronous reset active low
output reg dout
);
reg [4-1: 0] x;
wire add_cnt;
wire end_cnt;
reg [3:0] cnt ;
reg flag;
assign add_cnt = flag==1;
assign end_cnt = add_cnt && cnt==2*x-1;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt <= 0;
end
else if(add_cnt)begin
if(end_cnt)
cnt <= 0;
else
cnt <= cnt + 1;
end
end
//-----------------状态机-------------------
//--------------<状态机参数>----------------
parameter S0 =4'b0000,
S1 =4'b0001,
S2 =4'b0010,
S3 =4'b0100;
//---------------<信号定义>------------------
reg [4- 1 : 0] state_c, state_n;
//设计转移条件
wire S0toS1_condition = state_c== S0 && end_cnt==1;
wire S1toS2_condition = state_c== S1 && end_cnt==1;
wire S2toS3_condition = state_c== S2 && end_cnt==1;
//描述次态寄存器迁移到现态寄存器
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
state_c <= S0;
end
else begin
state_c <= state_n;
end
end
//描述状态转移条件判断
always@(*)begin
case(state_c)
S0:begin
if(S0toS1_condition)begin
state_n = S1;
end
else begin
state_n = state_c;
end
end
S1:begin
if(S1toS2_condition)begin
state_n = S2;
end
else begin
state_n = state_c;
end
end
S2:begin
if(S2toS3_condition)begin
state_n = S3;
end
else begin
state_n = state_c;
end
end
S3:begin
state_n = state_c;
end
default:begin
state_n = S0;
end
endcase
end
//输出
always @(*)begin
if(rst_n==0)begin
x<=0;
end
else if(state_c==S0)begin
x<=1;
end
else if(state_c==S1)begin
x<=2;
end
else if(state_c==S2)begin
x<=3;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
flag <=0;
end
else if(en1==1)begin
flag <=1;
end
else if(state_c==S3)begin
flag <=0;
end
else begin
flag <=flag;
end
end
reg doutr;
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
doutr<=0;
end
else if(state_c==S3)begin
doutr<=0;
end
else if(end_cnt==1)begin
doutr<=0;
end
else if(cnt==x-1 && flag==1)begin
doutr<=1;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
dout<=0;
end
else begin
dout<=doutr;
end
end
endmodule
仿真结果