简单卷积器的设计docx.docx

上传人:b****6 文档编号:5373152 上传时间:2022-12-15 格式:DOCX 页数:25 大小:45.82KB
下载 相关 举报
简单卷积器的设计docx.docx_第1页
第1页 / 共25页
简单卷积器的设计docx.docx_第2页
第2页 / 共25页
简单卷积器的设计docx.docx_第3页
第3页 / 共25页
简单卷积器的设计docx.docx_第4页
第4页 / 共25页
简单卷积器的设计docx.docx_第5页
第5页 / 共25页
点击查看更多>>
下载资源
资源描述

简单卷积器的设计docx.docx

《简单卷积器的设计docx.docx》由会员分享,可在线阅读,更多相关《简单卷积器的设计docx.docx(25页珍藏版)》请在冰豆网上搜索。

简单卷积器的设计docx.docx

简单卷积器的设计docx

练习十

简单卷积器的设计

//'timescale100ps/100ps

modulecon1(address,indata,outdata,wr,neonvst,nbusy,

enout1,enout2,CLK,reset,start);

inputCLK,//采用10MHZ的时钟

reset,//复位信号

start,〃因为RAM的空间是有限的,当RAM存满后采样和卷积都会停止。

〃此时给一个start的高电平脉冲将会开始下一次的卷积。

nbusy;〃从A/D转换器来的信号表示转换器的忙或闲

outputwr,//RAM写控制信号

enout1,enout2,〃enout1是存储卷积低字节结果RAM的片选信号

//enout2是存储卷积高字节结果RAM的片选信号

nconvst,//给A/D转换器的控制信号,命令转换器开始工作,低电平有效address;//地址输出

input[7:

0]indata;//从A/D转换器来的数据总线

output[7:

0]outdata;//写到RAM去的数据总线

wirenbusy;

regwr;

regneonvst,

enoutl,enout2;

reg[7:

0]outdata;

reg[10:

0]address;reg[8:

0]state;reg[15:

0]result;

reg[23:

0]line;reg[11:

0]counter;reghigh;

reg[4:

0]j;regEOC;

parameterh1=1,h2=2,h3=3;〃假设的系统系数

parameterIDLE=9'b000000001,START=9'b000000010,NCONVST=9'b000000100,

READ=9'b000001000,CALCU=9'b000010000,WRREADY=9'b000100000,

WR=9'b001000000,WREND=9'b010000000,WAITFOR=9'b100000000;

parameterFMAX=20;〃因为A/D转换的时间是随机的,为保证按一定的频率采样,A/D

//转换控制信号应以一定频率给出。

这里采样频率通过FMAX控制

//为500KHZ。

always@(posedgeCLK)

if(!

reset)

begin

state<=IDLE;

neonvst<=1'b1;

enout1<=1;

enout2<=1;

eounter<=12'b0;

high<=0;

wr<=1;

line<=24'b0;

address<=11'b0;

end

else

ease(state)

IDLE:

if(start==1)

begin

eounter<=0;//eounter是一个计数器,记录已

〃用的RAM空间

line<=24'b0;

state<=START;

end

else

state<=IDLE;

//START状态控制A/D开始转换

START:

if(EOC)

begin

neonvst<=0;

high<=0;

state<=NCONVST;

end

else

state<=START;

//NCONVST状态是A/D转换保持阶段

NCONVST:

begin

neonvst<=1;

state<=READ;

end

//READ状态读取A/D转换结果,计算卷积结果

READ:

begin

if(EOC)

begin

line<={line[15:

0],indata};

state<=CALCU;

end

else

state<=READ;

end

CALCU:

begin

result<=line[7:

0]*h1+line[15:

8]*h2+line[23:

16]*h3;state<=WRREADY;

end

〃将卷积结果写入RAM时,先写入低字节,再写入高字节//WRREADY状态是写RAM准备状态,建立地址和数据信

WRREADY:

begin

address<=counter;

if(!

high)outdata<=result[7:

0];elseoutdata<=result[15:

8];

state<=WR;

end

