原创 利用FPGA结合74LS138和74LS148功能

2011-7-23 16:13 3423 15 17 分类: FPGA/CPLD

7413874148分别是3-8译码器和8-3编码器。启源师兄让我们结合其功能,意思应该就是一个芯片,当信号从三线端输入,则八线端可以作为输出,此时该芯片为译码器;相反,当信号从八线端输入,则三线端可以作为输出,此时该芯片为编码器。如果此分析正确,则首先可以确定的是11IO口必须为双向口,通过一个引脚来控制该双向口的模式。FPGA中将双向口综合为三态门,通过一个引脚控制其输入或输出状态。

通过这个题目,收获最大的是在modelsim中对双向口的仿真,和普通端口的仿真要求不一样。这个题目是纯组合逻辑,对于刚入门FPGA的新手来说我觉得是个很好的锻炼,包括我。当然用单片机就更容易实现了,启源师兄应该是希望我们熟悉单片机的IO口操作咯,大家有空就做一下,贴上来一起讨论交流!

算了一下,51单片机的机器周期(24M晶振下)是0.5us,实现该题目,首先需要一个判断语句,大致花费时间是5*0.5us=2.5us,一个赋值语句1us,还有几个计算语句,保守估计5us,则一次译码需要的时间大概是8.5us。而FPGA的话,为了防止竞争冒险现象,延时1ns对信号取反,在延时1ns后对信号计算,立即输出,需要的时间不超过5ns。快了很多。不过FPGA的话是纯电路实现,速度也肯定快。

最后,贴上实现代码和测试代码以及测试数据。不足之处还请大家多多指教~嘻嘻

实现代码如下:

