定时/计数器的verilog代码

定时/计数器

功能:
具有计数和定时两个功能。
1)计数方式下可以对输入的外部脉冲进行计数,当计数到初值寄存器的值的时候,设置状态寄存器的相应位。
2)定时方式下,在时钟作用下计时器做减1,到1的时候设置状态寄存器的相应位,并在相应的COUT脚输出一个时钟的低电平(平时COUT是高电平)。
3)状态寄存器在被读取后被清零。

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2016/12/01 15:05:19
// Design Name: 
// Module Name: CNT0
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//




module CNT0(
rdata,wdata,CS,CLK,Reset,pulse0,address,IOW,IOR,COUT0,timing,counting,COUT2
    );
input[31:0] wdata;//cpu写数据
input[31:0] address;//端口地址
input CS,CLK,Reset,pulse0,IOW,IOR,timing,counting;//片选端,时钟端,复位信号,外部脉冲信号,写信号,读信号,计时控制信号,计数控制信号
output [31:0] rdata;//cpu读数据
output COUT0;//定时/计数器输出
output [31:0] COUT2;//计数测试


reg[31:0] ms;//方式/状态寄存器
reg[31:0] ini;//初值寄存器
reg[31:0] rda;//rdata的驱动寄存器
reg COU;//COUT0的驱动寄存器
reg[31:0] COU2;//COUT2的驱动寄存器
integer count0;//计数值
integer count1;//计时器初值
integer count2;//用来测试计数是否正常工作,最后删除掉
assign rdata=rda;//驱动
assign COUT0=COU;
assign COUT2=COU2;


initial
    begin
    count0=0;//用于计数
    end


always @(posedge CLK)
begin
if(CS)
begin
    if(Reset)
        begin
        ms[31:0]=0;
        ini[31:0]=0;
        count0=0;
        count1=0;
        count2=0;
        end


    


