07 A B 从计数器到可控线性序列机

07. A.从计数器到可控线性序列机

  1. 让LED灯按照亮0.25秒。灭0.75秒的状态循环亮灭
  2. 让LED灯按照亮0.25秒,灭0.5秒,亮0.75秒,灭1秒的状态循环亮灭
  3. 让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随即指定。以0.25秒为一个变化周期,8个变化状态为一个循环。
  4. 让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随机指定。8个变化状态为一个循环,每个变化状态的时间值可以根据不同的应用场景选择。
  5. 让多个LED灯按照设置的模式各自在一个变化循环内独立亮灭变化
  6. 每隔10ms,让LED灯的一个8状态循环执行一次(每个状态的变化时间值小一点,方便测试,比如设置为10us)

1.让LED灯按照亮0.25秒。灭0.75秒的状态循环亮灭

07 A B 从计数器到可控线性序列机_第1张图片

设计代码

module counter_led1(
	clk,
	rstn,
	led
);
	
	parameter MCNT = 50000000;
	input clk;
	input rstn;
	output reg led;
	
	reg[25:0] counter;
	always@(posedge clk or negedge rstn)
	if(!rstn)
		counter <= 0;
	else if(counter == MCNT-1)
		counter <= 0;
	else
		counter <= counter + 1'd1;
		
	always@(posedge clk or negedge rstn)
	if(!rstn)   
		led <= 0;
	else if(counter == 3*MCNT/4 -1)
		led <= 1;
	else if(counter == MCNT - 1)
		led <= 0;
		
endmodule

仿真代码

`timescale 1ns / 1ns

module counter_led1_tb();
    
    reg clk;
    reg rstn;
    wire led;
    
    counter_led1 counter_led1_inst(
        .clk(clk),
        .rstn(rstn),
        .led(led)
    );
    defparam counter_led1_inst.MCNT = 50000;
    
    initial clk = 1;
    always #10 clk = !clk;
    
    initial begin
        rstn = 0;
        #201;
        rstn = 1;
        #2000000;
        $stop;
    end
    
endmodule

仿真波形

07 A B 从计数器到可控线性序列机_第2张图片

2.让LED灯按照亮0.25秒,灭0.5秒,亮0.75秒,灭1秒的状态循环亮灭

设计代码

module counter_led2(
	clk,
	rstn,
	led
);
	
	parameter MCNT = 1250000000;
	input clk;
	input rstn;
	output reg led;
	
	reg[25:0] counter;
	always@(posedge clk or negedge rstn)
	if(!rstn)
		counter <= 0;
	else if(counter == MCNT-1)
		counter <= 0;
	else
		counter <= counter + 1'd1;
		
	always@(posedge clk or negedge rstn)
	if(!rstn)   
		led <= 1;
	else if(counter == MCNT/10 -1)
		led <= 0;
	else if(counter == 3*MCNT/10 - 1)
		led <= 1;
    else if(counter == 6*MCNT/10 - 1)
		led <= 0;
	else if(counter == MCNT - 1)
		led <= 1;
		
endmodule

仿真代码

`timescale 1ns / 1ns

module counter_led2_tb();
    
    reg clk;
    reg rstn;
    wire led;
    
    counter_led2 counter_led1_inst(
        .clk(clk),
        .rstn(rstn),
        .led(led)
    );
    defparam counter_led1_inst.MCNT = 125000;
    
    initial clk = 1;
    always #10 clk = !clk;
    
    initial begin
        rstn = 0;
        #201;
        rstn = 1;
        #200000000;
        $stop;
    end
    
endmodule

仿真波形

07 A B 从计数器到可控线性序列机_第3张图片

3.让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随即指定。以0.25秒为一个变化周期,8个变化状态为一个循环。

思路:2秒为一个周期;有一个指定亮灭状态的输入端口,控制八种状态的亮灭,如果把亮灭看成1和0,那么就可以设计一个八位的控制亮灭状态的端口。

设计代码

  1. ctrl的输入端口不要加reg,ctrl虽然在always块内,但是没有被赋值,led被赋值。在tb里ctrl需要加reg。
  2. 当else if语句比较多是,我们可以将其替换为case语句,case语句的default不要忘记。
module counter_led3(
	clk,
	rstn,
	ctrl,
	led
);
	
	parameter MCNT = 1000000000;
	input clk;
	input rstn;
	input [7:0] ctrl; //注意:不能加reg
	output reg led;
	
	reg[25:0] counter;
	always@(posedge clk or negedge rstn)
	if(!rstn)
		counter <= 0;
	else if(counter == MCNT-1)
		counter <= 0;
	else
		counter <= counter + 1'd1;
		
