temp6

DLL木马进程内幕大揭密

http://www.hackbase.com 2007-7-27 黑客基地
 
如果是位经常玩“马马”的朋友,那么一般情况下都会或多或少掌握一些木马的特性,然而,很多朋友还是不知道“DLL木马”是什么东东。那到底什么是“DLL木马”呢?它与一般的木马又有什么不同?带着这些疑问,一起开始这次揭密之旅吧!
    一、追根溯源从DLL说起
    要了解什么是“DLL木马”,就必须知道“DLL”是什么意思!说起DLL,就不能不涉及到久远的DOS时代。在DOS大行其道的时代,写程序是一件繁琐的事情,因为每个程序的代码都是需要独立的,这时为了实现一个普通的功能,甚至都要为此编写很多代码。后来随着编程技术发展与进步,程序员们开始把很多常用的代码集合(也就是通用代码)放进一个独立的文件里,并把这个文件称为“库”(Library)。在写程序的时候,把这个库文件加入编译器,就能使用这个库包含的所有功能而不必自己再去写一大堆代码,这个技术被称为“静态链接”(Static Link)。静态链接技术让劳累的程序员松了口气,一切似乎都很美好。然而静态链接技术的最大缺陷就是极度消耗和浪费资源,当一个程序只想用到一个库文件包含的某个图形效果时,系统将把这个库文件携带的所有的图形效果都加入程序,这样就使得程序非常臃肿。虽然这并不重要,可是这些臃肿的程序却把道路都阻塞了——静态链接技术让最终的程序成了大块头,因为编译器把整个库文件都加载进去了。
    技术永远是在发展的,静态链接技术由于无法避免的弊端,不能满足程序员和编程的需要,人们开始寻找一种更好的方法来解决代码重复的难题。随着Windows系统的出现, Windows系统使用一种被称为“动态链接库”(Dynamic Link Library)的新技术,它同样也是使用库文件,DLL的名字就是这样来的。动态链接本身和静态链接没什么区别,也是把通用代码写进一些独立文件里,但是在编译方面,微软把库文件做成已经编译好的程序文件,给它们开发一个交换数据的接口。程序员编写程序的时候,一旦要使用某个库文件的一个功能函数,系统就把这个库文件调入内存,连接上这个程序占有的任务进程,然后执行程序要用的功能函数,并把结果返回给程序显示出来。完成需要的功能后,这个DLL停止运行,整个调用过程结束。微软让这些库文件能被多个程序调用,实现了比较完美的共享,程序员无论要写什么程序,只要在代码里加入对相关DLL的调用声明就能使用它的全部功能。这样,写出来的程序就不能再携带一大堆无用的垃圾了。
    DLL技术的诞生,使编写程序变成一件简单的事情,Windows为我们提供了几千个函数接口,足以满足大多数程序员的需要。而且,Windows系统自身就是由几千个DLL文件组成,这些DLL相互扶持,组成了庞大的Windows系统。如果Windows依然使用静态链接技术,那将是不可想象的。
    二、什么是API

    在前面提到的“接口”又是什么呢?因为DLL不能像静态库文件那样塞进程序里,如何让程序知道实现功能的代码和文件成了问题,微软就为DLL技术做了标准规范,为每个DLL文件都明确地标注好它的功能名称,程序只要根据标准规范找到相关的名称进行调用就行了,这就是API(Application Programming Interface)应用程序接口,每个DLL带的接口都不尽相同,最大限度地减少了程序代码的重复。在Windows里,最基本的3个DLL文件是kernel32.dll、user32.dll、gdi32.dll。它们共同构成了基本的系统框架。
    三、DLL与木马
    DLL是编译好的代码,与一般程序没什么大差别,只是它不能独立运行,需要程序调用。那么,DLL与木马能扯上什么关系呢?如果你学过编程并且写过DLL,就会发现,其实DLL的代码和其他程序几乎没什么两样,仅仅是接口和启动模式不同,只要改动一下代码入口,DLL就变成一个独立的程序了。
    当然,DLL文件是没有程序逻辑的,其实DLL并不等于EXE。不过,依然可以把DLL看做缺少了main入口的程序,DLL带的各个功能函数可以看作一个程序的几个函数模块。DLL木马就是把一个实现了木马功能的代码,加上一些特殊代码写成DLL文件,导出相关的API,在别人看来,这只是一个普通的DLL,但是这个DLL却携带了完整的木马功能,这就是DLL木马的概念。也许有人会问,既然同样的代码就可以实现木马功能,那么直接做程序就可以,为什么还要多此一举写成DLL呢?这是为了隐藏,因为DLL运行时是直接挂在调用它的程序的进程里的,并不会另外产生进程,所以相对于传统EXE木马来说,它很难被查到。
    四、DLL的运行
    虽然DLL不能自己运行,可是Windows在加载DLL的时候,需要一个入口函数,就如同EXE的main一样,否则系统无法引用DLL。所以根据编写规范,Windows必须查找并执行DLL里的一个函数DllMain作为加载DLL的依据,这个函数不作为API导出,而是内部函数。DllMain函数使DLL得以保留在内存里,有的DLL里面没有DllMain函数,可是依然能使用,这是因为Windows在找不到DllMain的时候,会从其它运行库中找一个不做任何操作的缺省DllMain函数启动这个DLL使它能被载入,并不是说DLL可以放弃DllMain函数。