if(IOW)//CPU写数据
begin
    if(address[7:0]==8'b0010_0000) ms=wdata;//CPU写方式寄存器,CNT1此处应该是22
    else if(address[7:0]==8'b0010_0100) 
        begin
        ini=wdata;//CPU写初值寄存器,CNT1此处应该是26
        count1=ini;//count1用来备份初值寄存器的值
        end
end
    


if(IOR)//CPU读数据
begin
    if(address[7:0]==8'b0010_0000)
        begin
        rda=ms;//CPU读状态寄存器,CNT1此处应该是22
        ms[3:2]=2'b00;//状态寄存器读取后清零
        ms[15]=0;
        COU2=count2;
        end
    else if(address[7:0]==8'b0010_0100) rda=ini;//CPU读初值寄存器,CNT1此处应该是26
end
    




if(timing)//计时
begin
    if({ms[1],ms[0]}==2'b00)//读方式寄存器,非循环定时
        begin
        ms[15]=1;//写状态寄存器,定时开始
        if(ini==1)//初值寄存器减到1,定时结束
            begin
            ms[15]=0;//定时结束
            ms[3:2]=2'b01;//定时到
            COU=0;//定时到输出一个低电平
            end
        else if(ini>1)//尚未定时到
            begin
            ini=ini-1;//初值减1
            COU=1;//平时输出高电平
            end
        else COU=1;
        end    
    else if({ms[1],ms[0]==2'b10})//循环定时
        begin
        ms[15]=1;//写状态寄存器,定时开始
        if(ini==1)//初值寄存器减到1,定时到
            begin
            ms[3:2]=2'b01;
            ini=count1;//count1保存的初值再赋值给ini寄存器
            COU=0;//定时到输出一个低电平
            end
        else if(ini==count1-1)
            begin
            ms[3:2]=2'b00;//清除定时到
            ini=ini-1;
            COU=1'b1;
            end
        else
            begin
            ini=ini-1;
            COU=1;//平时输出高电平
            end
        end
end
else begin 
     COU=1;
     ms[15]=0;//没有处在计时的状态
     end




if(counting && pulse0)//计数
begin
    if({ms[1],ms[0]}==2'b01)
        begin
        ms[15]=1;//计数开始
            begin
            if(count0==ini)//计数值等于初值
                begin
                ms[15]=0;//计数结束
                ms[3:2]=2'b10;//设置状态寄存器,计数到
                end
            else begin
                 count0=count0+1;//计数
                 count2=count2+1;//测试
                 end
            end
        end 
    else if({ms[1],ms[0]}==2'b11)//循环计数
        begin
        ms[15]=1;//计数开始
        if(count0==ini)//计数值等于初值
            begin
            ms[3:2]=2'b10;//设置状态寄存器,计数到
            count0=1;//循环,重置计数值寄存器
            count2=count2+1;//测试
            end
        else if(count0==0)
            begin 
            ms[3:2]=2'b00;//清除状态寄存器
            count0=count0+1;
            count2=count2+1;//测试
            end
        else begin 
             count0=count0+1;//计数
             count2=count2+1;//测试
             end
        end
end else ms[15]=0;//没有处在计数的状态ms[15]为0,COUNTING 
end//CS 
end//always
endmodule


顶层文件

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2016/12/03 17:03:20
// Design Name: 
// Module Name: timepiece
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module timepiece(
rdata,wdata,CS,CLK,Reset,pulse0,address,IOW,IOR,COUT0,timing,counting,COUT2
    );
input[31:0] wdata;//cpu写数据
input[31:0] address;//端口地址
input CS,CLK,Reset,pulse0,IOW,IOR,timing,counting;//片选端,时钟端,复位信号,外部脉冲信号,写信号,读信号
output[31:0] rdata;//cpu读数据
output COUT0;//定时/计数器输出
output[31:0] COUT2;//计数测试

CNT0 U0(
    .rdata(rdata),
    .wdata(wdata),
    .CS(CS),
    .CLK(CLK),
    .Reset(Reset),
    .pulse0(pulse0),
    .address(address),
    .IOW(IOW),
    .IOR(IOR),
    .COUT0(COUT0),
    .timing(timing),
    .counting(counting),
    .COUT2(COUT2)
);
endmodule

仿真文件

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2016/12/03 17:13:25
// Design Name: 
// Module Name: timepiece_sim
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module timepiece_sim();
//input wdata,CS,CLK,Reset,pulse0,address,IOW,IOR
reg CLK=1;
reg [31:0] wdata=0;
reg CS=0;
reg Reset=0;
reg pulse0=1;
reg [31:0] address=0;
reg IOW=0;
reg IOR=0;
reg timing=0;
reg counting=0;

//output rdata,COUT0
wire [31:0] rdata;
wire COUT0;
wire [31:0] COUT2;

timepiece uut(
//input wdata,CS,CLK,Reset,pulse0,address,IOW,IOR
//output rdata,COUT0
    .CLK(CLK),
    .CS(CS),
    .wdata(wdata),
    .Reset(Reset),
    .pulse0(pulse0),
    .address(address),
    .IOW(IOW),
    .IOR(IOR),
    .rdata(rdata),
    .COUT0(COUT0),
    .timing(timing),
    .counting(counting),
    .COUT2(COUT2)
);

initial
    begin
    #100 CS=1;
    //非循环定时,2个clock输出一个时钟低电平
    #10 address[31:0]=8'hFFFF_FC24;//写初值寄存器
    #10 wdata[31:0]=8'h0000_0003;
    #10 IOW=1;
    #10 IOW=0;
    #10 address=8'hFFFF_FC20;//写方式寄存器
    #10 wdata=8'h0000_0000;
    #10 IOW=1;
    #10 IOW=0;
    #10 timing=1;
    //循环定时,2个clock输出一个时钟低电平,输出5个
    #30 timing=0; 
    #10 address=8'hFFFF_FC24;//写初值寄存器
    #10 wdata=8'h0000_0003;
    #10 IOW=1;
    #10 IOW=0;
    #10 address=8'hFFFF_FC20;//写方式寄存器
    #10 wdata=8'h0000_0003;
    #10 IOW=1;
    #10 IOW=0;
    #10 timing=1;
    //非循环计数,5个pulse0
    #150 timing=0;
    #10 address=8'hFFFF_FC24;//写初值寄存器
    #10 wdata=8'h0000_0005;
    #10 IOW=1;
    #10 IOW=0;
    #10 address=8'hFFFF_FC20;//写方式寄存器
    #10 wdata=8'h0000_0001;
    #10 IOW=1;
    #10 IOW=0;
    #10 counting=1;
    #10 address=8'hFFFF_FC20;//读状态寄存器
    #100 counting=0;
    #10 IOR=1;
    #10 IOR=0;
    //循环计数,每次2个pulse0,跑5次
    #10 Reset=1;//Reset
    #10 Reset=0;
    #10 address=8'hFFFF_FC24;//写初值寄存器
    #10 wdata=8'h0000_0002;
    #10 IOW=1;
    #10 IOW=0;
    #10 address=8'hFFFF_FC20;//写方式寄存器
    #10 wdata=8'h0000_0003;
    #10 IOW=1;
    #10 IOW=0;
    #10 counting=1;
    #10 address=8'hFFFF_FC20;//读状态寄存器
    #190 counting=0;
    #10 IOR=1;
    #10 IOR=0;
    end

always #5 CLK = ~CLK;

always #10 pulse0=~pulse0;
    

endmodule

状态/方式寄存器

15

3

2

1

0

定时/计数(状态)

计数到(状态)

定时到(状态)

循环/非循环(方式)

定时/计数(方式)



注意事项:

1)不同的register不能在不同的always语句块中重复赋值。

2)always以及initial语句块不能嵌套。

3)仿真文件中的延时是相邻两句之间的延时。







你可能感兴趣的:(综合系统设计,计数器,定时器,verilog)