//	always@(posedge clk or negedge rstn)
//	if(!rstn)   
//		led <= 0;
//	else if(counter == MCNT/8 -1)
//		led <= ctrl[0];
//	else if(counter == 2*MCNT/8 - 1)
//		led <= ctrl[1];
//    else if(counter == 3*MCNT/8 - 1)
//		led <= ctrl[2];
//	else if(counter == 4*MCNT/8 - 1)
//		led <= ctrl[3];
//	else if(counter == 5*MCNT/8 - 1)
//		led <= ctrl[4];
//	else if(counter == 6*MCNT/8 - 1)
//		led <= ctrl[5];
//	else if(counter == 7*MCNT/8 - 1)
//		led <= ctrl[6];
//	else if(counter == MCNT - 1)
//		led <= ctrl[7];
		
	always@(posedge clk or negedge rstn)
	if(!rstn)  
	    led <= 0;
	else case(counter)
	   1*MCNT/8 - 1 : led <= ctrl[0];
	   2*MCNT/8 - 1 : led <= ctrl[1];
	   3*MCNT/8 - 1 : led <= ctrl[2];
	   4*MCNT/8 - 1 : led <= ctrl[3];
	   5*MCNT/8 - 1 : led <= ctrl[4];
	   6*MCNT/8 - 1 : led <= ctrl[5];
	   7*MCNT/8 - 1 : led <= ctrl[6];
	   8*MCNT/8 - 1 : led <= ctrl[7];
	   default : led <= led;
	endcase
	
endmodule

3.1 仿真代码 (set as top)

`timescale 1ns / 1ns

module counter_led3_tb();
    
    reg clk;
    reg rstn;
    reg [7:0] ctrl;
    wire led;
    
    counter_led3 counter_led3_inst(
        .clk(clk),
        .rstn(rstn),
        .ctrl(ctrl),
        .led(led)
    );
    defparam counter_led3_inst.MCNT = 1000000;
    
    initial clk = 1;
    always #10 clk = !clk;
    
    initial begin
        rstn = 0;
        #201;
        rstn = 1;
        #2000;
        ctrl = 8'b10000110;
        #100000000;
        ctrl = 8'b10100110;
        #200000000;
        $stop;
    end
    
endmodule

仿真波形

总结:计数器不仅仅是一个计量整个时间的一个计数器,而且这个计数器里面的每一个计数值,他都可以作为整个这一段时间里面的一个刻度标尺,都可以拿来用

4.让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随机指定。8个变化状态为一个循环,每个变化状态的时间值可以根据不同的应用场景选择。

设计文件

  1. 使用case语句时,每种情况的值必须是一个确定值,在这种情况下,我们必须修改代码,使各个状态由确定值来给定,而不是不确定的时间。

  2. timer的数据位宽与counter的数据位宽须保持一致
module counter_led4(
	clk,
	rstn,
	ctrl,
	times,
	led
);
	
	input clk;
	input rstn;
	input [7:0] ctrl; 
	input [31:0] times; 
	output reg led;
	
	reg[31:0] counter;
	always@(posedge clk or negedge rstn)
	if(!rstn)
		counter <= 0;
	else if(counter == times - 1'd1) //times的数据位宽与counter的数据位宽须保持一致
		counter <= 0;
	else
		counter <= counter + 1'd1;
    
    reg [2:0]counter2;
    always@(posedge clk or negedge rstn)
	if(!rstn)
		counter2 <= 0;
	else if(counter == times - 1'd1)
	   counter2 <= counter2 + 1'd1;
		
		
	always@(posedge clk or negedge rstn)
	if(!rstn)  
	    led <= 0;
	else case(counter2)
	   0 : led <= ctrl[0];
	   1 : led <= ctrl[1];
	   2 : led <= ctrl[2];
	   3 : led <= ctrl[3];
	   4 : led <= ctrl[4];
	   5 : led <= ctrl[5];
	   6 : led <= ctrl[6];
	   7 : led <= ctrl[7];
	   default : led <= led;
	endcase
	
endmodule

仿真文件

`timescale 1ns / 1ns

module counter_led4_tb();
    
    reg clk;
    reg rstn;
    reg [7:0] ctrl;
    reg [31:0] times;
    wire led;
    
    counter_led4 counter_led4_inst(
        .clk(clk),
        .rstn(rstn),
        .ctrl(ctrl),
        .times(times),
        .led(led)
    );
    
    initial clk = 1;
    always #10 clk = !clk;
    
    initial begin
        rstn = 0;
        #201;
        rstn = 1;
        #2000;
        times = 32'd2500;
        ctrl = 8'b10000110;
        #100000000;
        times = 32'd10000;
        ctrl = 8'b10100110;
        #200000000;
        $stop;
    end
    
endmodule

仿真波形

07 A B 从计数器到可控线性序列机_第4张图片

5.让多个LED灯按照设置的模式各自在一个变化循环内独立亮灭变化

  1. 在4的基础上多设置几个led灯输出端口即可,此处设置了3个led灯。SPI,IIC等都用到了该相似的原理。
