APB接口的24小时钟表计数器

APB接口的24小时计数器

//2022-3-19 soc设计
//APB接口的钟表计数器模块
//题目1:APB接口的模6计数器/模10计数器模块
// 设计内容:
//APB2.0 接口
//支持异步复位(低电平有效)
//支持软件同步复位(高电平有效)
//支持计数暂停(高电平有效)
//钟表计数器的显示按照每秒更新
//钟表计数器按照24小时循环计数
// 实验内容:
//完成RTL设计
//完成TESTBENCH设计
//完成FPGA演示

1.hour24_counter.v是带有 APB 接口24小时计数器,作为APB_slave
2.Timer24是计数信号,组成:{8’d0,hour_h[4:0],hour_l[4:0],minute_h[4:0],minute_h[4:0],second_h[4:0],second_l[4:0]} 即8个0,和后面的24位时分秒钟
3.hour24_counter_tb 是hour24_counter的testbench
4.APB_Bridge.v是hour24_counter的master
5.seg_dec.v是七段数码管module

功能1:24小时计数,仿真结果如下
在这里插入图片描述

功能2:同步复位(高电平有效)res
异步复位(低电平有效)preset
在这里插入图片描述
在这里插入图片描述

功能3:计数暂停(高电平有效)
暂停的计数秒,比正常时间计数1秒时间长
在这里插入图片描述

功能4:写信号,写好地址,选择、使能、读写信号都为1 时,将数据写入timer24
在这里插入图片描述

功能5:读信号,写好地址,选择、使能信号都为1 ,读写信号为0时,将数据从timer24读出

在这里插入图片描述

在这里插入代码片
// 2022-3-21 verilog学习
// 24小时计数器 秒:0-59循环,分:0-59 循环,时:0-24循环,当23:59:59时,重新初始化
//2022-3-19 soc设计
//APB接口的钟表计数器模块
//题目1:APB接口的模6计数器/模10计数器模块 

 // 设计内容: 
 //APB2.0 接口 
 //支持异步复位(低电平有效) 
 //支持软件同步复位(高电平有效) 
 //支持计数暂停(高电平有效) 
 //钟表计数器的显示按照每秒更新 
 //钟表计数器按照24小时循环计数 
 // 实验内容: 
 //完成RTL设计 
 //完成TESTBENCH设计 
 //完成FPGA演示
