reg52.h中文详细注解

REG52.H是一个用于80C52和80C32微控制器的通用头文件。其中定义了各种特殊字节寄存器,如P0口、P1口、P2口、P3口、程序状态字寄存器、累加器、B特殊寄存器、堆栈指针寄存器和数字指针(低位/高位)等。此外,该头文件还定义了一些与定时器/计数器和电源控制相关的寄存器,例如PCON和TCON。定时器/计数器模式的选择由TMOD寄存器中的位控制。

现在将此文件汉化 然后用vscode 进行开发维护时,宏定义有中文提示 非常方面.
在程序编写过程中 只需要替换keil 安装目录下 的INC 头文件REG52.H

强烈建议大家使用
在这里插入图片描述

下面放出相关代码

/*--------------------------------------------------------------------------
REG52.H
 
Header file for generic 80C52 and 80C32 microcontroller.
Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software, Inc.
All rights reserved.
--------------------------------------------------------------------------*/
 
#ifndef __REG52_H__
#define __REG52_H__
 
/*  特殊字节(8位)寄存器 */
sfr P0 = 0x80;         // P0口特殊寄存器寻址位
sfr P1 = 0x90;         // P1口特殊寄存器寻址位
sfr P2 = 0xA0;         // P2口特殊寄存器寻址位
sfr P3 = 0xB0;         // P3口特殊寄存器寻址位
sfr PSW = 0xD0;         // 程序状态字寄存器
sfr ACC = 0xE0;         // 累加器
sfr B = 0xF0;         // B 特殊寄存器
sfr SP = 0x81;         // 堆栈指针寄存器
sfr DPL = 0x82;         // 数字指针(低位)
sfr DPH = 0x83;         // 数字指针(高位)
/*
电源控制寄存器
 
与串行口相关的只有SMOD ,其他的可以自己去查资料
-------------扩展资料---------------
SMOD:
在串口工作方式1,2,3中
是波特率加倍位
(产生高波特率时启用平时不用,比如用11.0592晶振产生57600波特率时就要设置成SMOD=1)
 
SMOD=1:
波特率加倍(PCON=0X80;)
SMOD=0:
波特率不加倍(PCON=0X80;)
(PCON=0X00;)
 
 
*/
sfr PCON = 0x87;
sfr TCON = 0x88; // 定时器/计数器 0 和 1 控制
 
 
/*
定时器/计数器 0 和 1 模式
 
GATE  C/T  M1  M0  GATE  C/T  M1  M0
--------------------------------------------
位                  符号          功能
TMOD.7/ GATE                  TMOD.7控制定时器1,置1时只有在INT1脚为高及TR1控制位置1       
                                    时才可打开定时器/计数器1。
TMOD.3/ GATE                  TMOD.3控制定时器0,置1时只有在INT0脚为高及TR0控制位置1       
                                    时才可打开定时器/计数器0。
TMOD.6/ C/T                  TMOD.6控制定时器1用作定时器或计数器,清零则用作定时器       
                                    (从内部系统时钟输入),置1用作计数器(从T1/P3.5脚输入)
TMOD.2/ C/T          TMOD.2控制定时器0用作定时器或计数器,清零则用作定时器       
                                    (从内部系统时钟输入),置1用作计数器(从T0/P3.4脚输入)
TMOD.5/TMOD.4 M1、M0         定时器定时器/计数器1模式选择
 
---------------------------------------------
 
0 0                  13位定时器/计数器,兼容8048定时模式,TL1只用低5位参与分频,TH1整个8位全用。
0 1                 16位定时器/计数器,TL1、TH1全用
1 0         8位自动重装载定时器,当溢出时将TH1存放的值自动重装入TL1.
1 1          定时器/计数器1此时无效(停止计数)。TMOD.1/TMOD.0 M1、M0 定时器/计数器0模式选择
0 0          13位定时器/计数器,兼容8048定时模式,TL0只用低5位参与分频,TH0整个8位全用。
0 1          16位定时器/计数器,TL0、TH0全用
1 0        8位自动重装载定时器,当溢出时将TH0存放的值自动重装入TL0
1 1         定时器0此时作为双8位定时器/计数器。TL0作为一个8位定时器/计数器,通过标准定时器0的控制位控制。TH0仅作为一个8位定时器,由定时器1的控制位控制。
 
 
*/
sfr TMOD = 0x89;
 
 
 
sfr TL0 = 0x8A;         // 定时器/计数器 0 低8位寄存器
sfr TL1 = 0x8B;         // 定时器/计数器 1低8位寄存器
sfr TH0 = 0x8C;         // 定时器/计数器 0高8位寄存器
sfr TH1 = 0x8D;         // 定时器/计数器 1高8位寄存器
sfr IE = 0xA8;         // 中断允许寄存器
sfr IP = 0xB8;         // 中断优先寄存器(低)
sfr SCON = 0x98; // 串口控制寄存器
sfr SBUF = 0x99; // 串口数据缓冲器
 
/*  8052扩展寄存器 */
sfr T2CON = 0xC8;  // 定时器/计数器2 控制
sfr RCAP2L = 0xCA; // 定时器/计数器2 重载/捕捉低位
sfr RCAP2H = 0xCB; // 定时器/计数器2 重载/捕捉高位
sfr TL2 = 0xCC;           // 定时器/计数器2 低位
sfr TH2 = 0xCD;           // 定时器/计数器2 高位
 
/*  位寄存器  */
 
