【精品博文】学习FPGA第一天
用case语句实现一个计数器
module ex_case(
input wire rst_n,
input wire sclk,
output reg o_dv, //标志数据有效
output reg [7:0] o_data, //用于数据输入
input wire [9:0] i_data,
input wire [7:0] i_addr
);
reg [2:0] cnt_7;
//不同功能的寄存器分开always块来写,这样代码的可维护性和可读性强.
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
cnt_7 <= 3'd0;
else
cnt_7 <= cnt_7 + 1'b1; //溢出,低三位重新为0
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)begin
o_data<=8'd0;
o_dv<=1'b0; //如果不赋初值,复位会接在o_dv使能端。
end
else begin
case(cnt_7)
3'd0:begin
o_data<=3'd7; //当cnt_7等于3'd0时,执行此条语句。如果:后多条语句,加beginend
o_dv<=1'b1;
end
3'd1:begin
o_data<=3'd0; //case endcase 比if else 快.相当于译码器
o_dv<=1'b0;
end
3'd2:begin
o_data<=3'd5;
o_dv<=1'b1;
end
default:begin
o_data<=3'd0;
o_dv<=1'b0;
end //case语句一定要有default
endcase //case语句只能在always块里,也是并行语句,满足case条件执行
end
endmodule
//在消除锁存器,锁存器在FPGA里不能用,延时无法时序分析,而且FPGA每一次综合布线是不固定的。 只有在电平触发时,case没有写全才会有锁存器出现。
//1、敏感列表写全,case条件,在赋值语句右边的变量也要加入敏感列表里.
//2、所有条件分支写全
//always @(cnt_7)
// case(cnt_7)
// 3'd0:begin
// o_data<=3d'7;
// o_dv<=1'b1;
// end
// 3'd1:begin
// o_data<=3d'0;
// o_dv<=1'b0;
// end
// 3'd2:begin
// o_data<=3d'5;
// o_dv<=1'b1;
// end
// default:begin
// o_data<=3d'0;
// o_dv<=1'b0;
// end
// endcase
testbench:
`timescale 1ns/1ns
module tb_ex_case;
reg sclk,rst_n;
wire [7:0] data;
wire dv;
reg [7:0] i_addr;
reg [9:0] i_data;
initial begin
sclk =0;
rst_n =0;
#200
rst_n =1;//不用设置位宽,tb因为不可综合
end
initial begin
#500
send(255);
end
always #10 sclk <= ~sclk;
ex_case ex_case_inst(
.rst_n (rst_n),
.sclk (sclk),
.o_dv (dv),
.o_data (data),
.i_data (i_data),
.i_addr (i_addr)
);
task send_data(len); //任务的声明,过程描述
integer len,i;
//变量声明区,在可综合模块不用integer 它指32位整型
begin
for(i=0;i<len;i=i+1)begin //循环语句
@(posedge sclk);
i_addr<=i[7:0];
i_data<=i[7:0];
end
i_addr<=0;
i_data<=0;
end
endtask
endmodule
sclk和rst_n信号线都为金线,延时很短,而其它端口多为铜线,一般不用posedge、negedge来写。
在modelsim仿真时提示“len”信号already declared in this scope ,
task send_data(len); //任务的声明,过程描述
integer len,i;
于是交换顺序无报错:integer len,i;
task send_data(len);
可能是modelsim有要求,在块里边出现之前,必须先做声明。(已经弄明白了task声明的要求)
测试后发现写的程序有问题,i_data和i_addr的波形图有问题:
将len加入波形,发现它一直是1,考虑到时位宽问题没有处理好,task send_data(len) len默认为1bit,代码改为:
task后变量的声明有顺序要求,任务使能语句中参数列表顺序应与之一直。新的波形图: