关于verilog的仿真测试程序编写

关于verilog的仿真测试程序编写,第1张

module mul3_testbench ; //定义一个没有输入输出端口的测试平台

reg a2,a1,a0,b2,b1,b0; //被测模块的input端口,改为对应的 reg寄存器做输入信号

wire p5,p4,p3,p2,p1,p0; //被测模块的output端口,改为对应的wire型

initial begin // 初始化所有 输入信号的寄存器值

a2= 0;

a1=0;

a0 =0;

b2 =0;

b1= 0;

b0 =0;

#50 //一般延迟较长时间后,应该使复位信号不复位系统正常工作,但你没有复位信号

end

// 初始化模块结束后一般时序电路仿真是产生时钟信号,

//这是纯组合逻辑没有时钟信号就省略了

//然后就可以根据你所需要验证的功能在此位置编写initial块或always块给reg 型

//的输入信号赋值的相关逻辑,观察wire型输入信号的值

//---------------------------调用被测对象,格式如一般元件调用-------------------

mul3 DUT( a2(a2),

a1(a2),

a0(a0),

b2(b2),

b1(b2),

b0(b0),

p5(p5),

p4(p4),

p3(p3),

p2(p2),

p1(p1),

p0(p0)

);

endmodule

// 最后的提示,你的程序里定义了整数型变量,其实是不好的用法,甚至不能被正确综合,

//可以用等值的reg 型变量来替代,即使你定义成整数型,实际上也是被综合成reg型的,

//另外,一般可综合代码中最好不要用for语句,个人认为你的代码会完全功能不正常的

#include"reg52h"

#include"intrinsh"

#define uchar unsigned char //无符号8位

#define uint unsigned int //无符号16位

#define ulong unsigned long //无符号32位

sbit K1=P1^0; //按下K1后,开始测距

sbit LEDRed=P1^1; //测距指示灯,亮表示正在测距,灭表示测距完成

//sbit BEEP=P1^2; //报警测量超出范围

sbit Trig=P2^5; //HC-SR04触发信号输入

sbit Echo=P2^6; //HC-SR04回响信号输出

float xdata DistanceValue=00; //测量的距离值

float xdata SPEEDSOUND; //声速

float xdata XTALTIME; //单片机计数周期

uchar xdata stringBuf[6]; //数值转字符串缓冲

//LCD1602提示信息

uchar code Prompts[][16]=

{

{"Measure Distance"}, //测量距离

{"- Out of Range -"}, //超出测量范围

{"MAX range 400cm "}, //测距最大值400cm

{"MIN range 2cm "}, //测距最小值2cm

{" "}, //清屏

{" Press K1 Start "} //按键开始测量

};

uchar xdata DistanceText[]="Range: "; //测量结果字符串

uchar xdata TemperatureText[]="Temperature: ";//测量温度

extern void LCD_Initialize(); //LCD初始化

extern void LCD_Display_String(uchar , uchar); //字符串显示

extern void ReadTemperatureFromDS18B20(); //从DS18B20读取温度值

extern int xdata CurTempInteger;

//毫秒延时函数

void DelayMS(uint ms);

//20微秒延时函数

void Delay20us();

//HCSR04初始化

void HCSR04_Initialize();

//测量距离

float MeasuringDistance();

//测距的数值排序求平均

float DistanceStatistics();

//输出距离值到LCD1602上

void DisplayDistanceValue(float dat);

//将无符号的整数转成字符串,返回字符串长度,不包括'\0'结束符

uchar UnsigedIntToString(uint value);

//蜂鸣器

//void Beep(uchar time);

//显示温度值

void DisplayTemperatureValue();

void main()

{

LCD_Initialize();//LCD1602初始化

LCD_Display_String(Prompts[0],0x00);

LCD_Display_String(Prompts[5],0x40);

ReadTemperatureFromDS18B20(); //测温度

HCSR04_Initialize(); //HC-SR04初始化

while(1)

{

if(K1==0)

{

DelayMS(5);

if(K1==0)

{

//Beep(1);

while(K1==0);

LEDRed=0;

ReadTemperatureFromDS18B20();//测温度

DisplayTemperatureValue();

if(CurTempInteger<14)

CurTempInteger=14;

else if(CurTempInteger>26)

CurTempInteger=26;

SPEEDSOUND=3341+CurTempInteger061;//计算声速

DistanceValue=DistanceStatistics(); //测距并返回距离值

DisplayDistanceValue(DistanceValue); //显示距离值

LEDRed=1;

}

}

}

}

