先说自己搞明白了一点点小问题:就是仿真文件中定义clk是和D触发器的工作原理对应的(上升沿触发)。
1~3题其实没什么难度,题目的意义在于,一段时间能等分成几个单位时间,并能对这些单位时间进行控制。除了5题都是一个led(1bit)。
4题
定义模块代码
module led4 (
reset_n,
ttime,
ctrl,
clk,
led
);
input reset_n;
input [31:0] ttime;
input [7:0] ctrl;
input clk;
output reg led;
reg [31:0] counter1;
reg [2:0] counter2; //3位二进制能表示8段。
/*****counter1计数*****/
always @ (negedge reset_n or posedge clk) begin
if (reset_n==0) counter1<=0; //always块中有复位信号,先复位清零。
else if (counter1==(ttime-1)) counter1<=0;
else counter1<=counter1+1'b1;
end
/*****counter2计数*****/
always @ (negedge reset_n or posedge clk) begin
if (reset_n==0) counter2<=0; //always块中有复位信号,先复位清零。
else if (counter1==(ttime-1)) counter2<=counter2+1'b1;
end
/*****crtl端口控制单位时间的高低电平*****/
always @ (negedge reset_n or posedge clk) begin
if (reset_n==0) led<=0; //always块中有复位信号,先复位清零。
else case (counter2)
3'd0:led<=ctrl[0];
3'd1:led<=ctrl[1];
3'd2:led<=ctrl[2];
3'd3:led<=ctrl[3];
3'd4:led<=ctrl[4];
3'd5:led<=ctrl[5];
3'd6:led<=ctrl[6];
3'd7:led<=ctrl[7];
default led<=led;
endcase
end
endmodule
6题
定义模块代码
module led6 (
reset_n,
ttime,
ctrl,
clk,
led
);
input reset_n;
input [31:0] ttime;
input [7:0] ctrl;
input clk;
output reg led;
reg [31:0] counter1;
reg [2:0] counter2;
reg [18:0] counter3; //10ms
reg EN;
/*****counter1计数*****/
always @ (negedge reset_n or posedge clk) begin
if (reset_n==0) counter1<=0; //always块中有复位信号,先复位清零。
else if (EN) begin
if(counter1==(ttime-1)) counter1<=0;
else counter1<=counter1+1'b1;
end
else counter1=0;
end
/*****counter2计数*****/
always @ (negedge reset_n or posedge clk) begin
if (reset_n==0) counter2<=0; //always块中有复位信号,先复位清零。
else if(counter1==(ttime-1))counter2<=counter2+1'b1;
end
/*****counter3计数*****/
always @ (negedge reset_n or posedge clk) begin
if (reset_n==0) counter3<=0; //always块中有复位信号,先复位清零。
else if (counter3==(500000-1)) counter3<=0;
else counter3<=counter3+1'b1;
end
/*****EN控制信号*****/
always @ (negedge reset_n or posedge clk) begin
if (reset_n==0) EN<=0; //always块中有复位信号,先复位清零。
else if (counter3==0)EN<=1;
else if ((counter2==7)&&(counter1==(ttime-1))) EN<=0; //计数i次<=>counter2=i。
end
/*****crtl端口控制单位时间的高低电平*****/
always @ (negedge reset_n or posedge clk) begin
if (reset_n==0) led<=0; //always块中有复位信号,先复位清零。
else case (counter2)
3'd0:led<=ctrl[0];
3'd1:led<=ctrl[1];
3'd2:led<=ctrl[2];
3'd3:led<=ctrl[3];
3'd4:led<=ctrl[4];
3'd5:led<=ctrl[5];
3'd6:led<=ctrl[6];
3'd7:led<=ctrl[7];
default led<=led;
endcase
end
endmodule
测试代码
`timescale 1ns/1ns
module led6_tb;
reg clk;
reg [31:0]ttime;
reg resetn;
reg [7:0]ctrl;
wire led;
led6 led6tb(
.clk(clk),
.ttime(ttime),
.reset_n(resetn),
.led(led),
.ctrl(ctrl)
);
initial clk=1;//和posedge clk是对应的。
always # 10 clk=!clk;
initial begin
resetn = 0;
ctrl = 0;
ttime = 0;//端口清零
#201;
resetn = 1;
ctrl=8'b1000_0110;
ttime=2500;//试验一个值
# 200000000;
$stop;
end
endmodule
语法
- 复位端口清零。清零后,后面的代码不考虑清零状态,因为清零状态是初始值。
定义模块:
always @ (negedge reset_n or posedge clk) begin
if (reset_n==0) counter <=0;
end
always @ (negedge reset_n or posedge clk) begin
if (reset_n==0) led <=0;
end
仿真模块:
initial begin
reset_n=0; //复位。
ttime=0; //输入端口清零。
ctrl=0;
#201; //复位清零设置一小段时间。
end
- 用case语法的时候,必须考虑case()括号里面的值穷举完了吗?没有穷举完用default补充。
default: led<=led;
- 当有多个仿真文件时,选择目的仿真文件为头文件。
设置为头文件之后会变成黑色加粗字体。
- 调试技巧
将定义模块中的端口添加到波形图中。