/*  PSW (程序状态字寄存器) */
sbit CY = PSW ^ 7;        // 进位、借位标志。进位、借位CY=1;否则CY=0
sbit AC = PSW ^ 6;        // 辅助进位、借位标志。当D3向D4有借位或进位时,AC=1;否则AC=0
sbit F0 = PSW ^ 5;        // 用户标志位
sbit RS1 = PSW ^ 4; // 寄存器组选择控制位1
sbit RS0 = PSW ^ 3; // 寄存器组选择控制位0
sbit OV = PSW ^ 2;        // 溢出标志。有溢出OV=1,否则OV=0
sbit F1 = PSW ^ 1;        // 保留位,无定义
sbit P = PSW ^ 0;        // 8052 only 奇偶校验标志位,由硬件置位或清0;
                                  // 存在ACC中的运算结果有奇数个1时P=1,否则P=0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/*  TCON (定时器/计数器 0 和 1 控制) */
 
/*定时器1溢出标志位。
 
当定时器1计满溢出时, 由硬件使TF1置“1”,并且申请中断。
进入中断服务程序后,由硬件自动清“0”,在查询方式下用软件清 “0”*/
sbit TF1 = TCON ^ 7;
/*定时器1运行控制位。
 
由软件清“0”关闭定时器1。
当GATE=1,且INT1为高电平时,TR1置“1”启动定时器1;
当GATE=0,TR1置“1” 启动定时器1*/
sbit TR1 = TCON ^ 6;
/*
定时器0溢出标志。
 
T0溢出中断标志。T0被允许计数以后,从初值开始加1计数,当产生溢出时,由硬件置
“1”TF0,向CPU请求中断,一直保持CPU响应该中断时,才由硬件清0(也可由查询
软件清0)。
*/
sbit TF0 = TCON ^ 5;
 
/*定时器0运行控制位。
 
由软件清“0”关闭定时器0。
当GATE=1,且INT0为高电平时,TR0置“1”启动定时器0;
当GATE=0,TR0置“1” 启动定时器0*/
sbit TR0 = TCON ^ 4;
 
/*
外部中断1请求标志。
 
 
外部中断1请求源(INT1/P3.3)标志。IE1=1,外部中断向CPU请求中断,当CPU响应该
中断时由硬件清“0”IE1。
 
*/
sbit IE1 = TCON ^ 3;
 
/*
外部中断1触发方式选择位。
 
IT1=0,INT1/P3.3引脚上的低电平信号可触发外部中断1。IT1=1,外部中断1为下降沿触发方式。
*/
sbit IT1 = TCON ^ 2;
/*
外部中断0请求标志。
 
外部中断0请求源(INT0/P3.2)标志。IE0=1外部中断0向CPU请求中断,当CPU响应外
部中断时,由硬件清“0”IE0(边沿触发方式)。
*/
sbit IE0 = TCON ^ 1;
 
/*
外部中断0触发方式选择位。
 
外部中断0中断源类型选择位。IT0=0,INT0/P3.2引脚上的低电平可触发外部中断0。
IT0=1,外部中断0为下降沿触发方式。
*/
sbit IT0 = TCON ^ 0;
 
/* IE (中断允许寄存器) */
 
/*
允许/禁止总中断
CPU的总中断允许控制位,EA=1,CPU开放中断,EA=0,CPU屏蔽所有的中断申请。
EA的作用是使中断允许形成两级控制。即各中断源首先受EA控制;其次还受各中断源自
己的中断允许控制位控制。
*/
sbit EA = IE ^ 7;
 
/*
8052 only 允许/禁止定时器2(T2)中断
 
定时/计数器T2的溢出中断允许位。ET2=1,允许T2中断;ET2=0,禁止T2中断。
*/
sbit ET2 = IE ^ 5;
 
/*
允许/禁止串口中断
 
串行口1中断允许位。ES=1,允许串行口1中断;ES=0,禁止串行口1中断。
 
*/
sbit ES = IE ^ 4;
 
/*允许/禁止T1溢出中断
 
定时/计数器T1的溢出中断允许位。ET1=1,允许T1中断;ET1=0,禁止T1中断。
 
*/
sbit ET1 = IE ^ 3;
/*
允许/禁止外部中断1[INT1].
 
外部中断1中断允许位。EX1=1,允许外部中断1中断;EX1=0,禁止外部中断1中断。
 
*/
sbit EX1 = IE ^ 2;
/*
允许/禁止T0溢出中断
 
ET0=1,允许T0中断;ET0=0禁止T0中断。
*/
sbit ET0 = IE ^ 1;
 