//测距的数值排序求平均

float DistanceStatistics()

{

uchar i,j;

float disData[7],t;

//连续测距

for(i=0;i<7;i++)

{

disData=MeasuringDistance();

DelayMS(80);

}

//排序

for(j=0;j<=6;j++)

{

for(i=0;i<7-j;i++)

{

if(disData>disData[i+1])

{

t=disData;

disData=disData[i+1];

disData[i+1]=t;

}

}

}

return (disData[2]+disData[3]+disData[4])/3;

}

//测量距离

float MeasuringDistance()

{

//最大定时时间约65ms

TH0=0;

TL0=0;

//生成20us的脉冲宽度的触发信号

Trig=1;

Delay20us();

Trig=0;

//等待回响信号变高电平

while(!Echo);

TR0=1; //启动定时器0

//等待回响信号变低电平

while(Echo);

TR0=0; //关闭定时器0

//返回距离值(mm)

return (SPEEDSOUNDXTALTIME((float)TH0256+(float)TL0))/2000;

}

//HCSR04初始化

void HCSR04_Initialize()

{

//计算单片机计数周期 晶振=11953M 单位us

XTALTIME=12/11953;

//温度25度时声速的值

SPEEDSOUND=3341+25061;

Trig=0;

Echo=0;

TMOD=0x01;

}

//输出距离值到LCD1602上

void DisplayDistanceValue(float dat)

{

uchar i=0,j=0,len;

uint value;

value=(uint)dat;

//范围检查大于4000mm和小于20mm都为超出测量范围

if(value>4000)

{

LCD_Display_String(Prompts[1],0x00);

LCD_Display_String(Prompts[2],0x40);

//Beep(2);

}

else if(value<20)

{

LCD_Display_String(Prompts[1],0x00);

LCD_Display_String(Prompts[3],0x40);

//Beep(2);

}

else

{

//将数值转换成字符串

len=UnsigedIntToString(value);

//保留1位小数

while(stringBuf!='\0')

{

if(len-j==1)

{

DistanceText[6+j]='';

j++;

}else

{

DistanceText[6+j]=stringBuf;

i++;

j++;

}

}

DistanceText[6+j]='c';

j++;

DistanceText[6+j]='m';

i=7+j;

//剩余位置补空格

while(i<16)

{

DistanceText=' ';

i++;

}

//LCD_Display_String(Prompts[0],0x00);

LCD_Display_String(DistanceText,0x40);

}

}

//显示温度值

void DisplayTemperatureValue()

{

TemperatureText[13]=CurTempInteger/10+'0';

TemperatureText[14]=CurTempInteger+'0';

TemperatureText[15]='C';

LCD_Display_String(TemperatureText,0x00);

}

//将无符号的整数转成字符串,返回字符串长度

uchar UnsigedIntToString(uint value)

{

uchar i=0,t,length;

//从个位开始转换

do

{

stringBuf='0'+value;

value=value/10;

i++;

}while(value!=0);

length=i;

//将字符串颠倒顺序

for(i=0;i<(length/2);i++)

{

t=stringBuf;

stringBuf=stringBuf[length-i-1];

stringBuf[length-i-1]=t;

}

stringBuf[length]='\0';

return length;

}

//蜂鸣器

//延时函数 毫秒 @12000MHz

void DelayMS(uint ms)

{

uchar i, j;

while(ms--)

{

_nop_();

i = 2;

j = 239;

do

{

while (--j);

}while (--i);

}

}

//延时函数 20微秒 @12000MHz

void Delay20us()

{

uchar i;

_nop_();

i = 7;

while (--i);

}

//定时器0中断

void Timer0() interrupt 1

{

}

//DS18B20代码:

#include

#include

#define uchar unsigned char //无符号8位

#define uint unsigned int //无符号16位

//定义DS18B20端口DS18B20_DQ

sbit DS18B20_DQ = P2^7;

//当前采集的温度值整数部分

int xdata CurTempInteger;

//当前采集的温度值小数部分

int xdata CurTempDecimal;

void Delayus(uint count)

{

while (--count);

}

uchar Reset_DS18B20()

{

uchar status;

DS18B20_DQ=1;

Delayus(1);

//开始复位过程

DS18B20_DQ=0; //数据线拉低

Delayus(100); //延时480us-960us

DS18B20_DQ=1; //数据线拉高

Delayus(10); //延时15us-60us

status=DS18B20_DQ; //读取数据线上的状态

Delayus(120);

return status;

}