`timescale 1ns/1ps

module hour24_counter(
								pclk,
								preset,
								
								
								s_reset,//同步复位,高电平有效
								pause,//计数暂停
								

								paddr,//地址总线,
								psel,//从译码器来的片选信号
								penable,//使能信号
								pwrite,//高电平:写   低电平:读
								pwdata,//32位宽写 
								prdata,//32位宽读
								
								
								timer24
								);

input					pclk;
input					preset;


input					s_reset;
input					pause;

input[31:0]				paddr;//地址总线,
input						psel;//从译码器来的片选信号
input						penable;//使能信号
input						pwrite;//高电平:写   低电平:读
input[31:0]				pwdata;//32位宽写 
output[31:0]			prdata;//32位宽读

output[31:0]		timer24;

parameter			frequency_pclk = 100;  // 24MHz

reg[8:0]				con_t;   // 秒脉冲分频计数器  24M, 十进制24000000转换为2进制是25位
reg					s_pulse; // 秒脉冲尖  pulse脉冲
reg[31:0]			timer24; // always中赋值需要reg型

wire[31:0]				paddr;//地址线,再在此设为学号:216189
reg[31:0]				prdata;//32位宽读
wire wr;//写
wire rd;//读
reg[31:0] REG_A;//模拟寄存器
reg[31:0] REG_B;//模拟寄存器

//------------ 读写功能 ---------------------
assign wr = psel & pwrite & penable;
assign rd = psel & (~pwrite) & penable;

always@(posedge pclk or negedge preset or posedge rd) begin // 敏感变量
	if(rd==1)begin
		case(paddr)
			32'h216189    : prdata<=timer24;
			//REG_A_ID    : prdatanxt = REG_A;
			//REG_B_ID    : prdatanxt = REG_B;
			//……寄存器的地址
		endcase
	end
end

// or posedge pause
always@(posedge pclk or negedge preset) begin // 敏感变量
	if(!preset) begin
		con_t <= 0;   // 复位下降沿,时钟计数清零
		s_pulse <= 0;  // 秒脉冲清零
		timer24<=0;
	end
	
	else if(s_reset==1'b1) begin
		con_t <= 0;   // 复位下降沿,时钟计数清零
		s_pulse <= 0;  // 秒脉冲清零
		timer24 <= 0;
	end
	

	

	else if(wr)begin//写数据有效
		case(paddr)
			32'h216189    : timer24<=pwdata;
			//REG_A_ID    : prdatanxt = REG_A;
			//REG_B_ID    : prdatanxt = REG_B;
			//……寄存器的地址
			default       : timer24 <= timer24;
		endcase
	end

	else if(pause==1)begin
		timer24<=timer24;
	end

	else begin
		//'''''秒脉冲分频计数器''''' 板子时钟频率24M,即1s中24M个脉冲
		if(con_t == frequency_pclk-1) begin  // 时钟计数周期为24M, 0-23999999,到周期清零
			con_t <= 0;
		end
		else begin
			con_t <= con_t+9'd1;
		end
	
		//'''''秒脉冲尖'''''
		if(con_t == 0)begin     // 1s中24M个脉冲,到第0个脉冲,秒脉冲 = 1
			s_pulse <= 1;
		end
		else begin
			s_pulse <= 0;
		end
	
		
		//'''''秒计数'''''
		if(s_pulse==1) begin
				//'''''秒计数di'''''
				if(timer24[3:0] == 9) begin  // 0-59循环秒计数
					timer24[3:0] <= 0;	
					timer24[7:4] <= timer24[7:4] + 4'd1;
				end
				else begin 
					timer24[3:0] <= timer24[3:0] +4'd1;//秒计数
				end
				
				//'''''秒计数gao''''
				if((timer24[7:4]>=5)&(timer24[3:0] == 9))begin
					timer24[7:4] <= 0;	timer24[3:0] <= 0;
					timer24[11:8] <= timer24[11:8] + 4'd1;
				end
				
				//'''''分计数di'''''
				if((timer24[11:8]==9)&(timer24[7:4]>=5)&(timer24[3:0] == 9))begin
					timer24[7:4] <= 0;	timer24[3:0] <= 0;
					timer24[11:8] <= 0;	timer24[15:12] <= timer24[15:12] + 4'd1;
				end
				
				//'''''分计数gao'''''
				if((timer24[15:12]>=5)&(timer24[11:8]==9)&(timer24[7:4]>=5)&(timer24[3:0] == 9))begin
					timer24[7:4] <= 0;	timer24[3:0] <= 0;
					timer24[11:8] <= 0;	timer24[15:12] <= 0;
					timer24[19:16] <= timer24[19:16] + 4'd1;
				end
				
				//'''''时计数di'''''
				if((timer24[19:16]==9)&(timer24[15:12]>=5)&(timer24[11:8]==9)&(timer24[7:4]>=5)&(timer24[3:0] == 9))begin
					timer24[7:4] <= 0;	timer24[3:0] <= 0;
					timer24[11:8] <= 0;	timer24[15:12] <= 0;
					timer24[19:16] <= 0;	timer24[23:20] <= timer24[23:20] + 4'd1;
				end
				
				//'''''时计数gao'''''
				if((timer24[23:20]==2)&(timer24[19:16]==3)&(timer24[15:12]>=5)&(timer24[11:8]==9)&(timer24[7:4]>=5)&(timer24[3:0] == 9))begin
					timer24[7:4] <= 0;	timer24[3:0] <= 0;
					timer24[11:8] <= 0;	timer24[15:12] <= 0;
					timer24[19:16] <= 0;	timer24[23:20] <= 0;
				end

		end
	
	end
end
endmodule





//  testbench 测试台
module hour24_counter_tb;

reg					pclk,preset,pause,s_reset;

reg[31:0]				paddr;//地址总线
reg						psel;//从译码器来的片选信号
reg						penable;//使能信号
reg						pwrite;//高电平:写   低电平:读
reg[31:0]				pwdata;//32位宽写 
wire[31:0]			prdata;//32位宽读

wire[31:0] 			timer24;//秒计数低


hour24_counter hour24_counter(
								.pclk(pclk),
								.preset(preset),
								.s_reset(s_reset),
								.pause(pause),
								
								.paddr(paddr),//地址总线,
								.psel(psel),//从译码器来的片选信号
								.penable(penable),//使能信号
								.pwrite(pwrite),//高电平:写   低电平:读
								.pwdata(pwdata),//32位宽写 
								.prdata(prdata),//32位宽读
								
								.timer24(timer24)

								
								);
												
												
												
												
												
												
initial begin
							//preset==0,//异步复位,低电平有效//+时钟上升沿
							//res==1,//同步,高电平有效
				#0			pclk=0; preset=0; pause=0;s_reset=0;
							psel=0; 	pwrite=0; penable=0; 
							paddr=0; pwdata=0;//初始化
							
				#17 		preset=1;   // 过17ns,时钟复位解除
				#50		s_reset=1;
				#100		s_reset=0;
				#300  	pause=1;//暂停时钟,高电平有效
				#350  	pause=0;//接触时钟暂停
				#900		preset=0;
				#920		preset=1;
				#1500		s_reset=1;
				#1520		s_reset=0;
				
				#2000 	psel=1;paddr=32'h216189;pwdata={8'b0,4'd2,4'd3,4'd5,4'd9,4'd5,4'd6};
				#2010		pwrite=1;
				#2020		penable=1;//完成一次写操作
				#2200		psel=0;paddr=0;pwdata=0;
				#2230		penable=0;pwrite=0;
				
				#3500		psel=1;
				#3510		penable=1;paddr=32'h216189;
				#3520		penable=0;//完成一次读操作
				#3550		psel=0;
				
				#7000 	$stop;
end

always #5 pclk <= ~pclk;  // 以10ns为周期的时钟

endmodule



在这里插入代码片
//-----------------------------------------------------------------------------------------------
//  Copyright    : 
//  File Name    : APB_Bridge
//  Author       : Luk.wj
//  Create       : 2020.12.14
//  Revise       : 2021.12.20
//  Description  : APB_Bridge的作用是将主设备的访问信号转化成APB总线信号访问从设备
//-----------------------------------------------------------------------------------------------

/* State */
`define Idle    2'b00//空闲
`define Setup   2'b01//建立
`define Access  2'b10//可用

