Verilog小练习- 看时序写代码(09--10)

写在前面

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

仿真结果

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_41445387/article/details/107318866