module counter_led5(
	clk,
	rstn,
	ctrla,ctrlb,ctrlc,
	times,
	led1,led2,led3
);
	
	input clk;
	input rstn;
	input [7:0] ctrla,ctrlb,ctrlc; 
	input [31:0] times; 
	output reg led1,led2,led3;
	
	reg[31:0] counter;
	always@(posedge clk or negedge rstn)
	if(!rstn)
		counter <= 0;
	else if(counter == times - 1'd1) 
		counter <= 0;
	else
		counter <= counter + 1'd1;
    
    reg [2:0]counter2;
    always@(posedge clk or negedge rstn)
	if(!rstn)
		counter2 <= 0;
	else if(counter == times - 1'd1)
	   counter2 <= counter2 + 1'd1;
		
		
	always@(posedge clk or negedge rstn)
	if(!rstn)  
	    begin led1 <= 0; led2 <= 0; led3 <= 0; end
	else case(counter2)
	   0 : begin led1 <= ctrla[0]; led2 <= ctrlb[0]; led3 <= ctrlc[0]; end
	   1 : begin led1 <= ctrla[1]; led2 <= ctrlb[1]; led3 <= ctrlc[1]; end
	   2 : begin led1 <= ctrla[2]; led2 <= ctrlb[2]; led3 <= ctrlc[2]; end
	   3 : begin led1 <= ctrla[3]; led2 <= ctrlb[3]; led3 <= ctrlc[3]; end
	   4 : begin led1 <= ctrla[4]; led2 <= ctrlb[4]; led3 <= ctrlc[4]; end
	   5 : begin led1 <= ctrla[5]; led2 <= ctrlb[5]; led3 <= ctrlc[5]; end
	   6 : begin led1 <= ctrla[6]; led2 <= ctrlb[6]; led3 <= ctrlc[6]; end
	   7 : begin led1 <= ctrla[7]; led2 <= ctrlb[7]; led3 <= ctrlc[7]; end
	   default : begin led1 <= led1; led2 <= led2; led3 <= led3; end
	endcase
	
endmodule

07. B.受控线性序列机课题的实现

6.每隔10ms,让LED灯的一个8状态循环执行一次(每个状态的变化时间值小一点,方便测试,比如设置为10us)

原理图:

07 A B 从计数器到可控线性序列机_第5张图片

总结:通过控制en的状态就能控制计数器的计数,通过计数器的计数,来产生不同的序列,即从计数器到可控状态序列机。

设计代码

module counter_led6(
	clk,
	rstn,
	ctrl,
	times,
	led
);
	parameter MCNT = 500000;//10ms计数器
	input clk;
	input rstn;
	input [7:0] ctrl; 
	input [31:0] times; 
	output reg led;
	
	reg [31:0] counter0;
	//10ms周期计数器
	always@(posedge clk or negedge rstn)
	if(!rstn)
	   counter0 <= 0;
	else if(counter0 == MCNT - 1'd1)
	   counter0 <= 0;
	else
	   counter0 <= counter0 + 1'd1;
	   
	reg EN;   
	always@(posedge clk or negedge rstn)
	if(!rstn)
	   EN <= 0;
	else if(counter0 == 0)
	   EN <= 1'd1;
	else if(counter0 == 8*times - 1)
	   EN <= 0;
	
	reg[31:0] counter1;
	always@(posedge clk or negedge rstn)
	if(!rstn)
		counter1 <= 0;
	else if(EN == 1) begin
        if(counter1 == times - 1'd1) 
            counter1 <= 0;
        else
            counter1 <= counter1 + 1'd1;
    end
    else 
        counter1 <= 0;
    
    reg [2:0]counter2;
    always@(posedge clk or negedge rstn)
	if(!rstn)
		counter2 <= 0;
	else if(EN == 1)begin
	   if(counter1 == times - 1'd1)
	       counter2 <= counter2 + 1'd1;
	end
	else
	   counter2 <= 0;
		
		
	always@(posedge clk or negedge rstn)
	if(!rstn)  
	    led <= 0;
	else case(counter2)
	   0 : led <= ctrl[0];
	   1 : led <= ctrl[1];
	   2 : led <= ctrl[2];
	   3 : led <= ctrl[3];
	   4 : led <= ctrl[4];
	   5 : led <= ctrl[5];
	   6 : led <= ctrl[6];
	   7 : led <= ctrl[7];
	   default : led <= led;
	endcase
	
endmodule

仿真代码

`timescale 1ns / 1ns

module counter_led6_tb();
    
    reg clk;
    reg rstn;
    reg [7:0] ctrl;
    reg [31:0] times;
    wire led;
    
    counter_led6 counter_led6_inst(
        .clk(clk),
        .rstn(rstn),
        .ctrl(ctrl),
        .times(times),
        .led(led)
    );
    
    initial clk = 1;
    always #10 clk = !clk;
    
    initial begin
        rstn = 0;
        #201;
        rstn = 1;
        #2000;
        times = 32'd500;
        ctrl = 8'b10000110;
        #100000000;
        ctrl = 8'b10100110;
        #200000000;
        $stop;
    end
    
endmodule

仿真波形

07 A B 从计数器到可控线性序列机_第6张图片

6.1 代码调试(添加设计信号到波形中)

 07 A B 从计数器到可控线性序列机_第7张图片

你可能感兴趣的:(verilog学习,fpga开发,笔记,学习,经验分享)