module APB_Bridge (
							PCLK,
							Prst,
							Haddr,
							Hwdata,
							Hwrite,
							Hen,
							Prdata_m,
							Paddr,
							Pen,
							Pwrite,
							Pwdata,
							Hrdata,
							Hready,
							PSEL0,
							PSEL1,
							PSEL2,
							PSEL3
							);
input PCLK;
input Prst;

/* AHB_Master */
input               Hwrite;
input               Hen;
input      [31:0]   Haddr;
input      [31:0]   Hwdata;
output reg          Hready;
output reg [31:0]   Hrdata;

/* APB_Slave */
input      [31:0]   Prdata_m;
output reg          Pen;
output reg          Pwrite;
output reg          PSEL0;
output reg          PSEL1;
output reg          PSEL2;
output reg          PSEL3;
output reg [31:0]   Pwdata;
output reg [31:0]   Paddr;

reg        [1:0]    APB_State;     //APB状态参数
reg        [23:0]   addr_d;        //截取总线地址的前24位选择从设备

/* 四个从设备内部变量 */
reg Hsel0;              
reg Hsel1;
reg Hsel2;
reg Hsel3;

/* Read Data */
always @(*) begin
    if (!Prst)   Hrdata = 32'h0;
    else         Hrdata = Prdata_m;
