写在前面
承接本系列上文。整理一些简单的根据时序图编写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
仿真结果