void WriteByteToDS18B20(uchar dat)

{

uchar i;

for(i=0;i<8;i++)

{

DS18B20_DQ=0;

DS18B20_DQ=dat&0x01; //发送1位数据

Delayus(15); //延时60us以上

DS18B20_DQ=1; //释放总线,等待总线恢复

dat>>=1; //准备下一位数据

}

}

uchar ReadByteFromDS18B20()

{

uchar i,dat=0;

for(i=0;i<8;i++)

{

DS18B20_DQ=0; //拉低总线,产生读信号

dat>>=1;

DS18B20_DQ=1; //释放总线,准备读1位数据

Delayus(2); //延时4us

if(DS18B20_DQ) dat|=0x80; //合并每位数据

Delayus(15); //延时60us

DS18B20_DQ=1; //拉高总线,准备读下1位数据

}

return dat;

}

void ReadTemperatureFromDS18B20()

{

uchar flag=0;//正负符号标志

//存储当前采集的温度值

uchar TempValue[]={0,0};

if(Reset_DS18B20())

{

CurTempInteger=255;

CurTempDecimal=0;

}

else

{

WriteByteToDS18B20(0xCC);//跳过ROM命令

WriteByteToDS18B20(0x44);//温度转换命令

Reset_DS18B20();//复位

WriteByteToDS18B20(0xCC);//跳过ROM命令

WriteByteToDS18B20(0xBE);//读取温度暂存器命令

TempValue[0]=ReadByteFromDS18B20();//先读低字节温度值

TempValue[1]=ReadByteFromDS18B20();//后读高字节温度值

Reset_DS18B20();//复位

//计算温度值

//先进行正温度与负温度判断,高5位全为1(0xF8)则为负数

if((TempValue[1]&0xF8)==0xF8)

{

//负温度计算:取反加1,低字节为0时,高字节取反加1,否则不需要。

TempValue[1]=~TempValue[1];

TempValue[0]=~TempValue[0]+1;

if(TempValue[0]==0x00) TempValue[1]++;

flag=1;//负数标志

}

//将温度值分为整数和小数两部分存储(默认为12位精度)

CurTempInteger=((TempValue[1]&0x07)<<4)|((TempValue[0]&0xF0)>>4); if(flag) CurTempInteger=-CurTempInteger;

CurTempDecimal=(TempValue[0]&0x0F)625;

}

}

//LCD1602程序代码:

#include

#include

#define uchar unsigned char

#define uint unsigned int

#define Delay4us(){_nop_();_nop_();_nop_();_nop_();}

sbit LCD_RS=P2^0;

sbit LCD_RW=P2^1;

sbit LCD_EN=P2^2;

void LCDDelay(uint ms)

{

uchar i, j;

while(ms--)

{

_nop_();

i = 2;

j = 239;

do

{

while (--j);

}while (--i);

}

}

bit LCD_Busy_Check()

{

bit result;

LCD_RS=0; LCD_RW=1; LCD_EN=1;

Delay4us();

result=(bit)(P0&0x80);

LCD_EN=0;

return result;

}

void Write_LCD_Command(uchar cmd)

{

while(LCD_Busy_Check());

LCD_RS=0; LCD_RW=0; LCD_EN=0; _nop_(); _nop_();

P0=cmd; Delay4us();

LCD_EN=1; Delay4us(); LCD_EN=0;

}

void Write_LCD_Data(uchar dat)

{

while(LCD_Busy_Check());

LCD_RS=1;LCD_RW=0;LCD_EN=0;

P0=dat;Delay4us();

LCD_EN=1;Delay4us();LCD_EN=0;

}

void LCD_Set_POS(uchar pos)

{

Write_LCD_Command(pos|0x80);

}

void LCD_Initialize()

{

Write_LCD_Command(0x01); LCDDelay(5);

Write_LCD_Command(0x38); LCDDelay(5);

Write_LCD_Command(0x0C); LCDDelay(5);

Write_LCD_Command(0x06); LCDDelay(5);

}

void LCD_Display_String(uchar str, uchar LineNo)

{

uchar k;

LCD_Set_POS(LineNo);

for(k=0;k<16;k++)

{

Write_LCD_Data(str[k]);

}

}

void LCD_Display_OneChar(uchar Dat, uchar X, uchar Y)