//WR状态产生片选和写脉冲

WR:

begin

if(!

high)enout1<=0;

elseenout2<=0;

wr<=0;state<=WREND;

end

WRREADY

//WREND状态结束一次写操作,若还未写入高字节则转到

//态开始高字节写入

WREND:

begin

wr<=1;

enout1<=1;

enout2<=1;

if(!

high)

begin

high<=1;

state<=WRREADY;

end

elsestate<=WAITFOR;

end

//WAITFOR状态控制采样频率并判断RAM是否已被写满

WAITFOR:

begin

if(j==FMAX-1)

begin

counter<=counter+1;

if(!

counter[11])state<=START;

else

begin

state<=IDLE;

$display($time,"Theramisused

up.");

$stop;

end

end

elsestate<=WAITFOR;

end

default:

state<=IDLE;

endcase

//assignrd=1;//RAM的读信号始终保持为高

//j记录时钟,与FMAX共同控制采样频率

//由于直接用CLK的上升沿对nbusy判断以

//决定某些操作是否运行时,会因为两个信号

//的跳变沿相隔太近而令状态机不能正常工作。

因此

//利用CLK的下降沿建立EOC信号与nbusy同步,相位〃相差180度,然后用CLK的上升沿判断操作是否进行。

always@(negedgeCLK)

begin

EOC<=nbusy;

if(!

reset||state==START)

j<=1;

else

j<=j+1;

end

endmodule

//testconl.v

'timescale100ps/100psmoduletestconl;

wirewr,

enin,

enoutl,

enout2;

wire[10:

0]address;

regrd,

CLK,

reset,start;

wirenbusy;

wireneonvst;

wire[7:

0]indata;

wire[7:

0]outdata;

integeri;

parameterHALF_PERIOD=1000;

//产生10KHZ的时钟

initial

begin

rd=1;

i=0;

CLK=1;forever#HALF_PERIODCLK=~CLK;

end

//产生置位信号

initial

begin

reset=1;

#(HALF_PERIOD*2+50)reset=0;#(HALF_PERIOD*3)reset=1;

end

//产生开始卷积控制信号

initial

begin

start=0;

#(HALF_PERIOD*7+20)start=1;#(HALF_PERIOD*2)start=0;

#(HALF_PERIOD*1OOO)start=1;#(HALF_PERIOD*2)start=0;end

assignenin=1;

conicon(.address(address),.indata(indata),.outdata(outdata),.wr(wr),.nconvst(nconvst),.nbusy(nbusy),.enout1(enoutl),

.enout2(enout2),.CLK(CLK),.reset(reset),.start(start));

sramramlow(.Address(address),.Data(outdata),.SRW(wr),.SRG(rd),.SRE(enout1));adcadc(.nconvst(nconvst),.nbusy(nbusy),.data(indata));

endmodule

//卷积器的改进

//con3ad.v

'timescaleins/100ps

modulecon3ad(indata,outdata,address,CLK,reset,start,nconvsti,neonvst2,neonvst3,nbusyl,nbusy2,nbusy3,wr,enout1,enout2);

inputindata,

CLK,

reset,

start,

nbusyl,

nbusy2,

nbusy3;

outputoutdata,

address,

nconvsti,//采用三根控制线控制三片A/D转换器

neonvst2,

neonvst3,

wr,

enoutl,

enout2;

wire[7:

0]indata;

wireCLK,

reset,

start,

nbusyl,

nbusy2,

nbusy3;

reg[7:

0]outdata;

reg[10:

0]address;

regneonvsti,

neonvst2,

neonvst3,

wr,

enoutl,

enout2;

reg[6:

0]state;

reg[5:

0]i;

reg[1:

0]j;

reg[11:

0]counter;

reg[23:

0]line;

reg[15:

0]result;

reghigh;

regk;

regEOC1,EOC2,EOC3;

parameterh1=1,h2=2,h3=3;

parameterIDLE=7'b0000001,READ_PRE=7'b0000010,

READ=7'b0000100,CALCU=7'b0001000,

WR=7'b0100000,

WRREADY=7'b0010000,

WREND=7'b1000000;

always@(posedgeCLK)

begin

if(!

reset)

beginstate<=IDLE;

counter<=12'b0;

wr<=1;

enout1<=1;

enout2<=1;

outdata<=8'bz;

address<=11'bz;

line<=24'b0;

result<=16'b0;

high<=0;

end//endof"if"

else

begincase(state)

IDLE:

if(start)

begin

counter<=0;state<=READ_PRE;end

elsestate<=IDLE;

READ_PRE:

if(EOC1||EOC2||EOC3)//由于频率相对改进前的卷积//器大大提高,所以加入〃READ_PRE状态对取数操作〃予以缓冲。

state<=READ;

else

state<=READ_PRE;

READ:

begin

high<=0;

enout2<=1;

wr<=1;

if(j==1)

begin

if(EOC1)

begin

line<={line[15:

0],indata};state<=CALCU;endelsestate<=READ_PRE;

end

elseif(j==2&&counter!

=0)

beginif(EOC2)beginline<={line[15:

0],indata};state<=CALCU;

end

elsestate<=READ_PRE;

end

elseif(j==3&&counter!

=0)

begin

if(EOC3)

begin

line<={line[15:

0],indata};

state<=CALCU;

end

elsestate<=READ_PRE;

end

elsestate<=READ;

end

CALCU:

beginresult<=line[7:

0]*h1+line[15:

8]*h2+line[23:

16]*h;state<=WRREADY;

end

WRREADY:

begin

wr<=1;

address<=counter;

if(k==1)state<=WR;

elsestate<=WRREADY;

end

WR:

begin

if(!

high)

enout1<=0;

else

enout2<=0;

wr<=0;

if(!

high)

outdata<=result[7:

0];

else

outdata<=result[15:

8];

if(k==1)

state<=WREND;

else

state<=WR;

end

WREND:

begin

wr<=1;

enout1<=1;

enout2<=1;

if(k==1)

if(!

high)

begin

high<=1;state<=WRREADY;end

else

begin

counter<=counter+1;

if(counter[11]&&counter[0])state<=IDLE;

elsestate<=READ_PRE;end

elsestate<=WREND;

end

default:

state<=IDLE;

endcase//endofthecase

end//endof"else"

end//endof"always"

//计数器i用来记录时间

always@(posedgeCLK)

begin

if(!

reset)i<=0;

else

begin

if(i==44)i<=0;

elsei<=i+1;

end

end

//j是控制信号,协调卷积器轮流从三片A/D上读取数据。

always@(posedgeCLK)

begin

if(i==4)j<=2;

elseif(i==10)j<=0;

elseif(i==19)j<=3;

elseif(i==25)j<=0;

elseif(i==34)j<=1;

elseif(i==40)j<=0;

end

//k是计数器,用以控制写操作信号

always@(posedgeCLK)

begin

if(state==WRREADY||state==WR||state==WREND)

if(k==1)k<=0;

elsek<=1;

elsek<=0;

NCONVST3

end

//根据计数器i控制三片A/D转换信号NC0NVST1,NCONVST2,always@(posedgeCLK)

begin

if(!

reset)neonvst1<=1;

elseif(i==0)neonvst1<=0;

elseif(i==3)neonvst1<=1;

end

always@(posedgeCLK)

begin

if(!

reset)neonvst2<=1;

elseif(i==15)neonvst2<=0;

elseif(i==18)neonvst2<=1;

endalways@(posedgeCLK)

begin

if(!

reset)neonvst3<=1;

elseif(i==30)neonvst3<=0;

elseif(i==33)neonvst3<=1;

end

always@(negedgeCLK)

begin

EOC1<=nbusyl;

EOC2<=nbusy2;

EOC3<=nbusy3;

end

endmodule

〃测试程序如下:

'timescale1ns/100ps

moduletesteon3ad;

wirewr,

enin,

enoutl,

enout2;

wire[10:

0]address;

regelk,

reset,

start;

rd;

wirenbusyl,

nbusy2,

nbusy3;

wireneonvstl,

neonvst2,

neonvst3;

wire[7:

0]indata;

wire[7:

0]outdata;

parameterHALF_PERIOD=15;〃时钟周期为30nsinitialbegin

clk=1;

forever#HALF_PERIODclk=~clk;

end

initial

begin

reset=1;

#110reset=0;

#140reset=1;

end

initial

begin

start=0;

rd=1;

#420start=1;

#120start=0;

#107600start=1;

#150start=0;

end

assignenin=1;

con3adcon3ad(.indata(indata),.outdata(outdata),.address(address),

.CLK(clk),.reset(reset),.start(start),

.neonvst1(neonvst1),.neonvst2(neonvst2),.neonvst3(neonvst3),

.nbusy1(nbusy1),.nbusy2(nbusy2),.nbusy3(nbusy3),

.wr(wr),.enout1(enout1),.enout2(enout2));

sramramlow(.Address(address),.Data(outdata),.SRW(wr),.SRG(rd),.SRE(enout1));

adcad_1(.nconvst(nconvst1),.nbusy(nbusy1),.data(indata));

adcad_2(.nconvst(nconvst2),.nbusy(nbusy2),.data(indata));

adcad_3(.nconvst(nconvst3),.nbusy(nbusy3),.data(indata));

endmodule

//A/D转换器的VerilogHDL行为模型如下:

//adc.v

'timescale100ps/100ps

moduleadc(neonvst,nbusy,data);

inputneonvst;//A/D启动脉冲ST,即上图中

outputnbusy;//A/D工作标志,即上图中

outputdata;//数据总线,从AD.DATA文件中读取数据后经端口输出

reg[7:

0]databuf,i;//内部寄存器

regnbusy;

wire[7:

0]data;

reg[7:

0]data_mem[0:

255];

reglink_bus;

integertconv,

t5,

t8,

t9,

t12;

integerwideth1,

wideth2,

wideth;

//时间参数定义(依据AD7886手册):

always@(negedgeneonvst)

begin

tconv=9500+{$random}%500;//(type950ns,max1000ns)ConversionTimet5={$random}%1000;//(max100ns)CONVSTtoBUSYPropagationDlay//CL=10pf

t8=200;//(min20ns)CL=20pfDataSetupTimePriortoBUSY

//(min10ns)CL=100pf

t9=100+{$random}%900;

//(min10ns,max100ns)BusRelinquishTimeAfterCONVST

t12=2500;//(type)BUSYHightoCONVSTLow,SHAAcquisitionTime

endinitial

begin

$readmemh("adc.data",data_mem);〃从数据文件adc.data中读取数据

i=0;

nbusy=1;

link_bus=0;

end

assigndata=link_bus?

databuf:

8'bzz;//三态总线

/*

在信号nconvst的负跳降沿到来后,隔t5秒nbusy信号置为低,tconv是AD将模拟信号转

换为数字信号的时间,在信号nconvst的正跳降沿到来后经过tconv时间后,输出nbusy信

号变为高。

*/

always@(negedgeneonvst)

fork

#t5nbusy=0;

@(posedgeneonvst)begin

#teonvnbusy=1;

end

join

/*

neonvst信号的下降沿触发,经过t9延时后,把数据总线输出关闭置为高阻态,如图示。

nconvst信号的上升沿到来后,经过(tconv-⑹时间,输出一个字节(8位数据)到databuf,该数据来自于data_mem。

而data_mem中的数据是初始化时从数据文件AD.DATA中读取的。

此时应启动总线的三态输出。

*/always@(negedgeneonvst)

begin

@(posedgeneonvst)

begin

#(teonv-t8)databuf=data_mem[i];

end

if(wideth<10000&&wideth>500)

begin

if(i==255)i=0;

elsei=i+1;

end

elsei=i;

end

〃在模数转换期间关闭三态输出,转换结束时启动三态输出

always@(negedgeneonvst)

fork

#t9link_bus=1'b0;//关闭三态输出,不允许总线输出

@(posedgeneonv

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 其它

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1