/*
允许/禁止外部中断0(INT0)
 
EX0=1,允许中断;EX0=0禁止中断。
*/
sbit EX0 = IE ^ 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/* IP (中断优先寄存器低)
 
2. 中断优先级控制寄存器IP/XICON和IPH
传统8051单片机具有两个中断优先级,即高优先级和低优先级,可以实现两级中断嵌套。
STC89C52系列单片机通过设置新增加的特殊功能寄存器(IPH/XICON)中的相应位,可将中断优
先级设置为4个中断优先级;如果只设置IP,那么中断优先级只有两级,与传统8051单片机两
级中断优先级完全兼容。
一个正在执行的低优先级中断能被高优先级中断所中断,但不能被另一个低优先级中断所
中断,一直执行到结束,遇到返回指令RETI,返回主程序后再执行一条指令才能响应新的中
断申请。以上所述可归纳为下面两条基本规则:
⒈ 低优先级中断可被高优先级中断所中断,反之不能。
⒉ 任何一种中断(不管是高级还是低级),一旦得到响应,不会再被它的同级中断所中断
STC89C52系列单片机的片内各优先级控制寄存器的格式如下:
IPH: 中断优先级控制寄存器高(不可位寻址)
SFR name Address bit B7 B6 B5 B4 B3 B2 B1 B0
IPH B7H name PX3H PX2H PT2 PSH PT1H PX1H PT0H PX0H
XICON : 辅助中断控制寄存器 (可位寻址)
SFR name Address bit B7 B6 B5 B4 B3 B2 B1 B0
XICON C0H name PX3 EX3 IE3 IT3 PX2 EX2 IE2 IT2
IP : 中断优先级控制寄存器低 (可位寻址)
SFR name Address bit B7 B6 B5 B4 B3 B2 B1 B0
IP B8H name - - PT2 PS PT1 PX1 PT0 PX0
PX3H, PX3: 外部中断3优先级控制位。
当PX3H=0且PX3=0时,外部中断3为最低优先级中断(优先级0)
当PX3H=0且PX3=1时,外部中断3为较低优先级中断(优先级1)
当PX3H=1且PX3=0时,外部中断3为较高优先级中断(优先级2)
当PX3H=1且PX3=1时,外部中断3为最高优先级中断(优先级3)
PX2H, PX2: 外部中断2优先级控制位。
当PX2H=0且PX2=0时,外部中断2为最低优先级中断(优先级0)
当PX2H=0且PX2=1时,外部中断2为较低优先级中断(优先级1)
当PX2H=1且PX2=0时,外部中断2为较高优先级中断(优先级2)
当PX2H=1且PX2=1时,外部中断2为最高优先级中断(优先级3)
163
STC MCU Limited.
南通国芯微电子有限公司 总机:0513-5501 2928 / 2929 / 2966 传真:0513-5501 2969 / 2956 / 2947
STC89C52系列单片机指南 官方网站:[url]www.STCMCU.com[/url] 研发顾问QQ:800003751 STC — 全球最大的8051单片机设计公司
PT2H, PT2: 定时器2中断优先级控制位。
当PT2H=0且PT2=0时,定时器2中断为最低优先级中断(优先级0)
当PT2H=0且PT2=1时,定时器2中断为较低优先级中断(优先级1)
当PT2H=1且PT2=0时,定时器2中断为较高优先级中断(优先级2)
当PT2H=1且PT2=1时,定时器2中断为最高优先级中断(优先级3)
PSH, PS: 串口1中断优先级控制位。
当PSH=0且PS=0时,串口1中断为最低优先级中断(优先级0)
当PSH=0且PS=1时,串口1中断为较低优先级中断(优先级1)
当PSH=1且PS=0时,串口1中断为较高优先级中断(优先级2)
当PSH=1且PS=1时,串口1中断为最高优先级中断(优先级3)
PT1H, PT1: 定时器1中断优先级控制位。
当PT1H=0且PT1=0时,定时器1中断为最低优先级中断(优先级0)
当PT1H=0且PT1=1时,定时器1中断为较低优先级中断(优先级1)
当PT1H=1且PT1=0时,定时器1中断为较高优先级中断(优先级2)
当PT1H=1且PT1=1时,定时器1中断为最高优先级中断(优先级3)
PX1H, PX1: 外部中断1优先级控制位。
当PX1H=0且PX1=0时,外部中断1为最低优先级中断(优先级0)
当PX1H=0且PX1=1时,外部中断1为较低优先级中断(优先级1)
当PX1H=1且PX1=0时,外部中断1为较高优先级中断(优先级2)
当PX1H=1且PX1=1时,外部中断1为最高优先级中断(优先级3)
PT0H, PT0: 定时器0中断优先级控制位。
当PT0H=0且PT0=0时,定时器0中断为最低优先级中断(优先级0)
当PT0H=0且PT0=1时,定时器0中断为较低优先级中断(优先级1)
当PT0H=1且PT0=0时,定时器0中断为较高优先级中断(优先级2)
当PT0H=1且PT0=1时,定时器0中断为最高优先级中断(优先级3)
PX0H, PX0: 外部中断0优先级控制位。
当PX0H=0且PX0=0时,外部中断0为最低优先级中断(优先级0)
当PX0H=0且PX0=1时,外部中断0为较低优先级中断(优先级1)
当PX0H=1且PX0=0时,外部中断0为较高优先级中断(优先级2)
当PX0H=1且PX0=1时,外部中断0为最高优先级中断(优先级3)
中断优先级控制寄存器IP和IPH的各位都由可用户程序置“1”和清“0”。但IP寄存器可
位操作,所以可用位操作指令或字节操作指令更新IP的内容。而IPH寄存器的内容只能用字节
操作指令来更新。STC89C52系列单片机复位后IP和IPH均为00H,各个中断源均为低优先级中
断。
 
*/
sbit PT2 = IP ^ 5; // 定时/计数器T2优先级设定位。
sbit PS = IP ^ 4;  // 串行口优先级设定位;
sbit PT1 = IP ^ 3; // 定时/计数器T1优先级设定位;
sbit PX1 = IP ^ 2; // 外部中断0优先级设定位;
sbit PT0 = IP ^ 1; // 定时/计数器T0优先级设定位;
sbit PX0 = IP ^ 0; // 外部中断0优先级设定位;
 
/* P3 (第二功能) */
sbit RD = P3 ^ 7;        // 外部数据存储器读脉冲
sbit WR = P3 ^ 6;        // 外部数据存储器写脉冲
sbit T1 = P3 ^ 5;        // 定时器/计数器1外部输入
sbit T0 = P3 ^ 4;        // 定时器/计数器0外部输入
sbit INT1 = P3 ^ 3; // 外部中断0。
sbit INT0 = P3 ^ 2; // 外部中断1。
sbit TXD = P3 ^ 1;        // 串行数据输出口
sbit RXD = P3 ^ 0;        // 串行数据输入口
 
/* SCON(控制寄存器,它是一个可寻址的专用寄存器,用于串行数据的通信控制) */
 
