07. A.从计数器到可控线性序列机
- 让LED灯按照亮0.25秒。灭0.75秒的状态循环亮灭
- 让LED灯按照亮0.25秒,灭0.5秒,亮0.75秒,灭1秒的状态循环亮灭
- 让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随即指定。以0.25秒为一个变化周期,8个变化状态为一个循环。
- 让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随机指定。8个变化状态为一个循环,每个变化状态的时间值可以根据不同的应用场景选择。
- 让多个LED灯按照设置的模式各自在一个变化循环内独立亮灭变化
- 每隔10ms,让LED灯的一个8状态循环执行一次(每个状态的变化时间值小一点,方便测试,比如设置为10us)
1.让LED灯按照亮0.25秒。灭0.75秒的状态循环亮灭
设计代码
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;elsecounter <= 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 / 1nsmodule 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 beginrstn = 0;#201;rstn = 1;#2000000;$stop;endendmodule
仿真波形
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;elsecounter <= 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 / 1nsmodule 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 beginrstn = 0;#201;rstn = 1;#200000000;$stop;endendmodule
仿真波形
3.让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随即指定。以0.25秒为一个变化周期,8个变化状态为一个循环。
思路:2秒为一个周期;有一个指定亮灭状态的输入端口,控制八种状态的亮灭,如果把亮灭看成1和0,那么就可以设计一个八位的控制亮灭状态的端口。
设计代码
- ctrl的输入端口不要加reg,ctrl虽然在always块内,但是没有被赋值,led被赋值。在tb里ctrl需要加reg。
- 当else if语句比较多是,我们可以将其替换为case语句,case语句的default不要忘记。
module counter_led3(clk,rstn,ctrl,led
);parameter MCNT = 1000000000;input clk;input rstn;input [7:0] ctrl; //注意:不能加regoutput reg led;reg[25:0] counter;always@(posedge clk or negedge rstn)if(!rstn)counter <= 0;else if(counter == MCNT-1)counter <= 0;elsecounter <= 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;endcaseendmodule
3.1 仿真代码 (set as top)
`timescale 1ns / 1nsmodule 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 beginrstn = 0;#201;rstn = 1;#2000;ctrl = 8'b10000110;#100000000;ctrl = 8'b10100110;#200000000;$stop;endendmodule
仿真波形
总结:计数器不仅仅是一个计量整个时间的一个计数器,而且这个计数器里面的每一个计数值,他都可以作为整个这一段时间里面的一个刻度标尺,都可以拿来用
4.让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随机指定。8个变化状态为一个循环,每个变化状态的时间值可以根据不同的应用场景选择。
设计文件
-
使用case语句时,每种情况的值必须是一个确定值,在这种情况下,我们必须修改代码,使各个状态由确定值来给定,而不是不确定的时间。
- 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;elsecounter <= 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;endcaseendmodule
仿真文件
`timescale 1ns / 1nsmodule 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 beginrstn = 0;#201;rstn = 1;#2000;times = 32'd2500;ctrl = 8'b10000110;#100000000;times = 32'd10000;ctrl = 8'b10100110;#200000000;$stop;endendmodule
仿真波形
5.让多个LED灯按照设置的模式各自在一个变化循环内独立亮灭变化
- 在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;elsecounter <= 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; endelse case(counter2)0 : begin led1 <= ctrla[0]; led2 <= ctrlb[0]; led3 <= ctrlc[0]; end1 : begin led1 <= ctrla[1]; led2 <= ctrlb[1]; led3 <= ctrlc[1]; end2 : begin led1 <= ctrla[2]; led2 <= ctrlb[2]; led3 <= ctrlc[2]; end3 : begin led1 <= ctrla[3]; led2 <= ctrlb[3]; led3 <= ctrlc[3]; end4 : begin led1 <= ctrla[4]; led2 <= ctrlb[4]; led3 <= ctrlc[4]; end5 : begin led1 <= ctrla[5]; led2 <= ctrlb[5]; led3 <= ctrlc[5]; end6 : begin led1 <= ctrla[6]; led2 <= ctrlb[6]; led3 <= ctrlc[6]; end7 : begin led1 <= ctrla[7]; led2 <= ctrlb[7]; led3 <= ctrlc[7]; enddefault : begin led1 <= led1; led2 <= led2; led3 <= led3; endendcaseendmodule
07. B.受控线性序列机课题的实现
6.每隔10ms,让LED灯的一个8状态循环执行一次(每个状态的变化时间值小一点,方便测试,比如设置为10us)
原理图:
总结:通过控制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;elsecounter0 <= 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) beginif(counter1 == times - 1'd1) counter1 <= 0;elsecounter1 <= counter1 + 1'd1;endelse counter1 <= 0;reg [2:0]counter2;always@(posedge clk or negedge rstn)if(!rstn)counter2 <= 0;else if(EN == 1)beginif(counter1 == times - 1'd1)counter2 <= counter2 + 1'd1;endelsecounter2 <= 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;endcaseendmodule
仿真代码
`timescale 1ns / 1nsmodule 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 beginrstn = 0;#201;rstn = 1;#2000;times = 32'd500;ctrl = 8'b10000110;#100000000;ctrl = 8'b10100110;#200000000;$stop;endendmodule
仿真波形
6.1 代码调试(添加设计信号到波形中)