赞
踩
源文件
module counter_led_0( input clk, input reset, output reg led ); reg [25:0] cnt; parameter MCNT=50000000; always@(posedge clk or negedge reset)begin if(!reset) cnt<=0; else if(cnt==MCNT-1) cnt<=0; else cnt<=cnt+1'b1; end always@(posedge clk or negedge reset)begin if(!reset) led<=0; else if(cnt==(MCNT/4+MCNT/2)-1) led<=1; else if(cnt==MCNT-1) led<=0; else led<=led; end endmodule
测试文件
`timescale 1ns / 1ns module counter_led_0_tb(); reg clk; reg reset_n; wire led; counter_led_0 counter_led_0( .clk(clk), .reset(reset_n), .led(led) ); defparam counter_led_0.MCNT=26'd25000; initial begin clk=0; end always#10 clk=!clk; initial begin reset_n=0; #201; reset_n=1; #40000000; $stop; end endmodule
仿真截图
收获:
1:用parameter定义变量的时候,对变量除以2还是很容易实现的,因为其对应的是一个常量的值,但是若是一个变量在过程中会实时变化的话直接/2是会有一些问题的~
2:需要这道题需要注意亮0.25s不代表是要在0的基础上计数到0.25s在变为1,而是在1的基础上保留的时间是0.25s,这里也是需要转过弯儿的地方~
源代码
module counter_led_1( input clk, input reset, output reg led ); reg [26:0] cnt; parameter MCNT=125000000; always@(posedge clk or negedge reset)begin if(!reset) cnt<=0; else if(cnt==MCNT-1) cnt<=0; else cnt<=cnt+1'b1; end always@(posedge clk or negedge reset)begin if(!reset) led<=1; else if(cnt==MCNT/10-1) led<=0; else if(cnt==MCNT/10+MCNT/5-1) led<=1; else if(cnt==(MCNT/10+MCNT/5)*2-1) led<=0; else if(cnt==MCNT-1) led<=1; else led<=led; end endmodule
仿真截图
收获
1:这里为了使亮灭计数好想,设置了复位状态时led灯为灭~
源代码
//该模块的功能是让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随机指定。以0.25s为一个变化周期,8个变化状态为一个循环 module counter_led_2( input clk, input reset, input [7:0]ctrl, output reg led ); reg [26:0] cnt; parameter MCNT=100000000; always@(posedge clk or negedge reset)begin if(!reset) cnt<=0; else if(cnt==MCNT-1) cnt<=0; else cnt<=cnt+1'b1; end always@(posedge clk or negedge reset)begin if(!reset) led<=0; else if(cnt==MCNT/8-1) led<=ctrl[0]; else if(cnt==MCNT*2/8-1) led<=ctrl[1]; else if(cnt==MCNT*3/8-1) led<=ctrl[2]; else if(cnt==MCNT*4/8-1) led<=ctrl[3]; else if(cnt==MCNT*5/8-1) led<=ctrl[4]; else if(cnt==MCNT*6/8-1) led<=ctrl[5]; else if(cnt==MCNT*7/8-1) led<=ctrl[6]; else if(cnt==MCNT*8/8-1) led<=ctrl[7]; else led<=led; end endmodule
测试文件
`timescale 1ns / 1ns module counter_led_2_tb(); reg clk; reg reset_n; reg [7:0]ctrl; wire led; counter_led_2 counter_led_2( .clk(clk), .reset(reset_n), .ctrl(ctrl), .led(led) ); defparam counter_led_2.MCNT=100000; initial begin clk=0; end always#10 clk=!clk; initial begin reset_n=0; ctrl=0; #201; reset_n=1; #200; ctrl=8'b1001_0001; #40000000; $stop; end endmodule
仿真图
思路:在原有的基础上因为时间是用户自己设定的,所以设置times变量作为输入,因为MCNT变量以往都是固定值,但是times会随时变化,所以这里就又定义了一个cnt2记到1——8,每到一个值灯就会反应出对应的亮度
源代码
//该模块的功能是让LED灯按照指定的亮灭模式亮灭,亮灭模式未知,由用户随机指定。8个变化状态为一个循环,每个变化状态的时间值可以根据不同的应用场景选择 module counter_led_3( input clk, input reset, input [31:0]times, input [7:0]ctrl, output reg led ); reg [31:0] cnt; always@(posedge clk or negedge reset)begin if(!reset) cnt<=0; else if(cnt==times-1) cnt<=0; else cnt<=cnt+1'b1; end reg [2:0]cnt2; always@(posedge clk or negedge reset)begin if(!reset) cnt2<=3'b0; else if(cnt==times-1) cnt2<=cnt2+1; end always@(posedge clk or negedge reset)begin if(!reset) led<=0; else begin case(cnt2) 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 end end endmodule
测试文件
`timescale 1ns / 1ns module counter_led_3_tb(); reg clk; reg reset_n; reg [7:0]ctrl; reg [31:0]times; wire led; counter_led_3 counter_led_3( .clk(clk), .reset(reset_n), .ctrl(ctrl), .times(times), .led(led) ); initial begin clk=0; end always#10 clk=!clk; initial begin reset_n=0; ctrl=0; times=0; #201; reset_n=1; #200; ctrl=8'b1001_0001; #201; times=2500; #2000001; times=25000; #400000000; $stop; end endmodule
仿真截图
答:在四的基础上增加led的位宽,以及设置多个控制信号进行赋值
module counter_led_5( Clk, Reset_n, CtrlA, CtrlB, Time, Led ); input Clk; input Reset_n; input [7:0]CtrlA; input [7:0]CtrlB; input [31:0]Time; output reg [1:0]Led; reg [31:0]counter; always@(posedge Clk or negedge Reset_n) if(!Reset_n) counter <= 0; else if(counter == Time - 1) counter <= 0; else counter <= counter + 1'b1; reg [2:0]counter2; always@(posedge Clk or negedge Reset_n) if(!Reset_n) counter2 <= 0; else if(counter == Time - 1) counter2 <= counter2 + 1'b1; always@(posedge Clk or negedge Reset_n) if(!Reset_n) Led <= 2'd0; else case(counter2) 0:begin Led[0] <= CtrlA[0]; Led[1] <= CtrlB[0]; end 1:begin Led[0] <= CtrlA[1]; Led[1] <= CtrlB[1]; end 2:begin Led[0] <= CtrlA[2]; Led[1] <= CtrlB[2]; end 3:begin Led[0] <= CtrlA[3]; Led[1] <= CtrlB[3]; end 4:begin Led[0] <= CtrlA[4]; Led[1] <= CtrlB[4]; end 5:begin Led[0] <= CtrlA[5]; Led[1] <= CtrlB[5]; end 6:begin Led[0] <= CtrlA[6]; Led[1] <= CtrlB[6]; end 7:begin Led[0] <= CtrlA[7]; Led[1] <= CtrlB[7]; end default:begin Led[0] <= Led; Led[1] <= Led[1]; end endcase endmodule
测试文件
`timescale 1ns/1ns module counter_led_5_tb; reg Clk; reg Reset_n; reg [7:0]CtrlA,CtrlB; reg [31:0]Time; wire [1:0]Led; counter_led_5 counter_led_5( .Clk(Clk), .Reset_n(Reset_n), .CtrlA(CtrlA), .CtrlB(CtrlB), .Time(Time), .Led(Led) ); initial Clk = 1; always #10 Clk = !Clk; initial begin Reset_n = 0; CtrlA = 0; CtrlB = 0; Time = 0; #201; Reset_n = 1; #2000; Time = 2500; CtrlA = 8'b1000_0110; CtrlB = 8'b1101_0010; #20000000; Time = 25000; CtrlA = 8'b1010_0110; CtrlB = 8'b1100_1010; #20000000; $stop; end endmodule
最开始自己的理解是在8个循环之后间隔10ms,所以才有了以下代码的理解,但是后来才懂原来周期是10msemmm有些许思想出路
注:以下代码的逻辑思想正确,即在原有计数的基础上又加了一个整体的计数周期=8*times+10ms,但是这里的8需要对输入变量做乘法,在运算时很有可能一个周期运算不出来,就会出现一些错误,所以这里还是要谨慎的使用;(小梅哥采用的是设置en进行控制,自己没有写出来,这里看完他的代码后自行默写了一下~)
//该模块的功能是每隔10ms,让LED灯的一个8状态循环执行一次(每个状态的变化时间值小一点,方便测试,比如设置为10us) module counter_led_4( input clk, input reset, input [31:0]times, input [7:0]ctrl, output reg led ); reg [31:0] cnt; reg en;//设置使能,只有在en为1的时候 parameter count=5000; always@(posedge clk or negedge reset)begin if(!reset) cnt<=0; else if(cnt==times-1) cnt<=0; else cnt<=cnt+1'b1; end reg [2:0]cnt2; always@(posedge clk or negedge reset)begin if(!reset) cnt2<=3'b0; else if(cnt==times-1) cnt2<=cnt2+1; end reg [35:0] cnt3; always@(posedge clk or negedge reset)begin if(!reset) cnt3<=0; else if(cnt3==times*8-1+count) cnt3<=0; else cnt3<=cnt3+1'b1; end always@(posedge clk or negedge reset)begin if(!reset) led<=0; else if(cnt3<=8*times-1) begin case(cnt2) 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 end else if(cnt3<=8*times-1+count) begin led<=0; end end endmodule
`timescale 1ns / 1ns module counter_led_4_tb(); reg clk; reg reset_n; reg [7:0]ctrl; reg [31:0]times; wire led; counter_led_4 counter_led_4( .clk(clk), .reset(reset_n), .ctrl(ctrl), .times(times), .led(led) ); initial begin clk=0; end always#10 clk=!clk; initial begin reset_n=0; ctrl=0; times=0; #201; reset_n=1; #200; ctrl=8'b1001_0001; #201; times=2500; #2000001; times=25000; #40000000; $stop; end endmodule
小梅哥的官方源码
module counter_led_4( Clk, Reset_n, Ctrl, Time, Led ); input Clk; input Reset_n; input [7:0]Ctrl; input [31:0]Time; output reg Led; reg [31:0]counter; reg EN; reg [18:0]counter0; //10ms���ڶ�ʱ�� always@(posedge Clk or negedge Reset_n) if(!Reset_n) counter0 <= 0; else if(counter0 == 500000 - 1) counter0 <= 0; else counter0 <= counter0 + 1'b1; always@(posedge Clk or negedge Reset_n) if(!Reset_n) EN <= 0; else if(counter0 == 0) EN <= 1; else if((counter2 == 7) && (counter == Time - 1)) EN <= 0; always@(posedge Clk or negedge Reset_n) if(!Reset_n) counter <= 0; else if(EN)begin if(counter == Time - 1) counter <= 0; else counter <= counter + 1'b1; end else counter <= 0; reg [3:0]counter2; always@(posedge Clk or negedge Reset_n) if(!Reset_n) counter2 <= 0; else if(EN)begin if(counter == Time - 1) counter2 <= counter2 + 1'b1; end else counter2 <= 4'd8; always@(posedge Clk or negedge Reset_n) if(!Reset_n) 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]; 8:Led <= 0; default:Led <= Led; endcase endmodule
测试文件
`timescale 1ns / 1ns module counter_led_4_tb(); reg clk; reg reset_n; reg [7:0]ctrl; reg [31:0]times; wire led; counter_led_4 counter_led_4( .Clk(clk), .Reset_n(reset_n), .Ctrl(ctrl), .Time(times), .Led(led) ); initial begin clk=0; end always#10 clk=!clk; initial begin reset_n=0; ctrl=0; times=0; #201; reset_n=1; #2000; ctrl=8'b1000_0111; times=2500; #20000001; times=25000; ctrl=8'b1010_0110; #20000000; $stop; end endmodule
仿真截图
收获:
1:锻炼了自己分析波形的能力,自己调试,最初小梅哥的代码在间隔10ms的时间里会一直保持ctrl[0]的状态,让波形看的很乱,找不到是什么时候开始算起的,于是我对counter2进行计数更改,当当前处于不计数的状态时,不为0.因为为0 的话需要在后面case循环中进行判断等于ctrl[0],于是我把不计数的状态设为不在判断范围内的8,使其为0,这样使得波形比较规律易懂
2:学会了添加模块中其他参数的方法,好开心~,这样查错就更容易了
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。