/* 串行口工作方式控制位0。
 
工作方式的分类:
 
SM0----SM1----工作方式----说明     
0   0   0        移位寄存器
0   1   1        10位异步收发器(8位数据)
1   0   2        11位异步收发器(8位数据)
1   1   3        11位异步收发器(9位数据)
 
 
 
*/
sbit SM0 = SCON ^ 7;
/* 串行口工作方式控制位1。
 
工作方式的分类:
 
SM0----SM1----工作方式----说明     
0   0   0        移位寄存器
0   1   1        10位异步收发器(8位数据)
1   0   2        11位异步收发器(8位数据)
1   1   3        11位异步收发器(9位数据)
*/
sbit SM1 = SCON ^ 6;
sbit SM2 = SCON ^ 5; // 多机通信控制位。
sbit REN = SCON ^ 4; // 允许接收位。用于控制数据接收的允许和禁止,ren=1时,允许接收,ren=0时,禁止接收。
sbit TB8 = SCON ^ 3; // 发送接收数据位8。(校验位)
sbit RB8 = SCON ^ 2; // 接收数据位8。(校验位)
/*
// 发送中断标志位。
 
如果TI=1,表示已经结束一帧数据的发送,
 
可由软件查询TI标志,也可向CPU申请中断
 
(注意:TI在任何工作方式下,都必须由软件清0才能再次发送数据)
 
中断地址:0023H
 
由于TI和RI 的中断入口相同,所以接收和发送时,需要在中断函数查询TI和RI的值做判断处理
*/
sbit TI = SCON ^ 1;         
 
/*
// 接收中断标志位。
 
如果RI=1,表示一帧数据接收结束.
 
可由软件查询RI标志,也可向CPU申请中断.
 
(注意:RI在任何工作方式下,都必须由软件清0才能再次发送数据)
 
中断地址:0023H
 
由于TI和RI 的中断入口相同,所以接收和发送时,需要在中断函数查询TI和RI的值做判断处理
*/
sbit RI = SCON ^ 0;         
 
 
/*  P1(第二功能) */
sbit T2EX = P1 ^ 1; // 8052 only        定时/计数器2捕捉/重装入触发
sbit T2 = P1 ^ 0;        // 8052 only        定时/计数器2外部输入
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/*  T2CON  (定时器/计数器2 控制) */
 
/*
定时器2 溢出标记
 
定时器2 溢出标志。定时器2溢出时置位,必须由软件清除。当RCLK或TCLK=1 时,
 
*/
sbit TF2 = T2CON ^ 7;
 
/*
定时器2 外部标记
 
定时器2外部标志。当EXEN2=1且T2EX的负跳变产生捕获或重装时,EXF2置位。定
时器2 中断使能时,EXF2=1将使CPU从中断向量处执行定时器2 中断子程序。EXF2
位必须用软件清零。在递增/递减计数器模式(DCEN=1)中,EXF2不会引起中断
*/
sbit EXF2 = T2CON ^ 6;       
 
/*
接收时钟标识
 
.0=串口时钟应用定时器1 溢出,  1=定时器 2
RCLK : RCLK置位时,定时器2的溢出脉冲作为串行口模式1和模式3的接收时钟。RCLK=0时,将定时器1的溢出脉冲作为接收时钟
*/
sbit RCLK = T2CON ^ 5;         
 
/*
发送时钟标志.
 
0=串口时钟应用定时器1 溢出,  1=定时器 2
TCLK : TCLK置位时,定时器2的溢出脉冲作为串行口模式1和模式3的发送时钟。TCLK=0时,将定时器1的溢出脉冲作为发送时钟
 
 
 
*/
sbit TCLK = T2CON ^ 4;       
 
/*
定时器 2 外部允许
 
定时器 2 外部使能标志。当其置位且定时器2未作为串行口时钟时,允许T2EX的负跳变产生捕获或重装。EXEN2=0 时,T2EX的跳变对定时器2无效
 
 
*/
sbit EXEN2 = T2CON ^ 3;       
sbit TR2 = T2CON ^ 2;         // 0=停止定时器, 1=开始定时器
 
/*
定时器/计数器选择
 
0 = 内部定时器(OSC/12 或OSC/6)
1 = 外部事件计数器(下降沿触发)
*/
sbit C_T2 = T2CON ^ 1;         
 
 
/* 重载/ 重装标志
 
0=重载, 1=捕捉选择
CP/RL2 : / 重装标志。置位:EXEN2=1 时,T2EX 的负跳变产生捕获。 清零:EXEN2=0 时,
定时器2溢出或T2EX 的负跳变都可使定时器自动重装。当RCLK=1 或TCLK=1时,该位无效且定时器强制为溢出时自动重装
 
 
 
 
*/
sbit CP_RL2 = T2CON ^ 0;
 
 
 