end

/* Slave Select */
always @(*) begin
    addr_d = Haddr[31:8];
    Hsel0  = 1'b0;
    Hsel1  = 1'b0;
    Hsel2  = 1'b0;
    Hsel3  = 1'b0;
    case (addr_d)
        24'h0000_00:      Hsel0 = 1'b1;
        24'h0000_01:      Hsel1 = 1'b1;
        24'h0000_02:      Hsel2 = 1'b1;
        24'h0000_03:      Hsel3 = 1'b1;
        default:   begin
            Hsel0 = 1'b0;
            Hsel1 = 1'b0;
            Hsel2 = 1'b0;
            Hsel3 = 1'b0;
        end  
    endcase
end

/* APB FSM */
always @(posedge PCLK or negedge Prst) begin
    if (!Prst) begin
        //AHB_Master
        Hready <= 1'b0;

        //APB_Slave
        APB_State <= `Idle;
        PSEL0     <= 1'b0;
        PSEL1     <= 1'b0;
        PSEL2     <= 1'b0;
        PSEL3     <= 1'b0;
        Pen       <= 1'b0;
        Pwrite    <= 1'b0;
        Pwdata    <= 32'b0;
        Paddr     <= 32'b0;
    end
    else begin
        case (APB_State)
            `Idle: begin
                if (Hen) begin
                    APB_State <= `Setup;
                    PSEL0  <= Hsel0;
                    PSEL1  <= Hsel1;
                    PSEL2  <= Hsel2;
                    PSEL3  <= Hsel3;
                    Pwrite <= Hwrite;
                    Paddr  <= Haddr;
                    Pwdata <= Hwdata;
                    Hready <= 1'b0;
                end
            end
            `Setup: begin
                APB_State <= `Access;
                Pen <= 1'b1;
                Hready <= 1'b0;
            end
            `Access: begin
                APB_State <= `Idle;
                Pen       <= 1'b0;
                PSEL0     <= 1'b0;
                PSEL1     <= 1'b0;
                PSEL2     <= 1'b0;
                PSEL3     <= 1'b0;
                Hready    <= 1'b1;
            end
            default: APB_State <= `Idle;
        endcase
    end
end

endmodule

在这里插入代码片
//2022-3-16 
//七段数码管
`timescale 1ns/10ps
module seg_dec(
					num,
					a_g
					);


input[3:0]		num;
output[6:0]		a_g;

reg[6:0] a_g;
//reg[3:0] num;
always@(num)begin
		case(num)
		//*****************abc-defg******哪个亮那个显示1
		4'd0:begin a_g<=7'b111_1110;end//a_g-->{abcdefg}
		4'd1:begin a_g<=7'b011_0001;end
		4'd2:begin a_g<=7'b110_1101;end
		4'd3:begin a_g<=7'b111_1001;end
		4'd4:begin a_g<=7'b011_0011;end
		4'd5:begin a_g<=7'b101_1011;end
		4'd6:begin a_g<=7'b101_1111;end
		4'd7:begin a_g<=7'b111_0000;end
		4'd8:begin a_g<=7'b111_1111;end
		4'd9:begin a_g<=7'b111_1011;end
		default:begin a_g<=7'b000_0001;end
		endcase
end

endmodule 

//testbench
/*
module seg_dec_tb;



seg_dec seg_dec(
					.num{},
					.a_g()
					);
	
endmodule

补码转换代码设计
七段译码代码设计
位拼接语句
case和default 的处理


*/












  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sr_shirui

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值