{

Y &= 0x01; //限制Y不能大于1(2行,0-1)

X &= 0x0F; //限制X不能大于15(16个字符,0-15)

if(Y) {X |= 0x40;} //当要在第二行显示时地址码+0x40;

X |= 0x80; //算出指令码

Write_LCD_Command(X);

Write_LCD_Data(Dat);

}

1、如果仿真一个传递函数的阶跃、脉冲等响应,可以直接使用matlab函数。

2、如果是一个复杂的系统,需要使用matlab中的Simulink工具箱。

3、仿真方法,仿真(s+1)/(2s^2+2s+1)的阶跃响应

num=[1

1];

den=[2

2

1];

f=tf(num,den)

Transfer

function:

 

 

s

+

1

2

s^2

+

2

s

+

1

>>

step(f)

这样就可以得到它的响应曲线。

一、代码写的也很清楚,问题也很明白。先说一下你这个程序想完成的功能吧:

P0口的数码管属于后台程序,他一直循环计数 0~8 。他能被任何一个中段所打断,并且该中断退出后,P0口的数码管能接着被打断之前的数字继续计数,而不是从 0 重新开始,这一点你的程序没有做到。

P2口的数码管由 INT0 中断控制,中断一次,只完成一次 0~8 的计数。他可以打断 P0 口,而不能打断 P1 口,因为 INT0 的优先级低。如果 INT0 被 INT1 打断了,INT1 退出后,INT0 应接着原来的数继续计数,而不是 INT1 退出之后,INT0 不会动了,这一点你的程序也没做到。

P1口的数码管由 INT1 中断控制,中断一次,也完成一次 0~8 的计数。他可以打断 P0口,也可以打断 P2口(INT0),他退出之后,被中断的程序应该恢复之前的工作。

这些问题都是由于在中断服务程序中,没有对现场进行保护引起的。问题找到了,解决方法很简单,就是在每个中断服务程序中加上现场保护就行了,即在每个中断服务程序的开始各加一条语句“PUSH    ACC”即可,现场恢复你的程序里边有。

二、下面是修改过的程序,并按照题目的要求添加了注释

ORG 0000H

SJMP STAR

ORG 0003H

SJMP INT0S

ORG 0013H

SJMP INT1S

ORG 0030H

STAR:

MOV IE,#85H //中断允许

MOV TCON,#05H  //低电平触发中断

MOV P3,#0FFH  //P3口拉高,为两个按钮服务

SETB PX1  //提高 INT1 的优先级

ST0:

MOV A,#1 //立即数 1 送 A,准备读 0 的段码

ST1:

PUSH ACC //入栈保存

ACALL SEG7 //去读段码

MOV P0,A //送 P0 口显示

ACALL DELAY  //延时一小会

POP ACC //把保存的 立即数d回 A

INC A //A 自身加 1,为读取下一个段码做准备

CJNE A,#10,ST1 // A=10:往下走,否则转到ST1

SJMP ST0 //开始下一轮 0~8 的显示

INT0S:

PUSH ACC //该句是添加的,用于现场保护

MOV A,#0

LOOP:

INC A

PUSH ACC

ACALL SEG7

MOV P2,A

POP ACC

ACALL DELAY

CJNE A,#9,LOOP

POP ACC //原来就有,用于现场恢复

MOV P2,#0FFH

RETI

INT1S:

PUSH ACC //这句也是现场保护

MOV A,#0

LOOP1:

INC A

PUSH ACC

ACALL SEG7

MOV P1,A

POP ACC

ACALL DELAY

CJNE A,#9,LOOP1

MOV P1,#0FFH

POP ACC //现场回复

RETI

DELAY:

MOV R7,#250

D1:

MOV R6,#250

D2:

NOP

NOP

NOP

NOP

NOP

NOP

NOP

NOP

DJNZ R6,D2

DJNZ R7,D1

RET

SEG7:

MOVC A,@A+PC

RET  //这条语句一字节,所以执行上句之前 A 要加 1

DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H

END

如果感到满意,你就跺跺脚,踩------纳!!!!!

以上就是关于关于verilog的仿真测试程序编写全部的内容,包括:关于verilog的仿真测试程序编写、1602显示超声波测距的C语言程序和Proteus仿真图、如何用matlab进行系统仿真等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zz/9848114.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-02
下一篇2023-05-02

发表评论

登录后才能评论

评论列表(0条)

    保存