(由于modelsim不能写中文注释,我就用我这烂英文加了英文注释,见笑~

`timescale 1ns/1ns

module combinechip(

                                     A,

                                     Y,

                                     EN,

                                     inout_en

                                     );

input EN,inout_en;

 

inout [2:0] A;

inout [7:0] Y;

 

wire [7:0] Ywire;

wire [2:0] Awire;

 

wire A2bar,A1bar,A0bar;

wire Y7bar,Y6bar,Y5bar,Y4bar,Y3bar,Y2bar,Y1bar,Y0bar;

 

 

//get the negated value

assign #1 A0bar=~A[0];

assign #1 A1bar=~A[1];

assign #1 A2bar=~A[2];

assign #1 Y0bar=~Y[0];

assign #1 Y1bar=~Y[1];

assign #1 Y2bar=~Y[2];

assign #1 Y3bar=~Y[3];

assign #1 Y4bar=~Y[4];

assign #1 Y5bar=~Y[5];

assign #1 Y6bar=~Y[6];

assign #1 Y7bar=~Y[7];

 

//calculate output port Y and save in the Ywire

assign #2 Ywire[0]=~(A2bar&A1bar&A0bar&EN);

assign #2 Ywire[1]=~(A2bar&A1bar&A[0]&EN);

assign #2 Ywire[2]=~(A2bar&A[1]&A0bar&EN);

assign #2 Ywire[3]=~(A2bar&A[1]&A[0]&EN);

assign #2 Ywire[4]=~(A[2]&A1bar&A0bar&EN);

assign #2 Ywire[5]=~(A[2]&A1bar&A[0]&EN);

assign #2 Ywire[6]=~(A[2]&A[1]&A0bar&EN);

assign #2 Ywire[7]=~(A[2]&A[1]&A[0]&EN);

 

//calculate the output port A,and save in the A wire

assign #2 Awire[0]=(((Y[1]&Y2bar&Y4bar&Y6bar)|(Y[3]&Y4bar&Y6bar)|(Y[5]&Y6bar)|Y[7])&EN);

assign #2 Awire[1]=(((Y[2]&Y4bar&Y5bar)|(Y[3]&Y4bar&Y5bar)|Y[6]|Y[7])&EN);

assign #2 Awire[2]=(Y[4]|Y[5]|Y[6]|Y[7])&EN;

 

//if (inout_en) then Y is output,A is input.at this time,it is 3-8 decoder;

//else Y is input,A is output,at this time,it is 8-3 decoder;

assign Y=(inout_en==1)?Ywire:8'bz;

assign A=(inout_en==0)?Awire:3'bz;

 

endmodule

 

此代码在Quartus II 9.1 的寄存器级描述结果为:

在Quartus的RTL VIEW结果

其实就是把7413874148中的电路整到一块芯片,然后在输出口加个三态门,通过一个引脚控制而已。

下面是modelsimtestbench代码:

 

//the combinechip module's testbench

module combinechip_test;

 

  //if I want to use always to change the port's value

  //the variable must be reg

  reg [2:0] DA;

  reg [7:0] DY;

 

  //but if I want to test the inout port

  //the variable must be wire

  //so change the reg variable firstly,and then assign to wire variable

  wire [2:0] A;

  wire [7:0] Y;

 

  reg EN,inout_en;

 

//the module is tested 

combinechip t_combinechip(A,Y,EN,inout_en);

 

 

//generate input signal--------

 

initial

  begin

    DA=3'b0;

    DY=8'b0;

    EN=1;//enble the decoder

    inout_en=1;//inout_en=HIGH,Y is output;

   

    #45 inout_en=0;//inout_en=LOW,Y is input;

   

    //change the input port Y per 5ns

    #5 DY=8'h01;

    #5 DY=8'h02;

    #5 DY=8'h04;

    #5 DY=8'h08;

    #5 DY=8'h10;

    #5 DY=8'h20;

    #5 DY=8'h40;

    #5 DY=8'h80;

   

    #5 $stop;

   

  end

 

//It is opposite with above.

//if(inout_en) A is output,Y is input

//else A is input,Y is output 

assign  A=(inout_en==1)?DA:3'bz;

assign  Y=(inout_en==0)?DY:8'bz;

 

//we can find that the regular

//A0 is 0101...

//A1 is 00110011...

//A2 is 00001111... 

//so use the regular to generate signal is convenient

always

  #5 DA[0]=~DA[0];

always

  #10 DA[1]=~DA[1];

always

  #20 DA[2]=~DA[2];

 

//list the information about EN,inout_en,A and Y for us

initial

  $monitor("Time=%t:",$time,"EN=%d,inout_en=%d,A=%b,Y=%b",EN,inout_en,A,Y);

 

endmodule

 

仿真结果如下:(为了防止竞争冒险现象,所以当信号输入时,第一纳秒是对信号进行取反;第二纳秒才是对信号进行运算,所以应该是第三纳秒的结果才是准确的。即输入信号后,在2ns内的输出结果是不确定的。其中有一点大惑不解的是,当A作为输入时,3ns时刻的值才是正确的,而当Y作为输入时,需要的转换时间仅为2ns,即2ns时刻的值即稳定了。这个想了很久没想明白,先搁着,可能后面做多了会知道的~

# Time=                   0:EN=1,inout_en=1,A=000,Y=xxxxxxxx

# Time=                   2:EN=1,inout_en=1,A=000,Y=1111111x

# Time=                   3:EN=1,inout_en=1,A=000,Y=11111110

# Time=                   5:EN=1,inout_en=1,A=001,Y=11111110

# Time=                   7:EN=1,inout_en=1,A=001,Y=11111100

# Time=                   8:EN=1,inout_en=1,A=001,Y=11111101

# Time=                  10:EN=1,inout_en=1,A=010,Y=11111101

# Time=                  12:EN=1,inout_en=1,A=010,Y=11111111

# Time=                  13:EN=1,inout_en=1,A=010,Y=11111011

# Time=                  15:EN=1,inout_en=1,A=011,Y=11111011

# Time=                  17:EN=1,inout_en=1,A=011,Y=11110011

# Time=                  18:EN=1,inout_en=1,A=011,Y=11110111

# Time=                  20:EN=1,inout_en=1,A=100,Y=11110111

# Time=                  22:EN=1,inout_en=1,A=100,Y=11111111

# Time=                  23:EN=1,inout_en=1,A=100,Y=11101111

# Time=                  25:EN=1,inout_en=1,A=101,Y=11101111

# Time=                  27:EN=1,inout_en=1,A=101,Y=11001111

# Time=                  28:EN=1,inout_en=1,A=101,Y=11011111

# Time=                  30:EN=1,inout_en=1,A=110,Y=11011111

# Time=                  32:EN=1,inout_en=1,A=110,Y=11111111

# Time=                  33:EN=1,inout_en=1,A=110,Y=10111111

# Time=                  35:EN=1,inout_en=1,A=111,Y=10111111

# Time=                  37:EN=1,inout_en=1,A=111,Y=00111111

# Time=                  38:EN=1,inout_en=1,A=111,Y=01111111

# Time=                  40:EN=1,inout_en=1,A=000,Y=01111111

# Time=                  42:EN=1,inout_en=1,A=000,Y=11111111

# Time=                  43:EN=1,inout_en=1,A=000,Y=11111110

# Time=                  45:EN=1,inout_en=0,A=111,Y=00000000

# Time=                  47:EN=1,inout_en=0,A=000,Y=00000000

# Time=                  50:EN=1,inout_en=0,A=000,Y=00000001

# Time=                  55:EN=1,inout_en=0,A=000,Y=00000010

# Time=                  57:EN=1,inout_en=0,A=001,Y=00000010

# Time=                  60:EN=1,inout_en=0,A=001,Y=00000100

# Time=                  62:EN=1,inout_en=0,A=010,Y=00000100

# Time=                  65:EN=1,inout_en=0,A=010,Y=00001000

# Time=                  67:EN=1,inout_en=0,A=011,Y=00001000

# Time=                  70:EN=1,inout_en=0,A=011,Y=00010000

# Time=                  72:EN=1,inout_en=0,A=100,Y=00010000

# Time=                  75:EN=1,inout_en=0,A=100,Y=00100000

# Time=                  77:EN=1,inout_en=0,A=101,Y=00100000

# Time=                  80:EN=1,inout_en=0,A=101,Y=01000000

# Time=                  82:EN=1,inout_en=0,A=110,Y=01000000

# Time=                  85:EN=1,inout_en=0,A=110,Y=10000000

# Time=                  87:EN=1,inout_en=0,A=111,Y=10000000

PARTNER CONTENT

文章评论2条评论)

登录后参与讨论

用户1615925 2012-4-7 10:47

说得极是,当时初学,还不懂用状态机

用户284347 2011-7-25 20:28

你为什么要这么写,直接用状态机的写法不更好吗?
相关推荐阅读
用户1615925 2012-06-05 23:48
CVT面试经历
  2012.5.27 CVT总部之旅       今天参加了CVT总部二面,面的是硬件工程师实习生,很高兴自己能到二面,其实前面的话只要模电知识比较扎实都是可以过的。今年的流程比较简单,...
EE直播间
更多
我要评论
2
15
关闭 站长推荐上一条 /3 下一条