五、DLL木马技术分析
    到了这里,大家也许会想,既然DLL木马有那么多好处,以后写木马都采用DLL方式不就好了吗?话虽然是这么说没错,但是编写DLL木马并不是一些人想象的那么容易写的。要写一个能用的DLL木马,需要了解更多关于操作系统底层的知识。
    1.木马的主体
    千万别把木马模块写得真的像个API库一样,这不是开发WINAPI。DLL木马可以导出几个辅助函数,但是必须有一个过程负责主要执行代码,否则这个DLL只能是一堆零碎API函数,别提工作了。如果涉及一些通用代码,可以在DLL里写一些内部函数,供自己的代码使用,而不是把所有代码都开放成接口,这样它自己本身都难调用了,更不可能发挥作用。
DLL木马的标准执行入口为DllMain,所以必须在DllMain里写好DLL木马运行的代码,或者指向DLL木马的执行模块。
    2.动态嵌入技术
    Windows中,每个进程都有自己的私有内存空间,别的进程是不允许对这个私人领地进行操作的,但是,实际上我们仍然可以利用种种方法进入并操作进程的私有内存,这就是动态嵌入,它是将自己的代码嵌入正在运行的进程中的技术。动态嵌入有很多种,最常见的是钩子、API以及远程线程技术,现在的大多数DLL木马都采用远程线程技术把自己挂在一个正常系统进程中。其实动态嵌入并不少见,罗技的MouseWare驱动就挂着每一个系统进程。远程线程技术就是通过在另一个进程中创建远程线程(RemoteThread)的方法进入那个进程的内存地址空间。在DLL木马的范畴里,这个技术也叫做“注入”,当载体在那个被注入的进程里创建了远程线程并命令它加载DLL时,木马就挂上去执行了,没有新进程产生,要想让木马停止惟有让挂接这个木马DLL的进程退出运行。但是,很多时候我们只能束手无策——它和Explorer.exe挂在一起了。
    3.木马的启动

    也许您会有这样的想法,直接把这个DLL加入系统启动项目不就可以了?“NO”!前面已经介绍过,DLL不能独立运行,所以无法在启动项目里直接启动它。要想让“马儿”顺利地跑起来,就需要一个EXE使用动态嵌入技术让DLL挂上其他正常进程,让被嵌入的进程调用这个DLL的DllMain函数,激活木马运行,最后启动木马的EXE结束运行,木马启动完毕。启动DLL木马的EXE非常重要,它被称为加载(Loader)。所以,一个相对比较成熟的DLL木马会想办法保护它的Loader不会那么容易被发现和毁灭。
     Loader可以是多种多样的,Windows的rundll32.exe也被一些DLL木马用来做了Loader,这种木马一般不带动态嵌入技术,它直接挂着rundll32进程运行,用rundll32的方法像调用API一样去引用这个DLL的启动函数激发木马模块开始执行,即使你杀了rundll32,木马本体还是在的,一个最常见的例子就是3721中文实名,虽然它不是木马。
    注册表的AppInit_DLLs键也被一些木马用来启动自己,如求职信病毒。利用注册表启动,就是让系统执行DllMain来达到启动木马的目的。因为它是kernel调入的,对这个DLL的稳定性有很大要求,稍有错误就会导致系统崩溃,所以很少看到这种木马。有一些更复杂点的DLL木马通过svchost.exe启动,这种DLL木马必须写成NT-Service,入口函数是ServiceMain,一般很少见,但是这种木马的隐蔽性也不错,而且Loader有保障。
     4.寥寥无几
     到这里大家也应该对DLL木马有个了解了,是不是很想写一个?别急,不知道大家想过没有,既然DLL木马这么好,为什么到现在能找到的DLL木马寥寥无几?现在让我来泼冷水,最重要的原因只有一个:由于DLL木马挂着系统进程运行,如果它本身写得不好,例如没有防止运行错误的代码或者没有严格规范用户的输入,DLL就会很容易出错并崩溃。但是DLL崩溃会导致它挂着的程序跟着遭殃,别忘记它挂接的可是系统进程啊,结局就是……惨不忍睹。所以写一个能公布的DLL木马,在排错检查方面做的工作要比一般的EXE木马多,甚至写得多了连编写者自己都会烦躁不已!
    六、DLL木马的发现和查杀
    经常看看启动项有没有多出莫名其妙的项目,这是Loader的所在。而DLL木马本体比较难发现,需要用户有一定编程知识和分析能力,在Loader里查找DLL名称,或者从进程里看有没有挂接什么陌生的DLL!但是,对于一些计算机的初级用户来说,这样的发现过程是非常困难的!因此,最简单的方法:杀毒软件和防火墙,这虽然不是万能的解决之道,但是对于不了解系统原理,没有编程经验的新手来说,总算是一种权宜之计吧!
 