#endif
module timing_check ( input rst, input clk, //100M input work_mode_vld, //数据有效指示 input [7:0] work_mode, //输入数据 output reg start_req, input en, output reg busy, //定时三模与ctrl_flash_top接口 output reg check_read, output reg [31:0] flash_addr, output [63:0] flash_read_length, output reg err_flag, input clk_rdflash, input rdflash_out_valid, input [63:0] rd_byte_cnt, input [7:0] rdflash_out1, input [7:0] rdflash_out2, input [7:0] rdflash_out3, input flash_busy, //高有效 //擦除 output reg begin_erase, //单拍脉冲,开始擦除指令 //写入 output reg begin_write, //单拍脉冲,开始写入指令 output reg [9:0] write_length, //在新的写单脉冲信号来之前保持原值,新的写脉冲来后同步更新 output wdata_valid, //数据有效指示 output reg [7:0] write_data, //有效数据 //读取 output reg begin_read, //单拍脉冲,开始读取指令 output reg [9:0] read_length, //在新的读单脉冲信号来之前保持原值,新的读脉冲来后同步更新 input read_valid, input [7:0] read_data_1, input [7:0] read_data_2, input [7:0] read_data_3, //localbus input cs, input we, input oe, input [8:0] addr, input [31:0] data_in, output [31:0] data_out, output ta ); /****************************************************************************\ Parameter/Define \****************************************************************************/ parameter [3:0] IDLE = 4'd0, HAND = 4'd1, MONI = 4'd2, ERAS_0 = 4'd3, READ_0 = 4'd4, WRIT_0 = 4'd5, ERAS_1 = 4'd6, READ_1 = 4'd7, WRIT_1 = 4'd8, BUFF = 4'd9, WAIT = 4'd10; //localparam [27:0] TIME_1S = 100_000_000;// 1S localparam [27:0] TIME_1S = 10_000;// sim_mode localparam [7:0] CHECK_TIME = 30;//30分钟 localparam [7:0] BASE_REGS = 8'h0; localparam [7:0] BASE_RAMS = 8'h80; /****************************************************************************\ Input/Output \****************************************************************************/ /****************************************************************************\ Register/Wire \****************************************************************************/ reg [3:0] curr_st; reg [3:0] next_st; reg [7:0] work_mode_d1; reg en_d1; reg rdflash_out_valid_d1; reg [63:0] rd_byte_cnt_d1; reg rdflash_err; reg [7:0] err_cnt; //reg err_flag; wire fifo_wr; reg fifo_rd; reg fifo_rd_d1; reg fifo_rd_d2; reg fifo_rd_d3; wire fifo_empty; reg fifo_empty_d1; wire[63:0] fifo_out; reg [63:0] rdflash_addr; reg [63:0] eras_ram_addr; reg [7:0] flash_256knum; reg flash_busy_d1; reg flash_busy_d2; reg [11:0] cycle_cnt; wire rd_vld_ram; reg [8:0] ram_wr_addr; wire rd_vld_buff; reg [8:0] buff_wr_addr; reg ram_rd_en; reg ram_rd_en_d1; reg ram_rd_en_d2; reg [8:0] ram_rd_addr; wire[7:0] ram_dout1; wire[7:0] ram_dout2; wire[7:0] ram_dout3; reg [27:0] nsec_cnt; //纳秒 reg [7:0] sec_cnt; //秒 reg [7:0] min_cnt; //分 wire cs_reg; wire cs_ram; wire[7:0] adr_reg; wire[7:0] adr_ram; reg [31:0] dout_reg; wire[31:0] dout_ram; reg [31:0] data_out_d1; reg [31:0] test_reg; reg [31:0] bit_err_cnt; reg [7:0] bit_flag; reg [31:0] byte_err_cnt; reg read_valid_d1; reg read_valid_d2; wire rd_vld_three; reg [8:0] wr_addr_three; reg three_rd_en; reg three_rd_en_d1; reg three_rd_en_d2; reg [8:0] three_rd_addr; wire[7:0] three_dout1; reg [35:0] state2_cnt; reg [35:0] state3_cnt; reg [35:0] state4_cnt; reg [35:0] state5_cnt; /****************************************************************************\ Main Code \****************************************************************************/ // always @(posedge clk) work_mode_d1 <= work_mode; // always @(posedge clk) if(rst) curr_st <= IDLE; else curr_st <= next_st; // always @(*) case (curr_st) IDLE : if(~rst) next_st = HAND; else if(work_mode_vld && work_mode == 8'h0 && (work_mode_d1 == 8'h30 || work_mode_d1 == 8'hc0)) next_st = HAND; else next_st = IDLE; HAND : if(busy) next_st = MONI; else next_st = HAND; MONI : if(err_flag && ~flash_busy && flash_busy_d1)//在检测错误,检测到,就擦缓冲第一,这个也是读,读的地址会变化 next_st = ERAS_0; else if(~flash_busy && flash_busy_d1) //没检测到错误就去等待read_valid下降沿边,然后就去等30分钟再弄一遍 next_st = BUFF; else next_st = MONI; ERAS_0 : if(~flash_busy && flash_busy_d1) //在擦缓冲第一,如果擦完就读错误扇区 next_st = READ_0; else next_st = ERAS_0; READ_0 : if(~flash_busy && ~read_valid_d1 && read_valid_d2) //正在读错误扇区,一次读512,读完就写 next_st = WRIT_0; else next_st = READ_0; WRIT_0 : if(cycle_cnt == 12'd512 && ~flash_busy && flash_busy_d1) //正在写在缓冲区,三模且写完了512次就擦错误扇区,不然继续写完继续读再继续写,ERAS_0,READ_0,WRIT_0就是一个256扇区 next_st = ERAS_1; else if(~flash_busy && flash_busy_d1) next_st = READ_0; else next_st = WRIT_0; ERAS_1 : if(~flash_busy && flash_busy_d1) //正在擦错误扇区,擦完读READ_1缓冲区 next_st = READ_1; else next_st = ERAS_1; READ_1 : if(~flash_busy && ~read_valid_d1 && read_valid_d2) //读完就写,把从缓冲区读到的复制到错误区 next_st = WRIT_1; else next_st = READ_1; WRIT_1 : if(flash_256knum == 8'd191 && cycle_cnt == 12'd1024 && ~flash_busy && flash_busy_d1) //读写了191次代表全搞完了,我不需要191次 next_st = BUFF; else if(cycle_cnt == 12'd1024 && ~flash_busy && flash_busy_d1) //之前计数就是512,现在搬完了也就1024了 next_st = MONI; else if(~flash_busy && flash_busy_d1) next_st = READ_1; else next_st = WRIT_1; BUFF : if(~flash_busy && ~read_valid_d1 && read_valid_d2) next_st = WAIT; else next_st = BUFF; WAIT : if(min_cnt == CHECK_TIME) next_st = IDLE; else next_st = WAIT; default : next_st = IDLE; endcase // always @(posedge clk) en_d1 <= en; // always @(posedge clk) if(rst) start_req <= 1'b0; else if(curr_st == IDLE && next_st == HAND) start_req <= 1'b1; else if(curr_st == HAND && en && ~en_d1) start_req <= 1'b0; // always @(posedge clk) if(rst) busy <= 1'b0; else if(curr_st == IDLE) busy <= 1'b0; else if(curr_st == HAND && en && ~en_d1) busy <= 1'b1; else if(curr_st == WAIT) busy <= 1'b0; // always @(posedge clk) if(rst) check_read <= 1'b0; else if(curr_st == HAND && next_st == MONI) check_read <= 1'b1; else if(curr_st == WRIT_1 && next_st == MONI) check_read <= 1'b1; else check_read <= 1'b0; // assign flash_read_length = 64'h300_0000; // always @(posedge clk) if(rst) flash_addr <= 32'h0; else if(curr_st == HAND && next_st == MONI) flash_addr <= 32'h0; else if(curr_st == WRIT_1 && next_st == MONI) flash_addr <= flash_256knum * 16'd256 * 16'd1024 + 16'd256 * 16'd1024; else if(curr_st == MONI && next_st == ERAS_0) flash_addr <= 32'h300_0000; else if(curr_st == ERAS_0 && next_st == READ_0) flash_addr <= flash_256knum * 16'd256 * 16'd1024 + cycle_cnt * 10'd512; else if(curr_st == WRIT_0 && next_st == READ_0) flash_addr <= flash_256knum * 16'd256 * 16'd1024 + cycle_cnt * 10'd512; else if(curr_st == READ_0 && next_st == WRIT_0) flash_addr <= 32'h300_0000 + cycle_cnt * 10'd512; else if(curr_st == WRIT_0 && next_st == ERAS_1) flash_addr <= flash_256knum * 16'd256 * 16'd1024 + (cycle_cnt - 10'd512) * 10'd512; else if(curr_st == ERAS_1 && next_st == READ_1) flash_addr <= 32'h300_0000 + (cycle_cnt - 10'd512) * 10'd512; else if(curr_st == WRIT_1 && next_st == READ_1) flash_addr <= 32'h300_0000 + (cycle_cnt - 10'd512) * 10'd512; else if(curr_st == READ_1 && next_st == WRIT_1) flash_addr <= flash_256knum * 16'd256 * 16'd1024 + (cycle_cnt - 10'd512) * 10'd512; else if(curr_st == MONI && next_st == BUFF) flash_addr <= 64'h2fc_0000; else if(curr_st == WRIT_1 && next_st == BUFF) flash_addr <= 64'h2fc_0000; else flash_addr <= flash_addr; // always @(posedge clk_rdflash) begin rdflash_out_valid_d1 <= rdflash_out_valid; rd_byte_cnt_d1 <= rd_byte_cnt; end // always @(posedge clk_rdflash) if(~rdflash_out_valid) rdflash_err <= 1'b0; else if(rdflash_out1 != rdflash_out2) rdflash_err <= 1'b1; else if(rdflash_out1 != rdflash_out3) rdflash_err <= 1'b1; else rdflash_err <= 1'b0; // always @(posedge clk_rdflash) if(~rdflash_out_valid_d1) err_cnt <= 8'h0; else if(rdflash_err && err_cnt == 8'h0) err_cnt <= err_cnt + 1'b1; else err_cnt <= err_cnt; assign fifo_wr = rdflash_err && err_cnt == 8'h0; // always @(posedge clk) fifo_empty_d1 <= fifo_empty; // always @(posedge clk) if(rst) fifo_rd <= 1'b0; else if(~fifo_empty & fifo_empty_d1) fifo_rd <= 1'b1; else fifo_rd <= 1'b0; // always @(posedge clk) begin fifo_rd_d1 <= fifo_rd; fifo_rd_d2 <= fifo_rd_d1; fifo_rd_d3 <= fifo_rd_d2; end // always @(posedge clk) if(rst) err_flag <= 1'b0; else if(fifo_rd & ~fifo_rd_d1) err_flag <= 1'b1; else if(curr_st == MONI && next_st == ERAS_0) err_flag <= 1'b0; else err_flag <= err_flag; // always @(posedge clk) if(rst) rdflash_addr <= 64'h0; else if(fifo_rd_d1) rdflash_addr <= fifo_out; else rdflash_addr <= rdflash_addr; // async_fifo_mc #( .DWIDTH (64 ), .AWIDTH (4 ), .SHOWAHEAD_MODE ("OFF" ), .OUTPUTREG ("OFF" ) ) u_async_fifo_mc ( .aclr (rst ), // I .wrclk (clk_rdflash ), // I .wrreq (fifo_wr ), // I .rdclk (clk ), // I .rdreq (fifo_rd ), // I .din (rd_byte_cnt_d1 ), // I .wr_cnt ( ), // O .qout (fifo_out ), // O .wr_full ( ), // O .rd_empty (fifo_empty ), // O .rd_cnt ( ) // O ); // always @(posedge clk) if(rst) flash_256knum <= 8'h0; else if(curr_st == WAIT) flash_256knum <= 8'h0; else if(curr_st == WRIT_1 && cycle_cnt == 12'd1024 && ~flash_busy && flash_busy_d1) flash_256knum <= flash_256knum + 1'b1; else if(fifo_rd_d2) flash_256knum <= flash_256knum + (rdflash_addr >> 18); else flash_256knum <= flash_256knum; // always @(posedge clk) if(rst) begin_erase <= 1'b0; else if(curr_st == MONI && next_st == ERAS_0) begin_erase <= 1'b1; else if(curr_st == WRIT_0 && next_st == ERAS_1) begin_erase <= 1'b1; else begin_erase <= 1'b0; // always @(posedge clk) begin flash_busy_d1 <= flash_busy; flash_busy_d2 <= flash_busy_d1; end // always @(posedge clk) if(rst) cycle_cnt <= 12'd0; else if(curr_st == MONI) cycle_cnt <= 12'd0; else if(begin_write) cycle_cnt <= cycle_cnt + 1'b1; else cycle_cnt <= cycle_cnt; // always @(posedge clk) begin read_valid_d1 <= read_valid; read_valid_d2 <= read_valid_d1; end // always @(posedge clk) if(rst) begin_read <= 1'b0; else if(curr_st == ERAS_0 && next_st == READ_0) begin_read <= 1'b1; else if(curr_st == WRIT_0 && next_st == READ_0) begin_read <= 1'b1; else if(curr_st == ERAS_1 && next_st == READ_1) begin_read <= 1'b1; else if(curr_st == WRIT_1 && next_st == READ_1) begin_read <= 1'b1; else if(curr_st == MONI && next_st == BUFF) begin_read <= 1'b1; else if(curr_st == WRIT_1 && next_st == BUFF) begin_read <= 1'b1; else begin_read <= 1'b0; // always @(posedge clk) if(rst) read_length <= 10'h0; else if(curr_st == ERAS_0 && next_st == READ_0) read_length <= 10'h200; else if(curr_st == MONI && next_st == BUFF) read_length <= 10'h200; else read_length <= read_length; assign rd_vld_ram = (curr_st == READ_0) ? read_valid : 1'b0; // always @(posedge clk) if(rst) ram_wr_addr <= 9'h0; else if(rd_vld_ram) ram_wr_addr <= ram_wr_addr + 1'b1; else ram_wr_addr <= ram_wr_addr; assign rd_vld_buff = (curr_st == BUFF) ? read_valid : 1'b0; // always @(posedge clk) if(rst) buff_wr_addr <= 9'h0; else if(rd_vld_buff) buff_wr_addr <= buff_wr_addr + 1'b1; else buff_wr_addr <= buff_wr_addr; // always @(posedge clk) if(rst) ram_rd_addr <= 9'h0; else if(ram_rd_en) ram_rd_addr <= ram_rd_addr + 1'b1; else ram_rd_addr <= ram_rd_addr; // always @(posedge clk) if(rst) ram_rd_en <= 1'b0; else if(curr_st == READ_0 && next_st == WRIT_0) ram_rd_en <= 1'b1; else if(ram_rd_addr == 9'd511) ram_rd_en <= 1'b0; else ram_rd_en <= ram_rd_en; // always @(posedge clk) begin ram_rd_en_d1 <= ram_rd_en; ram_rd_en_d2 <= ram_rd_en_d1; end // always @(posedge clk) if(rst) begin_write <= 1'b0; else if(ram_rd_en_d1 & ~ram_rd_en_d2) begin_write <= 1'b1; else if(three_rd_en_d1 & ~three_rd_en_d2) begin_write <= 1'b1; else begin_write <= 1'b0; // always @(posedge clk) if(rst) write_length <= 10'h0; else if(ram_rd_en_d1 & ~ram_rd_en_d2) write_length <= 10'h200; else write_length <= write_length; // assign wdata_valid = ram_rd_en_d2 | three_rd_en_d2; //三模 genvar i; generate for (i = 0; i < 8; i = i+1) begin : three_one // always @(posedge clk) if(rst) write_data[i] <= 1'b0; else if(ram_rd_en_d1) begin if(ram_dout1[i] == ram_dout2[i]) write_data[i] <= ram_dout1[i]; else if(ram_dout2[i] == ram_dout3[i]) write_data[i] <= ram_dout2[i]; else if(ram_dout3[i] == ram_dout1[i]) write_data[i] <= ram_dout3[i]; end else if(three_rd_en_d1) write_data[i] <= three_dout1[i]; else write_data[i] <= 1'b0; // always @(posedge clk) if(rst) bit_flag[i] <= 1'b0; else if(ram_rd_en_d1) begin if(ram_dout1[i] == ram_dout2[i] && ram_dout2[i] == ram_dout3[i]) bit_flag[i] <= 1'b0; else bit_flag[i] <= 1'b1; end else bit_flag[i] <= 1'b0; end endgenerate // always @(posedge clk) if(rst) bit_err_cnt <= 32'h0; else if(ram_rd_en_d2) bit_err_cnt <= bit_err_cnt + bit_flag[0] + bit_flag[1] + bit_flag[2] + bit_flag[3] + bit_flag[4] + bit_flag[5] + bit_flag[6] + bit_flag[7]; else bit_err_cnt <= bit_err_cnt; // always @(posedge clk) if(rst) byte_err_cnt <= 32'h0; else if(|bit_flag) byte_err_cnt <= byte_err_cnt + 1'b1; else byte_err_cnt <= byte_err_cnt; //flash 1 sdp_ram_mc #( .DWIDTH_A (8 ), .AWIDTH_A (9 ), .DWIDTH_B (8 ), .AWIDTH_B (9 ), .OUTPUTREG ("OFF" ) ) u1_sdp_ram_mc ( .wrclk (clk ), // I .we (rd_vld_ram ), // I .wraddr (ram_wr_addr ), // I .din (read_data_1 ), // I .rdclk (clk ), // I .rdaddr (ram_rd_addr ), // I .dout (ram_dout1 ) // O ); //flash 2 sdp_ram_mc #( .DWIDTH_A (8 ), .AWIDTH_A (9 ), .DWIDTH_B (8 ), .AWIDTH_B (9 ), .OUTPUTREG ("OFF" ) ) u2_sdp_ram_mc ( .wrclk (clk ), // I .we (rd_vld_ram ), // I .wraddr (ram_wr_addr ), // I .din (read_data_2 ), // I .rdclk (clk ), // I .rdaddr (ram_rd_addr ), // I .dout (ram_dout2 ) // O ); //flash 3 sdp_ram_mc #( .DWIDTH_A (8 ), .AWIDTH_A (9 ), .DWIDTH_B (8 ), .AWIDTH_B (9 ), .OUTPUTREG ("OFF" ) ) u3_sdp_ram_mc ( .wrclk (clk ), // I .we (rd_vld_ram ), // I .wraddr (ram_wr_addr ), // I .din (read_data_3 ), // I .rdclk (clk ), // I .rdaddr (ram_rd_addr ), // I .dout (ram_dout3 ) // O ); // assign rd_vld_three = (curr_st == READ_1) ? read_valid : 1'b0; // always @(posedge clk) if(rst) wr_addr_three <= 9'h0; else if(rd_vld_three) wr_addr_three <= wr_addr_three + 1'b1; else wr_addr_three <= wr_addr_three; // always @(posedge clk) if(rst) three_rd_addr <= 9'h0; else if(three_rd_en) three_rd_addr <= three_rd_addr + 1'b1; else three_rd_addr <= three_rd_addr; // always @(posedge clk) if(rst) three_rd_en <= 1'b0; else if(curr_st == READ_1 && next_st == WRIT_1) three_rd_en <= 1'b1; else if(three_rd_addr == 9'd511) three_rd_en <= 1'b0; else three_rd_en <= three_rd_en; // always @(posedge clk) begin three_rd_en_d1 <= three_rd_en; three_rd_en_d2 <= three_rd_en_d1; end //three mode sdp_ram_mc #( .DWIDTH_A (8 ), .AWIDTH_A (9 ), .DWIDTH_B (8 ), .AWIDTH_B (9 ), .OUTPUTREG ("OFF" ) ) u4_sdp_ram_mc ( .wrclk (clk ), // I .we (rd_vld_three ), // I .wraddr (wr_addr_three ), // I .din (read_data_1 ), // I .rdclk (clk ), // I .rdaddr (three_rd_addr ), // I .dout (three_dout1 ) // O ); // sdp_ram_mc #( .DWIDTH_A (8 ), .AWIDTH_A (9 ), .DWIDTH_B (32 ), .AWIDTH_B (7 ), .OUTPUTREG ("OFF" ) ) u_buff_ram_mc ( .wrclk (clk ), // I .we (rd_vld_buff ), // I .wraddr (buff_wr_addr ), // I .din (read_data_1 ), // I .rdclk (clk ), // I .rdaddr (adr_ram[6:0] ), // I .dout ({dout_ram[7:0], dout_ram[15:8], dout_ram[23:16], dout_ram[31:24]}) // O ); // always @(posedge clk) if(rst) nsec_cnt <= 28'h0; else if(curr_st == WAIT) begin if(nsec_cnt < TIME_1S - 1'b1) nsec_cnt <= nsec_cnt + 1'b1; else nsec_cnt <= 28'h0; end else nsec_cnt <= 28'h0; // always @(posedge clk) if(rst) sec_cnt <= 8'h0; else if(curr_st == WAIT) begin if(sec_cnt == 8'd59 && nsec_cnt == TIME_1S - 1'b1) sec_cnt <= 8'h0; else if(nsec_cnt == TIME_1S - 1'b1) sec_cnt <= sec_cnt + 1'b1; else sec_cnt <= sec_cnt; end else sec_cnt <= 8'h0; // always @(posedge clk) if(rst) min_cnt <= 8'h0; else if(curr_st == WAIT) begin if(sec_cnt == 8'd59 && nsec_cnt == TIME_1S - 1'b1) min_cnt <= min_cnt + 1'b1; else min_cnt <= min_cnt; end else min_cnt <= 8'h0; //0x00--0x7f (length 2**8) assign cs_reg = (cs == 1'b0) & (addr >= 8'h00) & (addr <= 8'h7f); //1 active assign adr_reg = addr - 8'h00; //0x80--0xff (length 2**9) assign cs_ram = (cs == 1'b0) & (addr >= 8'h80) & (addr <= 8'hff); //1 active assign adr_ram = addr - 8'h80; //data_out assign data_out = cs_reg ? dout_reg : cs_ram ? dout_ram : data_out_d1; //data_out_d1 always @(posedge clk) data_out_d1 <= data_out; //localbus 读 always @(posedge clk) if(cs_reg && oe) begin case (adr_reg) 10'h000 : dout_reg <= 32'h2025_0116; 10'h001 : dout_reg <= test_reg; 10'h002 : dout_reg <= bit_err_cnt; 10'h003 : dout_reg <= {28'h0, curr_st}; 10'h004 : dout_reg <= {31'h0, busy}; 10'h005 : dout_reg <= {31'h0, flash_busy}; default : dout_reg <= 32'h5a5a5a5a; endcase end else dout_reg <= dout_reg; //DEBUG always @(posedge clk) if(rst) state2_cnt <= 36'h0; else if(curr_st == MONI) state2_cnt <= state2_cnt + 1'b1; else state2_cnt <= state2_cnt; // always @(posedge clk) if(rst) state3_cnt <= 36'h0; else if(curr_st == ERAS_0 || curr_st == ERAS_1) state3_cnt <= state3_cnt + 1'b1; else state3_cnt <= state3_cnt; // always @(posedge clk) if(rst) state4_cnt <= 36'h0; else if(curr_st == READ_0 || curr_st == READ_1) state4_cnt <= state4_cnt + 1'b1; else state4_cnt <= state4_cnt; // always @(posedge clk) if(rst) state5_cnt <= 36'h0; else if(curr_st == WRIT_0 || curr_st == WRIT_1) state5_cnt <= state5_cnt + 1'b1; else state5_cnt <= state5_cnt; endmodule解读一下此代码
最新发布
09-06
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序猿Debug

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

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

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

打赏作者

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

抵扣说明:

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

余额充值