简单卷积器的设计docxWord格式文档下载.docx
《简单卷积器的设计docxWord格式文档下载.docx》由会员分享,可在线阅读,更多相关《简单卷积器的设计docxWord格式文档下载.docx(25页珍藏版)》请在冰豆网上搜索。
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<
eounter<
=12'
b0;
high<
=0;
wr<
line<
=24'
address<
=11'
end
else
ease(state)
IDLE:
if(start==1)
eounter<
//eounter是一个计数器,记录已
〃用的RAM空间
=START;
//START状态控制A/D开始转换
START:
if(EOC)
=NCONVST;
//NCONVST状态是A/D转换保持阶段
NCONVST:
begin
=READ;
//READ状态读取A/D转换结果,计算卷积结果
READ:
begin
if(EOC)
={line[15:
0],indata};
=CALCU;
CALCU:
result<
=line[7:
0]*h1+line[15:
8]*h2+line[23:
16]*h3;
state<
=WRREADY;
〃将卷积结果写入RAM时,先写入低字节,再写入高字节//WRREADY状态是写RAM准备状态,建立地址和数据信
WRREADY:
begin
=counter;
high)outdata<
=result[7:
0];
elseoutdata<
=result[15:
8];
=WR;
//WR状态产生片选和写脉冲
WR:
high)enout1<
elseenout2<
=WREND;
WRREADY
//WREND状态结束一次写操作,若还未写入高字节则转到
//态开始高字节写入
WREND:
high)
elsestate<
=WAITFOR;
//WAITFOR状态控制采样频率并判断RAM是否已被写满
WAITFOR:
if(j==FMAX-1)
counter<
=counter+1;
counter[11])state<
$display($time,"
Theramisused
up."
);
$stop;
default:
endcase
//assignrd=1;
//RAM的读信号始终保持为高
//j记录时钟,与FMAX共同控制采样频率
//由于直接用CLK的上升沿对nbusy判断以
//决定某些操作是否运行时,会因为两个信号
//的跳变沿相隔太近而令状态机不能正常工作。
因此
//利用CLK的下降沿建立EOC信号与nbusy同步,相位〃相差180度,然后用CLK的上升沿判断操作是否进行。
always@(negedgeCLK)
EOC<
=nbusy;
reset||state==START)
j<
=j+1;
endmodule
//testconl.v
'
timescale100ps/100psmoduletestconl;
wirewr,
enin,
enoutl,
enout2;
wire[10:
regrd,
CLK,
reset,start;
wireneonvst;
wire[7:
integeri;
parameterHALF_PERIOD=1000;
//产生10KHZ的时钟
initial
rd=1;
i=0;
CLK=1;
forever#HALF_PERIODCLK=~CLK;
//产生置位信号
reset=1;
#(HALF_PERIOD*2+50)reset=0;
#(HALF_PERIOD*3)reset=1;
//产生开始卷积控制信号
start=0;
#(HALF_PERIOD*7+20)start=1;
#(HALF_PERIOD*2)start=0;
#(HALF_PERIOD*1OOO)start=1;
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));
//卷积器的改进
//con3ad.v
timescaleins/100ps
modulecon3ad(indata,outdata,address,CLK,reset,start,nconvsti,neonvst2,neonvst3,nbusyl,nbusy2,nbusy3,wr,enout1,enout2);
inputindata,
reset,
start,
nbusyl,
nbusy2,
nbusy3;
outputoutdata,
address,
nconvsti,//采用三根控制线控制三片A/D转换器
neonvst2,
neonvst3,
wr,
enoutl,
wireCLK,
regneonvsti,
reg[6:
reg[5:
0]i;
reg[1:
reg[11:
0]counter;
reg[15:
reghigh;
regk;
regEOC1,EOC2,EOC3;
parameterIDLE=7'
b0000001,READ_PRE=7'
b0000010,
READ=7'
b0000100,CALCU=7'
b0001000,
WR=7'
b0100000,
WRREADY=7'
b0010000,
WREND=7'
b1000000;
beginstate<
counter<
outdata<
=8'
bz;
=16'
end//endof"
if"
begincase(state)
if(start)
=READ_PRE;
READ_PRE:
if(EOC1||EOC2||EOC3)//由于频率相对改进前的卷积//器大大提高,所以加入〃READ_PRE状态对取数操作〃予以缓冲。
if(j==1)
if(EOC1)
endelsestate<
elseif(j==2&
&
counter!
=0)
beginif(EOC2)beginline<
elseif(j==3&
if(EOC3)
beginresult<
16]*h;
if(k==1)state<
enout2<
if(k==1)
if(counter[11]&
counter[0])state<
endcase//endofthecase
else"
always"
//计数器i用来记录时间
reset)i<
if(i==44)i<
elsei<
=i+1;
//j是控制信号,协调卷积器轮流从三片A/D上读取数据。
if(i==4)j<
=2;
elseif(i==10)j<
elseif(i==19)j<
=3;
elseif(i==25)j<
elseif(i==34)j<
elseif(i==40)j<
//k是计数器,用以控制写操作信号
if(state==WRREADY||state==WR||state==WREND)
if(k==1)k<
elsek<
NCONVST3
//根据计数器i控制三片A/D转换信号NC0NVST1,NCONVST2,always@(posedgeCLK)
reset)neonvst1<
elseif(i==0)neonvst1<
elseif(i==3)neonvst1<
reset)neonvst2<
elseif(i==15)neonvst2<
elseif(i==18)neonvst2<
endalways@(posedgeCLK)
reset)neonvst3<
elseif(i==30)neonvst3<
elseif(i==33)neonvst3<
always@(negedgeCLK)
EOC1<
=nbusyl;
EOC2<
=nbusy2;
EOC3<
=nbusy3;
〃测试程序如下:
timescale1ns/100ps
moduletesteon3ad;
regelk,
start;
rd;
wirenbusyl,
wireneonvstl,
neonvst3;
parameterHALF_PERIOD=15;
〃时钟周期为30nsinitialbegin
clk=1;
forever#HALF_PERIODclk=~clk;
#110reset=0;
#140reset=1;
#420start=1;
#120start=0;
#107600start=1;
#150start=0;
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));
adcad_1(.nconvst(nconvst1),.nbusy(nbusy1),.data(indata));
adcad_2(.nconvst(nconvst2),.nbusy(nbusy2),.data(indata));
adcad_3(.nconvst(nconvst3),.nbusy(nbusy3),.data(indata));
//A/D转换器的VerilogHDL行为模型如下:
//adc.v
moduleadc(neonvst,nbusy,data);
inputneonvst;
//A/D启动脉冲ST,即上图中
outputnbusy;
//A/D工作标志,即上图中
outputdata;
//数据总线,从AD.DATA文件中读取数据后经端口输出
0]databuf,i;
//内部寄存器
regnbusy;
0]data;
0]data_mem[0:
255];
reglink_bus;
integertconv,
t5,
t8,
t9,
t12;
integerwideth1,
wideth2,
wideth;
//时间参数定义(依据AD7886手册):
always@(negedgeneonvst)
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
$readmemh("
adc.data"
data_mem);
〃从数据文件adc.data中读取数据
i=0;
nbusy=1;
link_bus=0;
assigndata=link_bus?
databuf:
8'
bzz;
//三态总线
/*
在信号nconvst的负跳降沿到来后,隔t5秒nbusy信号置为低,tconv是AD将模拟信号转
换为数字信号的时间,在信号nconvst的正跳降沿到来后经过tconv时间后,输出nbusy信
号变为高。
*/
fork
#t5nbusy=0;
@(posedgeneonvst)begin
#teonvnbusy=1;
join
neonvst信号的下降沿触发,经过t9延时后,把数据总线输出关闭置为高阻态,如图示。
nconvst信号的上升沿到来后,经过(tconv-⑹时间,输出一个字节(8位数据)到databuf,该数据来自于data_mem。
而data_mem中的数据是初始化时从数据文件AD.DATA中读取的。
此时应启动总线的三态输出。
*/always@(negedgeneonvst)
@(posedgeneonvst)
#(teonv-t8)databuf=data_mem[i];
if(wideth<
10000&
wideth>
500)
if(i==255)i=0;
elsei=i+1;
elsei=i;
〃在模数转换期间关闭三态输出,转换结束时启动三态输出
#t9link_bus=1'
//关闭三态输出,不允许总线输出
@(posedgeneonv