module ecnt( //input RST_N,//内部设置 input inclk0, // 加入 PLL 输入时钟信号 input start_in, output start, output reg [11:0] result1, output reg [11:0] result2, output reg [11:0] result3, output reg [11:0] result4, output reg [11:0] result5, output reg [11:0] result6 ); wire locked; wire clk_pulse1; wire clk_pluse2; //IP核设置 相位180° reg gate1; reg gate2; reg gate3; reg [2:0] edge_cnt; reg [11:0] result_cnt1; reg [11:0] result_cnt_temp1; reg [11:0] result_cnt2; reg [11:0] result_cnt_temp2; reg [11:0] result_cnt3; reg [11:0] result_cnt_temp3; //反向计数器 reg [11:0] result_cnt4; reg [11:0] result_cnt_temp4; reg [11:0] result_cnt5; reg [11:0] result_cnt_temp5; reg [11:0] result_cnt6; reg [11:0] result_cnt_temp6; reg [19:0] cnt; wire sys_rst_n; assign sys_rst_n = 1'b1; assign rst_n = sys_rst_n & locked; plle_0002 u_PLLE ( .refclk (inclk0), // refclk.clk .rst (~sys_rst_n), // reset.reset .outclk_0 (clk_pulse1), // 193M .outclk_1 (clk_pulse2),// 193M-相位180° .locked (locked) // locked.export ); pll_test_0002 u_pll_test ( .refclk (inclk0), // refclk.clk .rst (~sys_rst_n), // reset.reset .outclk_0 (c_test) // outclk0.clk //.locked (locked_test) // locked.export ); localparam start_r_time = 20'd200; // 200x5=1000ns localparam start_d_time = 20'd400; // 400x5=2000ns-1000ns localparam cnt_time = 20'd10000; // 70000x5=350000ns=3.5ms assign start = (cnt >= start_r_time && cnt <= start_d_time) ? 1'b1 : 1'b0; always @(posedge clk_pulse1 or negedge rst_n) begin if(!rst_n) cnt <= 20'd0; else if (cnt == cnt_time) cnt <= 20'd0; else cnt <= cnt + 1'b1; end always @(posedge start_in or negedge rst_n)begin if(rst_n == 1'b0)begin gate1 <= 1'b0; gate2 <= 1'b0; gate3 <= 1'b0; //start<=1'b0; edge_cnt <= 3'b000; end else if (start)begin gate1<=1'b0; gate2<=1'b0; gate3 <= 1'b0; edge_cnt<=3'b001; end else if ((start_in)&&(edge_cnt==3'b001))begin gate1<=1'b1; gate2<=1'b0; gate3 <= 1'b0; edge_cnt<=edge_cnt+3'b001; end else if ((start_in)&&(edge_cnt==3'b010))begin gate1<=1'b0; gate2<=1'b1; gate3 <= 1'b0; edge_cnt<=edge_cnt+3'b001; end else if ((start_in)&&(edge_cnt==3'b011))begin gate1<=1'b0; gate2<=1'b0; gate3 <= 1'b1; edge_cnt<=edge_cnt+3'b001; end else if ((start_in)&&(edge_cnt==3'b100))begin gate1<=1'b0; gate2<=1'b0; gate3 <= 1'b0; edge_cnt<=3'b000; end end //格雷码计数器 reg [11:0] NextCnt1; reg [11:0] tmpCnt1; integer k; always @(posedge clk_pulse1 or negedge rst_n) begin if(!rst_n)begin result_cnt_temp1 <= 12'b0; result_cnt1 <= 12'b0; end else if(gate1) result_cnt_temp1 <= NextCnt1;//到下一个时钟的上升沿 else begin result_cnt1 <= result_cnt_temp1; result_cnt_temp1 <= 12'b0; end end always @(result_cnt_temp1) begin tmpCnt1[11] = result_cnt_temp1[11]; for(k = 10; k >= 0; k = k - 1) tmpCnt1[k] = result_cnt_temp1[k] ^ tmpCnt1[k+1]; if(tmpCnt1[0] == 1'b0) begin NextCnt1[0] = ~result_cnt_temp1[0]; NextCnt1[11:1] = result_cnt_temp1[11:1]; end else if(tmpCnt1[1] == 1'b0) begin NextCnt1[0] = result_cnt_temp1[0]; NextCnt1[1] = ~result_cnt_temp1[1]; NextCnt1[11:2] = result_cnt_temp1[11:2]; end else if(tmpCnt1[2] == 1'b0) begin NextCnt1[1:0] = result_cnt_temp1[1:0]; NextCnt1[2] = ~result_cnt_temp1[2]; NextCnt1[11:3] = result_cnt_temp1[11:3]; end else if(tmpCnt1[3] == 1'b0) begin NextCnt1[2:0] = result_cnt_temp1[2:0]; NextCnt1[3] = ~result_cnt_temp1[3]; NextCnt1[11:4] = result_cnt_temp1[11:4]; end else if(tmpCnt1[4] == 1'b0) begin NextCnt1[3:0] = result_cnt_temp1[3:0]; NextCnt1[4] = ~result_cnt_temp1[4]; NextCnt1[11:5] = result_cnt_temp1[11:5]; end else if(tmpCnt1[5] == 1'b0) begin NextCnt1[4:0] = result_cnt_temp1[4:0]; NextCnt1[5] = ~result_cnt_temp1[5]; NextCnt1[11:6] = result_cnt_temp1[11:6]; end else if(tmpCnt1[6] == 1'b0) begin NextCnt1[5:0] = result_cnt_temp1[5:0]; NextCnt1[6] = ~result_cnt_temp1[6]; NextCnt1[11:7] = result_cnt_temp1[11:7]; end else if(tmpCnt1[7] == 1'b0) begin NextCnt1[6:0] = result_cnt_temp1[6:0]; NextCnt1[7] = ~result_cnt_temp1[7]; NextCnt1[11:8] = result_cnt_temp1[11:8]; end else if(tmpCnt1[8] == 1'b0) begin NextCnt1[7:0] = result_cnt_temp1[7:0]; NextCnt1[8] = ~result_cnt_temp1[8]; NextCnt1[11:9] = result_cnt_temp1[11:9]; end else if(tmpCnt1[9] == 1'b0) begin NextCnt1[8:0] = result_cnt_temp1[8:0]; NextCnt1[9] = ~result_cnt_temp1[9]; NextCnt1[11:10] = result_cnt_temp1[11:10]; end else if(tmpCnt1[10] == 1'b0) begin NextCnt1[9:0] = result_cnt_temp1[9:0]; NextCnt1[10] = ~result_cnt_temp1[10]; NextCnt1[11] = result_cnt_temp1[11]; end else begin NextCnt1[10:0] = result_cnt_temp1[10:0]; NextCnt1[11] = ~result_cnt_temp1[11]; end end //计数第二个gate reg [11:0] NextCnt2; reg [11:0] tmpCnt2; always @(posedge clk_pulse1 or negedge rst_n) begin if(!rst_n)begin result_cnt_temp2 <= 12'b0; result_cnt2 <= 12'b0; end else if(gate2) result_cnt_temp2 <= NextCnt2;//到下一个时钟的上升沿 else begin result_cnt2 <= result_cnt_temp2; result_cnt_temp2 <= 12'b0; end end always @( result_cnt_temp2 ) begin tmpCnt2[11] = result_cnt_temp2[11]; for( k=10; k>=0; k=k-1 ) tmpCnt2[k] = result_cnt_temp2[k] ^ tmpCnt2[k+1]; if( tmpCnt2[0]==1'b0 ) begin NextCnt2[0] = ~result_cnt_temp2[0]; NextCnt2[11:1] = result_cnt_temp2[11:1]; end else if( tmpCnt2[1]==1'b0 ) begin NextCnt2[0] = result_cnt_temp2[0]; NextCnt2[1] = ~result_cnt_temp2[1]; NextCnt2[11:2] = result_cnt_temp2[11:2]; end else if( tmpCnt2[2]==1'b0 ) begin NextCnt2[1:0] = result_cnt_temp2[1:0]; NextCnt2[2] = ~result_cnt_temp2[2]; NextCnt2[11:3] = result_cnt_temp2[11:3]; end else if( tmpCnt2[3]==1'b0 ) begin NextCnt2[2:0] = result_cnt_temp2[2:0]; NextCnt2[3] = ~result_cnt_temp2[3]; NextCnt2[11:4] = result_cnt_temp2[11:4]; end else if( tmpCnt2[4]==1'b0 ) begin NextCnt2[3:0] = result_cnt_temp2[3:0]; NextCnt2[4] = ~result_cnt_temp2[4]; NextCnt2[11:5] = result_cnt_temp2[11:5]; end else if(tmpCnt2[5]==1'b0 ) begin NextCnt2[4:0] = result_cnt_temp2[4:0]; NextCnt2[5] = ~result_cnt_temp2[5]; NextCnt2[11:6] = result_cnt_temp2[11:6]; end else if(tmpCnt2[6]==1'b0 ) begin NextCnt2[5:0] = result_cnt_temp2[5:0]; NextCnt2[6] = ~result_cnt_temp2[6]; NextCnt2[11:7] = result_cnt_temp2[11:7]; end else if (tmpCnt2[7]==1'b0) begin NextCnt2[6:0] = result_cnt_temp2[6:0]; NextCnt2[7] = ~result_cnt_temp2[7]; NextCnt2[11:8] = result_cnt_temp2[11:8]; end else if (tmpCnt2[8]==1'b0) begin NextCnt2[7:0] = result_cnt_temp2[7:0]; NextCnt2[8] = ~result_cnt_temp2[8]; NextCnt2[11:9] = result_cnt_temp2[11:9]; end else if (tmpCnt2[9]==1'b0) begin NextCnt2[8:0] = result_cnt_temp2[8:0]; NextCnt2[9] = ~result_cnt_temp2[9]; NextCnt2[11:10] = result_cnt_temp2[11:10]; end else begin NextCnt2[10:0] = result_cnt_temp2[10:0]; NextCnt2[11] = ~result_cnt_temp2[11]; end end //计数第三个gate reg [11:0] NextCnt3; reg [11:0] tmpCnt3; always @(posedge clk_pulse1 or negedge rst_n) begin if(!rst_n)begin result_cnt_temp3 <= 12'b0; result_cnt3 <= 12'b0; end else if(gate3) result_cnt_temp3 <= NextCnt3;//到下一个时钟的上升沿 else begin result_cnt3 <= result_cnt_temp3; result_cnt_temp3 <= 12'b0; end end always @( result_cnt_temp3 ) begin tmpCnt3[11] = result_cnt_temp3[11]; for( k=10; k>=0; k=k-1 ) tmpCnt3[k] = result_cnt_temp3[k] ^ tmpCnt3[k+1]; if( tmpCnt3[0]==1'b0 ) begin NextCnt3[0] = ~result_cnt_temp3[0]; NextCnt3[11:1] = result_cnt_temp3[11:1]; end else if( tmpCnt3[1]==1'b0 ) begin NextCnt3[0] = result_cnt_temp3[0]; NextCnt3[1] = ~result_cnt_temp3[1]; NextCnt3[11:2] = result_cnt_temp3[11:2]; end else if( tmpCnt3[2]==1'b0 ) begin NextCnt3[1:0] = result_cnt_temp3[1:0]; NextCnt3[2] = ~result_cnt_temp3[2]; NextCnt3[11:3] = result_cnt_temp3[11:3]; end else if( tmpCnt3[3]==1'b0 ) begin NextCnt3[2:0] = result_cnt_temp3[2:0]; NextCnt3[3] = ~result_cnt_temp3[3]; NextCnt3[11:4] = result_cnt_temp3[11:4]; end else if( tmpCnt3[4]==1'b0 ) begin NextCnt3[3:0] = result_cnt_temp3[3:0]; NextCnt3[4] = ~result_cnt_temp3[4]; NextCnt3[11:5] = result_cnt_temp3[11:5]; end else if(tmpCnt3[5]==1'b0 ) begin NextCnt3[4:0] = result_cnt_temp3[4:0]; NextCnt3[5] = ~result_cnt_temp3[5]; NextCnt3[11:6] = result_cnt_temp3[11:6]; end else if(tmpCnt3[6]==1'b0 ) begin NextCnt3[5:0] = result_cnt_temp3[5:0]; NextCnt3[6] = ~result_cnt_temp3[6]; NextCnt3[11:7] = result_cnt_temp3[11:7]; end else if (tmpCnt3[7]==1'b0) begin NextCnt3[6:0] = result_cnt_temp3[6:0]; NextCnt3[7] = ~result_cnt_temp3[7]; NextCnt3[11:8] = result_cnt_temp3[11:8]; end else if (tmpCnt3[8]==1'b0) begin NextCnt3[7:0] = result_cnt_temp3[7:0]; NextCnt3[8] = ~result_cnt_temp3[8]; NextCnt3[11:9] = result_cnt_temp3[11:9]; end else if (tmpCnt3[9]==1'b0) begin NextCnt3[8:0] = result_cnt_temp3[8:0]; NextCnt3[9] = ~result_cnt_temp3[9]; NextCnt3[11:10] = result_cnt_temp3[11:10]; end else begin NextCnt3[10:0] = result_cnt_temp3[10:0]; NextCnt3[11] = ~result_cnt_temp3[11]; end end //把格雷码计数结果转为二进制码 reg [11:0] result_cnt1_b; reg [11:0] result_cnt2_b; reg [11:0] result_cnt3_b; always @(result_cnt_temp1) begin result_cnt1_b[11] = result_cnt_temp1[11]; for(k = 10; k >= 0; k = k - 1) result_cnt1_b[k] = result_cnt_temp1[k] ^ result_cnt1_b[k+1]; end always @( result_cnt_temp2 )begin result_cnt2_b[11] = result_cnt_temp2[11]; for( k=10; k>=0; k=k-1 ) result_cnt2_b[k] = result_cnt_temp2[k] ^ result_cnt2_b[k+1]; end always @( result_cnt_temp3 )begin result_cnt3_b[11] = result_cnt_temp3[11]; for( k=10; k>=0; k=k-1 ) result_cnt3_b[k] = result_cnt_temp3[k] ^ result_cnt3_b[k+1]; end //计算start和stop脉冲的间隔时间 always @(posedge clk_pulse1 or negedge rst_n) begin if(!rst_n) result1 <= 12'b0; else if(result_cnt1_b) result1 <= result_cnt1_b ; end always @(posedge clk_pulse1 or negedge rst_n) begin if(!rst_n) result2 <= 12'b0; else if(result_cnt2_b) result2 <= result_cnt2_b ; end always @(posedge clk_pulse1 or negedge rst_n) begin if(!rst_n) result3 <= 12'b0; else if(result_cnt2_b) result3 <= result_cnt3_b ; end //反相计数器第一个gate //格雷码计数器 reg [11:0] NextCnt4; reg [11:0] tmpCnt4; always @(posedge clk_pulse2 or negedge rst_n) begin if(!rst_n)begin result_cnt_temp4 <= 12'b0; result_cnt4 <= 12'b0; end else if(gate1) result_cnt_temp4 <= NextCnt4;//到下一个时钟的上升沿 else begin result_cnt4 <= result_cnt_temp4; result_cnt_temp4 <= 12'b0; end end always @(result_cnt_temp4) begin tmpCnt4[11] = result_cnt_temp4[11]; for(k = 10; k >= 0; k = k - 1) tmpCnt4[k] = result_cnt_temp4[k] ^ tmpCnt4[k+1]; if( tmpCnt4[0]==1'b0 )begin NextCnt4[0] = ~result_cnt_temp4[0]; NextCnt4[11:1] = result_cnt_temp4[11:1]; end else if(tmpCnt4[1] == 1'b0) begin NextCnt4[0] = result_cnt_temp4[0]; NextCnt4[1] = ~result_cnt_temp4[1]; NextCnt4[11:2] = result_cnt_temp4[11:2]; end else if(tmpCnt4[2] == 1'b0) begin NextCnt4[1:0] = result_cnt_temp4[1:0]; NextCnt4[2] = ~result_cnt_temp4[2]; NextCnt4[11:3] = result_cnt_temp4[11:3]; end else if(tmpCnt4[3] == 1'b0) begin NextCnt4[2:0] = result_cnt_temp4[2:0]; NextCnt4[3] = ~result_cnt_temp4[3]; NextCnt4[11:4] = result_cnt_temp4[11:4]; end else if(tmpCnt4[4] == 1'b0) begin NextCnt4[3:0] = result_cnt_temp4[3:0]; NextCnt4[4] = ~result_cnt_temp4[4]; NextCnt4[11:5] = result_cnt_temp4[11:5]; end else if(tmpCnt4[5] == 1'b0) begin NextCnt4[4:0] = result_cnt_temp4[4:0]; NextCnt4[5] = ~result_cnt_temp4[5]; NextCnt4[11:6] = result_cnt_temp4[11:6]; end else if(tmpCnt4[6] == 1'b0) begin NextCnt4[5:0] = result_cnt_temp4[5:0]; NextCnt4[6] = ~result_cnt_temp4[6]; NextCnt4[11:7] = result_cnt_temp4[11:7]; end else if(tmpCnt4[7] == 1'b0) begin NextCnt4[6:0] = result_cnt_temp4[6:0]; NextCnt4[7] = ~result_cnt_temp4[7]; NextCnt4[11:8] = result_cnt_temp4[11:8]; end else if(tmpCnt4[8] == 1'b0) begin NextCnt4[7:0] = result_cnt_temp4[7:0]; NextCnt4[8] = ~result_cnt_temp4[8]; NextCnt4[11:9] = result_cnt_temp4[11:9]; end else if(tmpCnt4[9] == 1'b0) begin NextCnt4[8:0] = result_cnt_temp4[8:0]; NextCnt4[9] = ~result_cnt_temp4[9]; NextCnt4[11:10] = result_cnt_temp4[11:10]; end else if(tmpCnt4[10] == 1'b0) begin NextCnt4[9:0] = result_cnt_temp4[9:0]; NextCnt4[10] = ~result_cnt_temp4[10]; NextCnt4[11] = result_cnt_temp4[11]; end else begin NextCnt4[10:0] = result_cnt_temp4[10:0]; NextCnt4[11] = ~result_cnt_temp4[11]; end end //反向计数第二个gate reg [11:0] NextCnt5; reg [11:0] tmpCnt5; always @(posedge clk_pulse2 or negedge rst_n) begin if(!rst_n)begin result_cnt_temp5 <= 12'b0; result_cnt5<= 12'b0; end else if(gate2) result_cnt_temp5 <= NextCnt5;//到下一个时钟的上升沿 else begin result_cnt5 <= result_cnt_temp5; result_cnt_temp5 <= 12'b0; end end always @( result_cnt_temp5 ) begin tmpCnt5[11] = result_cnt_temp5[11]; for( k=10; k>=0; k=k-1 ) tmpCnt5[k] = result_cnt_temp5[k] ^ tmpCnt5[k+1]; if( tmpCnt5[0]==1'b0 )begin NextCnt5[0] = ~result_cnt_temp5[0]; NextCnt5[11:1] = result_cnt_temp5[11:1]; end else if( tmpCnt2[1]==1'b0 ) begin NextCnt5[0] = result_cnt_temp5[0]; NextCnt5[1] = ~result_cnt_temp5[1]; NextCnt5[11:2] = result_cnt_temp5[11:2]; end else if( tmpCnt5[2]==1'b0 ) begin NextCnt5[1:0] = result_cnt_temp5[1:0]; NextCnt5[2] = ~result_cnt_temp5[2]; NextCnt5[11:3] = result_cnt_temp5[11:3]; end else if( tmpCnt5[3]==1'b0 ) begin NextCnt5[2:0] = result_cnt_temp5[2:0]; NextCnt5[3] = ~result_cnt_temp5[3]; NextCnt5[11:4] = result_cnt_temp5[11:4]; end else if( tmpCnt5[4]==1'b0 ) begin NextCnt5[3:0] = result_cnt_temp5[3:0]; NextCnt5[4] = ~result_cnt_temp5[4]; NextCnt5[11:5] = result_cnt_temp5[11:5]; end else if(tmpCnt5[5]==1'b0 ) begin NextCnt5[4:0] = result_cnt_temp5[4:0]; NextCnt5[5] = ~result_cnt_temp5[5]; NextCnt5[11:6] = result_cnt_temp5[11:6]; end else if(tmpCnt5[6]==1'b0 ) begin NextCnt5[5:0] = result_cnt_temp5[5:0]; NextCnt5[6] = ~result_cnt_temp5[6]; NextCnt5[11:7] = result_cnt_temp5[11:7]; end else if (tmpCnt5[7]==1'b0) begin NextCnt5[6:0] = result_cnt_temp5[6:0]; NextCnt5[7] = ~result_cnt_temp5[7]; NextCnt5[11:8] = result_cnt_temp5[11:8]; end else if (tmpCnt5[8]==1'b0) begin NextCnt5[7:0] = result_cnt_temp5[7:0]; NextCnt5[8] = ~result_cnt_temp5[8]; NextCnt5[11:9] = result_cnt_temp5[11:9]; end else if (tmpCnt5[9]==1'b0) begin NextCnt5[8:0] = result_cnt_temp5[8:0]; NextCnt5[9] = ~result_cnt_temp5[9]; NextCnt5[11:10] = result_cnt_temp5[11:10]; end else begin NextCnt5[10:0] = result_cnt_temp5[10:0]; NextCnt5[11] = ~result_cnt_temp5[11]; end end //反向计数第三个gate reg [11:0] NextCnt6; reg [11:0] tmpCnt6; always @(posedge clk_pulse2 or negedge rst_n) begin if(!rst_n)begin result_cnt_temp6 <= 12'b0; result_cnt6<= 12'b0; end else if(gate3) result_cnt_temp6 <= NextCnt6;//到下一个时钟的上升沿 else begin result_cnt6 <= result_cnt_temp6; result_cnt_temp6 <= 12'b0; end end always @( result_cnt_temp6 ) begin tmpCnt6[11] = result_cnt_temp6[11]; for( k=10; k>=0; k=k-1 ) tmpCnt6[k] = result_cnt_temp6[k] ^ tmpCnt6[k+1]; if( tmpCnt6[0]==1'b0 ) begin NextCnt6[0] = ~result_cnt_temp6[0]; NextCnt6[11:1] = result_cnt_temp6[11:1]; end else if( tmpCnt6[1]==1'b0 ) begin NextCnt6[0] = result_cnt_temp6[0]; NextCnt6[1] = ~result_cnt_temp6[1]; NextCnt6[11:2] = result_cnt_temp6[11:2]; end else if( tmpCnt6[2]==1'b0 ) begin NextCnt6[1:0] = result_cnt_temp6[1:0]; NextCnt6[2] = ~result_cnt_temp6[2]; NextCnt6[11:3] = result_cnt_temp6[11:3]; end else if( tmpCnt6[3]==1'b0 ) begin NextCnt6[2:0] = result_cnt_temp6[2:0]; NextCnt6[3] = ~result_cnt_temp6[3]; NextCnt6[11:4] = result_cnt_temp6[11:4]; end else if( tmpCnt6[4]==1'b0 ) begin NextCnt6[3:0] = result_cnt_temp6[3:0]; NextCnt6[4] = ~result_cnt_temp6[4]; NextCnt6[11:5] = result_cnt_temp6[11:5]; end else if(tmpCnt6[5]==1'b0 ) begin NextCnt6[4:0] = result_cnt_temp6[4:0]; NextCnt6[5] = ~result_cnt_temp6[5]; NextCnt6[11:6] = result_cnt_temp6[11:6]; end else if(tmpCnt6[6]==1'b0 ) begin NextCnt6[5:0] = result_cnt_temp6[5:0]; NextCnt6[6] = ~result_cnt_temp6[6]; NextCnt6[11:7] = result_cnt_temp6[11:7]; end else if (tmpCnt6[7]==1'b0) begin NextCnt6[6:0] = result_cnt_temp6[6:0]; NextCnt6[7] = ~result_cnt_temp6[7]; NextCnt6[11:8] = result_cnt_temp6[11:8]; end else if (tmpCnt6[8]==1'b0) begin NextCnt6[7:0] = result_cnt_temp6[7:0]; NextCnt6[8] = ~result_cnt_temp6[8]; NextCnt6[11:9] = result_cnt_temp6[11:9]; end else if (tmpCnt6[9]==1'b0) begin NextCnt6[8:0] = result_cnt_temp6[8:0]; NextCnt6[9] = ~result_cnt_temp6[9]; NextCnt6[11:10] = result_cnt_temp6[11:10]; end else begin NextCnt6[10:0] = result_cnt_temp6[10:0]; NextCnt6[11] = ~result_cnt_temp6[11]; end end //把格雷码计数结果转为二进制码 reg [11:0] result_cnt4_b; reg [11:0] result_cnt5_b; reg [11:0] result_cnt6_b; always @(result_cnt_temp4) begin result_cnt4_b[11] = result_cnt_temp4[11]; for(k = 10; k >= 0; k = k - 1) result_cnt4_b[k] = result_cnt_temp4[k] ^ result_cnt4_b[k+1]; end always @( result_cnt_temp5 )begin result_cnt5_b[11] = result_cnt_temp5[11]; for( k=10; k>=0; k=k-1 ) result_cnt5_b[k] = result_cnt_temp5[k] ^ result_cnt5_b[k+1]; end always @( result_cnt_temp6 )begin result_cnt6_b[11] = result_cnt_temp6[11]; for( k=10; k>=0; k=k-1 ) result_cnt6_b[k] = result_cnt_temp6[k] ^ result_cnt6_b[k+1]; end //计算start和stop脉冲的间隔时间 always @(posedge clk_pulse2 or negedge rst_n) begin if(!rst_n) result4 <= 12'b0; else if(result_cnt4_b) result4 <= result_cnt1_b ; end always @(posedge clk_pulse2 or negedge rst_n) begin if(!rst_n) result5 <= 12'b0; else if(result_cnt2_b) result5 <= result_cnt5_b ; end always @(posedge clk_pulse2 or negedge rst_n) begin if(!rst_n) result6 <= 12'b0; else if(result_cnt2_b) result6 <= result_cnt6_b ; end endmodule
最新发布
06-07
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值