verilog中双向端口inout的使用的心得

合集下载

关于inout管脚的使用说明

关于inout管脚的使用说明

本人也是初学者,关于inout的verilog使用方法网上流传着很多版本。

在此将两个版本综合一下。

经本人测试,两种写法都能实现。

方法一:
assign ds18b20=ds18b20_reg;
这样的话,后面可以对ds18b20_reg进行赋值,可以赋值为0,z。

我没试过输出1,估计也是可以的。

这种方法意思是管脚与寄存器连接。

方法二:
assign ds18b20=(ds18b20_reg==0)?ds18b20_reg:1'bz;
这种方法实际上是定义了ds18b20_reg为使能端。

当ds18b20_reg==0为真时,三态门导通,可以作为输出;当ds18b20_reg==0为假时,三态门不导通,可以作为输入。

这种方法很形象的说明了inout管脚作为三态门的结构:使能信号、输入、输出。

这里ds18b20_reg 也可以替换成其他寄存器。

下面附上扒来的inout管脚电路图:
图一:详细图
图二:简单描述。

汇编语言中OUT和IN的用法

汇编语言中OUT和IN的用法

汇编语言中OUT和IN的用法在汇编语言中,OUT和IN是两条常用的指令,用于进行输入输出操作。

OUT指令用于向外部设备输出数据,而IN指令则用于从外部设备读取数据。

本文将详细介绍这两条指令的用法和常见应用情况。

一、OUT指令的用法OUT指令用于将数据从微处理器输出到外部设备,通常用于与键盘、显示器等设备的交互。

OUT指令的格式如下:```OUT DX, AL```其中,DX为输出端口的地址,而AL为要输出的数据。

OUT指令的使用步骤如下:1. 向DX寄存器中加载要输出数据的端口地址;2. 使用AL寄存器存放要输出的数据;3. 执行OUT指令完成输出操作。

例如,若需要向端口地址为80h的显示器输出数据55h,可以使用如下汇编代码:```MOV DX, 80hMOV AL, 55hOUT DX, AL```这样,55h将被输出到端口地址为80h的显示器上。

二、IN指令的用法与OUT指令相反,IN指令用于从外部设备读取数据到微处理器中,用于实现键盘、鼠标等设备的输入操作。

IN指令的格式如下:```IN AL, DX```其中,AL为读取到的数据,而DX为输入端口的地址。

IN指令的使用步骤如下:1. 向DX寄存器中加载要读取数据的端口地址;2. 执行IN指令,将读取到的数据存放到AL寄存器中。

例如,若需要从端口地址为60h的键盘读取数据,可以使用如下汇编代码:```MOV DX, 60hIN AL, DX```这样,从键盘读取到的数据将被存放在AL寄存器中。

三、OUT和IN的常见应用1. 输入和输出控制:通过OUT指令向显示器输出字符、控制光标位置等;通过IN指令从键盘读取字符,实现用户输入控制。

2. 与外设通信:通过OUT指令向串口、并口等外部设备输出数据,用于与其它设备进行通信;通过IN指令从这些外部设备读取数据,实现数据的接收和处理。

3. 程序调试与测试:在程序调试时,可以使用OUT指令将调试信息输出到控制台或显示器上,方便程序员进行调试;同时,可以使用IN指令从特定的端口读取调试信息,实现程序的测试与分析。

verilog语言中wire与reg的区别以及inout使用

verilog语言中wire与reg的区别以及inout使用

Verilog语言中wire与reg的区别reg相当于存储单元,wire相当于物理连线。

reg表示一定要有触发,没有输入的时候可以保持原来的值,但不直接实际的硬件电路对应。

wire表示直通,即输入有变化,输出马上无条件地反映(如与、非门的简单连接)。

两者的区别是:寄存器型数据保持最后一次的赋值,而线型数据需要持续的驱动。

wire使用在连续赋值语句中,而reg使用在过程赋值语句中。

在连续赋值语句中,表达式右侧的计算结果可以立即更新表达式的左侧。

在理解上,相当于一个逻辑之后直接连了一条线,这个逻辑对应于表达式的右侧,而这条线就对应于wire。

在过程赋值语句中,表达式右侧的计算结果在某种条件的触发下放到一个变量当中,而这个变量可以声明成reg类型的。

根据触发条件的不同,过程赋值语句可以建模不同的硬件结构:如果这个条件是时钟的上升沿或下降沿,那么这个硬件模型就是一个触发器;如果这个条件是某一信号的高电平或低电平,那么这个硬件模型就是一个锁存器;如果这个条件是赋值语句右侧任意操作数的变化,那么这个硬件模型就是一个组合逻辑。

对组合逻辑输出变量,可以直接用assign。

即如果不指定为reg类型,那么就默认为1位wire类型,故无需指定1位wire类型的变量。

当然专门指定出wire类型,可能是多位或为使程序易读。

wire只能被assign连续赋值,reg只能在initial和always中赋值。

输入端口可以由wire/reg驱动,但输入端口只能是wire;输出端口可以使wire/reg 类型,输出端口只能驱动wire;若输出端口在过程块中赋值则为reg型,若在过程块外赋值则为net型。

用关键词inout声明一个双向端口, inout端口不能声明为reg类型,只能是wire 类型。

默认信号是wire类型,reg类型要申明。

这里所说的默认是指输出信号申明成output 时为wire。

如果是模块内部信号,必须申明成wire或者reg.对于always语句而言,赋值要申明成reg。

Verilog的双向IO口的实现(

Verilog的双向IO口的实现(

Verilog的双向IO口的实现(最近有一个项目要用到FPGA,还要用硬件描述语言综合出一个双向IO口用作地址数据总线。

一直没能够实现,在实验过程中遇到了或这或那的问题,终于在今天有所突破!能够正确的读写CAN控制芯片SJA1000的测试寄存器。

在试验中也总结了一些东西,如下:1、Inout口,一般要放在最顶层的V文件中,我试验过放到下面的v文件中,没能够成功(更正一下:inout并非一定要在最顶层,也可以在底层设置。

具体可参见黑金开发板建模篇实验13 DS1302实时时钟驱动。

)。

2、在一个module中,可以将输出定义为reg型,然后直接与要驱动module的wire型输入相连,没有问题。

3、在调试程序的过程中,尽量借助于工具,如quartus内部的Signal Tap。

之前一直不会使用,现在也在慢慢学习。

用来模拟的是intel模式的总线读写其时序图如下:代码包括下面的及部分:can_top.vmodule can_top(CLK,RSTn,Row_scan,Column_scan,can_pin,can_ALE,can_WR,can_RD,can_CS,can_dir,can_rst_out);input CLK;input RSTn;output [7:0] Row_scan; output [1:0] Column_scan; inout [7:0] can_pin;output can_ALE;output can_WR;output can_RD;output can_CS;output can_dir;output can_rst_out;wire [7:0] data_in;wire rmd;wire wmd;wire [7:0] adr;wire [7:0] data_tx;wire [7:0] data_rx;wire rd_flag;wire wr_flag;trans_control U3(.CLK(CLK),.RSTn(RSTn),.data_in(data_in),.Row_scan(Row_scan),.Column_scan(Column_scan) ); wire can_rst;can_ctr U1(.CLK(CLK),.RSTn(RSTn),.rd_flag(rd_flag),.wr_flag(wr_flag),.data_rx(data_rx),.data_display(data_in), .rmd(rmd), .wmd(wmd),.adr(adr),.data_tx(data_tx),.can_rst(can_rst));can_op U2(.CLK(CLK),.RSTn(RSTn),.can_rst_in(can_rst),.rmd(rmd),.wmd(wmd),.adr(adr),.data_tx(data_tx),.can_in(can_in_temp),.en_out(en_out),.can_out(can_out),.read_cmd(read_cmd),.data_rx(data_rx),.can_ALE(can_ALE),.can_WR(can_WR),.can_RD(can_RD),.can_CS(can_CS),.can_dir(can_dir),.rd_flag(rd_flag),.wr_flag(wr_flag),.can_rst_out(can_rst_out));wire en_out;wire [7:0] can_out;// wire [7:0] can_in;reg [7:0] can_in_temp;wire read_cmd;always @ ( posedge CLK or negedge RSTn )beginif(!RSTn)can_in_temp<=8'b1000_1001;elsebeginif(read_cmd==1'b1)can_in_temp <= can_pin;endend// assign can_in = can_in_temp;assign can_pin = (en_out==1'b1)?can_out:8'bZZZZZZZZ; //双向口设置endmodulecan_ctr.vmodule can_ctr(CLK,RSTn,rd_flag,data_rx,data_display,rmd,wmd,adr,data_tx,can_rst);input CLK;input RSTn;input rd_flag;input wr_flag;input [7:0] data_rx;output [7:0] data_display;output rmd;output wmd;output [7:0] adr;output [7:0] data_tx;output can_rst;reg [7:0] data_display_temp;reg rmd_temp;reg wmd_temp;reg [7:0] adr_temp;reg [7:0] data_tx_temp;reg can_rst_temp;reg rst_flag;parameter TS = 26'd29_999_999; parameter T1S = 26'd49_999_999;always @ ( posedge CLK or negedge RSTn )if(!RSTn)begincan_rst_temp<=1'b1;rst_flag<=1'b1;endelse if (Count_Sec==26'd100 && rst_flag == 1'b1) begin can_rst_temp<=1'b0;rst_flag<=1'b0;endendalways @ ( posedge CLK or negedge RSTn )beginif(!RSTn)beginrmd_temp<=1'b0;wmd_temp<=1'b0;adr_temp<=8'b0000_0000;data_display_temp<= 8'b1000_1000;data_tx_temp<=8'b0000_0000;endelsebeginif (Count_Sec==TS)beginwmd_temp<=1'b1;adr_temp<=8'b0001_0000;data_tx_temp<=8'b0001_0010;endif (Count_Sec==T1S)rmd_temp<=1'b1;adr_temp<=8'b0001_0000; //读测试寄存器endif (wr_flag==1'b1)beginwmd_temp<=1'b0;endif (rd_flag==1'b1)beginrmd_temp<=1'b0;data_display_temp<= data_rx;endendendreg [25:0]Count_Sec;always @ ( posedge CLK or negedge RSTn ) if( !RSTn )Count_Sec <= 26'd0;else if( Count_Sec == T1S )Count_Sec <= 26'd0;elseCount_Sec <= Count_Sec + 1'b1;assign data_display=data_display_temp; assign rmd=rmd_temp;assign wmd=wmd_temp;assign adr=adr_temp;assign data_tx=data_tx_temp;assign can_rst=can_rst_temp;endmodulecan_op.vmodule can_op (CLK,RSTn,can_rst_in, rmd,wmd,adr,data_tx,can_in,en_out,can_out,read_cmd,data_rx,can_ALE,can_WR,can_RD,can_CS,can_dir,rd_flag,wr_flag,can_rst_out);input CLK;input RSTn; input can_rst_in; input rmd;input wmd; input [7:0]adr; input [7:0]data_tx;input [7:0]can_in;output en_out;output [7:0] can_out;output read_cmd;output [7:0]data_rx;output can_ALE;output can_WR;output can_RD;output can_CS;output can_dir;output rd_flag;output wr_flag;output can_rst_out;reg [7:0] can_out_temp;reg en_out_temp; //这两个变量来组成双向口输出控制reg read_cmd_temp;reg [7:0] data_rx_temp;reg can_ALE_temp;reg can_WR_temp;reg can_RD_temp;reg can_CS_temp;reg can_dir_temp;reg rd_flag_temp;reg wr_flag_temp;reg [3:0] count;always @ ( posedge CLK or negedge RSTn ) beginif ( !RSTn )beginrd_flag_temp<=1'b0;wr_flag_temp<=1'b0;can_WR_temp<=1'b1;can_RD_temp<=1'b1;can_CS_temp<=1'b1;can_dir_temp<=1'b0;data_rx_temp<=8'd221;count<= 4'd0;en_out_temp<=1'b1;can_out_temp<=8'd0;read_cmd_temp<=1'b0;endelsebeginif (rmd)begincase(count)4'd0,4'd1,4'd6: count<= count+1'b1; 4'd2: begincan_out_temp<= adr;en_out_temp<=1'b1;can_ALE_temp<= 1'b1;count<= count+1'b1;end4'd3:begincan_ALE_temp<=1'b0;count<= count+1'b1;end4'd4:begincan_CS_temp<= 1'b0;en_out_temp<=1'b0; end4'd5:begincan_RD_temp<= 1'b0; can_dir_temp=1'b1; count<= count+1'b1; end4'd7:beginread_cmd_temp<=1'b1; count<= count+1'b1; end4'd8:begincount<= count+1'b1; read_cmd_temp<=1'b0; end4'd9:begindata_rx_temp <= can_in; can_RD_temp<= 1'b1; count<= count+1'b1; can_dir_temp <= 1'b0; en_out_temp<=1'b1; end4'd10:begincan_CS_temp<= 1'b1;rd_flag_temp<=1'b1;end4'd11:begincount<=4'd0;rd_flag_temp<=1'b0;endendcaseendif (wmd)begincase(count)4'd0,4'd1: count<= count+1'b1; 4'd2: begincan_out_temp<= adr;en_out_temp<=1'b1;can_ALE_temp<= 1'b1;count<= count+1'b1;end4'd3:begincan_ALE_temp<=1'b0;count<= count+1'b1;end4'd4:begincan_CS_temp<= 1'b0;count<= count+1'b1;endbegincan_WR_temp<= 1'b0; count<= count+1'b1; end4'd6:begincan_out_temp<= data_tx; count<= count+1'b1; end 4'd7:begincount<= count+1'b1; end4'd8:begincan_WR_temp<= 1'b1; count<= count+1'b1; end4'd9:begincan_CS_temp<= 1'b1; can_ALE_temp<=1'b1; count<= count+1'b1;wr_flag_temp<=1'b1; end4'd10:begincount<= 1'b0;wr_flag_temp<=1'b0; end endcaseendendassign data_rx=data_rx_temp;assign can_ALE=can_ALE_temp;assign can_WR=can_WR_temp;assign can_RD=can_RD_temp;assign can_CS=can_CS_temp;assign can_dir=can_dir_temp;assign wr_flag=wr_flag_temp;assign rd_flag=rd_flag_temp;assign can_rst_out=can_rst_in;assign can_out=can_out_temp;assign en_out=en_out_temp;assign read_cmd=read_cmd_temp;endmoduletrans_control.v 这个与下面两个v文件是用来将接收到的数据显示到数码管上module trans_control(CLK,RSTn,data_in,Row_scan,Column_scan);input CLK;input RSTn;input [7:0] data_in;output [7:0] Row_scan;output [1:0] Column_scan;wire [7:0] data1_temp;wire [7:0] data2_temp;trans_module U1(.CLK (CLK),.RSTn (RSTn),.data_in (data_in),.out_data1 (data1_temp), .out_data2 (data2_temp) );scan_module U2(.CLK (CLK),.RSTn (RSTn),.scan_data1 (data1_temp), .scan_data2 (data2_temp), .Row_scan (Row_scan),.Column_scan (Column_scan) );endmoduletrans_module.vmodule trans_module(CLK,RSTn,data_in,out_data1,out_data2);input CLK;input RSTn;input [7:0] data_in;output [7:0] out_data1; output [7:0] out_data2;reg [7:0] out_data1_temp; reg [7:0] out_data2_temp;reg [3:0] temp1;reg [3:0] temp2;parameter _0 = 8'b1100_0000, _1 = 8'b1111_1001, _2 = 8'b1010_0100, _3 = 8'b1011_0000, _4 = 8'b1001_1001, _5 = 8'b1001_0010, _6 = 8'b1000_0010, _7 = 8'b1111_1000, _8 = 8'b1000_0000,_9 = 8'b1001_0000, _A = 8'b1000_1000, _B = 8'b1000_0011, _C = 8'b1100_0110, _D = 8'b1010_0001, _E = 8'b1000_0100, _F = 8'b1000_1110;always @ ( posedge CLK or negedge RSTn )if( !RSTn )beginout_data1_temp<= 8'b1100_0000;out_data2_temp<= 8'b1100_0000;temp1 <= 4'd0;temp2 <= 4'd0;endelsebegintemp1 <= data_in[3:0];temp2 <= data_in[7:4];case(temp1)4'h0 : out_data1_temp <= _0;4'h1 : out_data1_temp <= _1;4'h2 : out_data1_temp <= _2;4'h3 : out_data1_temp <= _3;4'h4 : out_data1_temp <= _4;4'h5 : out_data1_temp <= _5;4'h6 : out_data1_temp <= _6;4'h7 : out_data1_temp <= _7;4'h8 : out_data1_temp <= _8;4'h9 : out_data1_temp <= _9;4'hA : out_data1_temp <= _A;4'hB : out_data1_temp <= _B;4'hC : out_data1_temp <= _C;4'hD : out_data1_temp <= _D;4'hE : out_data1_temp <= _E;4'hF : out_data1_temp <= _F; endcasecase(temp2)4'h0 : out_data2_temp <= _0;4'h1 : out_data2_temp <= _1;4'h2 : out_data2_temp <= _2;4'h3 : out_data2_temp <= _3;4'h4 : out_data2_temp <= _4;4'h5 : out_data2_temp <= _5;4'h6 : out_data2_temp <= _6;4'h7 : out_data2_temp <= _7;4'h8 : out_data2_temp <= _8;4'h9 : out_data2_temp <= _9;4'hA : out_data2_temp <= _A;4'hB : out_data2_temp <= _B;4'hC : out_data2_temp <= _C;4'hD : out_data2_temp <= _D;4'hE : out_data2_temp <= _E;4'hF : out_data2_temp <= _F; endcaseendassign out_data1 = out_data1_temp; assign out_data2 = out_data2_temp;endmodulescan_module.vmodule scan_module(CLK,RSTn,scan_data1,scan_data2,Column_scan,Row_scan);input CLK;input RSTn;input [7:0] scan_data1;input [7:0] scan_data2;output [7:0] Row_scan;output [1:0] Column_scan;parameter T10MS = 19'd499_999;//50M*0.01-1=499_999 reg [18:0]Count1;always @ ( posedge CLK or negedge RSTn )if( !RSTn )Count1 <= 19'd0;else if( Count1 == T10MS )Count1 <= 19'd0;elseCount1 <= Count1 + 19'b1;reg [1:0]t;always @ ( posedge CLK or negedge RSTn )if( !RSTn )t <= 2'd0;else if( t == 2'd2 )t <= 2'd0;else if( Count1 == T10MS )t <= t + 1'b1;reg [7:0] Row_scan_temp;reg [1:0] Column_scan_temp;always @ ( posedge CLK or negedge RSTn )if( !RSTn )beginColumn_scan_temp <= 2'b01;Row_scan_temp <= 8'hd0;endelse if( Count1 == T10MS )case( t )2'd0 : begin Column_scan_temp <= 2'b01; Row_scan_temp <= scan_data1; end 2'd1 : begin Column_scan_temp <= 2'b10; Row_scan_temp <= scan_data2; end endcaseassign Column_scan = Column_scan_temp;assign Row_scan = Row_scan_temp;endmodule代码就这些,还有TCL引脚说明#------------------GLOBAL--------------------#set_global_assignment -name RESERVE_ALL_UNUSED_PINS "AS INPUT TRI-STATED" set_global_assignment -name ENABLE_INIT_DONE_OUTPUT OFF#复位引脚set_location_assignment PIN_M1 -to RSTn#时钟引脚set_location_assignment PIN_R9 -to CLK#数码管对应的引脚set_location_assignment PIN_M8 -to Row_scan[0] set_location_assignment PIN_L7 -to Row_scan[1] set_location_assignment PIN_P9 -to Row_scan[2] set_location_assignment PIN_N9 -to Row_scan[3] set_location_assignment PIN_M9 -to Row_scan[4] set_location_assignment PIN_M10 -to Row_scan[5] set_location_assignment PIN_P11 -to Row_scan[6] set_location_assignment PIN_N11 -to Row_scan[7] set_location_assignment PIN_N8 -to Column_scan[0] set_location_assignment PIN_P8 -to Column_scan[1] #CAN控制信号对应引脚set_location_assignment PIN_R1 -to can_pin[0]set_location_assignment PIN_R3 -to can_pin[1]set_location_assignment PIN_L3 -to can_pin[2]set_location_assignment PIN_K5 -to can_pin[3]set_location_assignment PIN_P3 -to can_pin[4]set_location_assignment PIN_L8 -to can_pin[5]set_location_assignment PIN_N5 -to can_pin[6]set_location_assignment PIN_K6 -to can_pin[7]set_location_assignment PIN_L6 -to can_ALEset_location_assignment PIN_T3 -to can_WRset_location_assignment PIN_L4 -to can_RDset_location_assignment PIN_N3 -to can_CSset_location_assignment PIN_T2 -to can_dirset_location_assignment PIN_P2 -to can_rst_out。

verilog中双向端口inout的使用的心得

verilog中双向端口inout的使用的心得

verilog中双向端口inout的使用的心得见许多问这个问题的,总结一下,希望能对大家有点用处,如果有不对的地方,欢迎指出.芯片外部引脚很多都使用inout类型的,为的是节省管腿。

一般信号线用做总线等双向数据传输的时候就要用到INOUT类型了。

就是一个端口同时做输入和输出。

inout在具体实现上一般用三态门来实现。

三态门的第三个状态就是高阻'Z'。

当inout端口不输出时,将三态门置高阻。

这样信号就不会因为两端同时输出而出错了,更详细的内容可以搜索一下三态门tri-state的资料.1 使用inout类型数据,可以用如下写法:inout data_inout;input data_in;reg data_reg;//data_inout的映象寄存器reg link_data;assign data_inout=link_data?data_reg:1’bz;//link_data控制三态门//对于data_reg,可以通过组合逻辑或者时序逻辑根据data_in对其赋值.通过控制link_data 的高低电平,从而设置data_inout是输出数据还是处于高阻态,如果处于高阻态,则此时当作输入端口使用.link_data可以通过相关电路来控制.2 编写测试模块时,对于inout类型的端口,需要定义成wire类型变量,而其它输入端口都定义成reg类型,这两者是有区别的.当上面例子中的data_inout用作输入时,需要赋值给data_inout,其余情况可以断开.此时可以用assign语句实现:assign data_inout=link?data_in_t:1’bz;其中的link ,data_in_t 是reg类型变量,在测试模块中赋值.另外,可以设置一个输出端口观察data_inout用作输出的情况:Wire data_out;Assign data_out_t=(!link)?data_inout:1’bz;else,in RTLinout use in top module(PAD)dont use inout(tri) in sub module也就是说,在内部模块最好不要出现inout,如果确实需要,那么用两个port实现,到顶层的时候再用三态实现。

双向既做输入又做输出的FPGA管脚

双向既做输入又做输出的FPGA管脚

双向信号既做输出又做输出- FPGA双向电路设计经验[导读] 2)双向信号既做输出又做输出上例是最简单的双向信号应用的特例.在实际的工程中,双向信号既做信号的输入,又做信号的输出,常见的数据总线就是这种操作在工程应用中,双向电路是设计者不得不面对的问题.在实际应用中,数据总线往往是双向的.如何正确处理数据总线是进行时序逻辑电路设计的基础.在程序设计过程中,关键技术在于:实体部分必须对端口属性进行申明,端口属性必须为Inout类型,在构造体需要对输出信号进行有条件的高阻控制.在双向电路的处理问题上,常用的处理方式有两种,在介绍双向电路的处理方式之前,先看看双向电路的基本格式:ENTITY Bidir_pin IS(Bidir : INOUT Std_logic;Oe, Clk, From_core : IN Std_logic;To_core : OUT Std_logic;……END Bidir_pin;ARCHITECTURE Behavior OF Bidir_pin ISBEGINBidir <= From_core WHEN Oe=‘1’ ELSE “ZZZZ”;To_core <= Bidir;___END Behavior;该程序揭示了双向电路的处理技巧,首先在实体部分Bidir属于双向信号,在端口定义时,端口属性为Inout类型,即把Bidir信号作为输入三态输出. 语句“Bidir <= From_core WHEN Oe=‘1’ ELSE “ZZZZ”;”表示Bidir信号三态输出,语句”To_core <= Bidir;”把Bidir信号作为输入信号.由此可见,双向电路在程序设计中,Didir输入当着普通的In类型,而在输出时,需要加一定的控制条件,三态输出.问题的关键在于:如何确定这个条件?1)双向信号作一个信号的输入,作另一信号的输出ENTITY Bidir ISPORT(Bidir : INOUT STD_LOGIC_VECTOR (7 DOWNTO 0);Oe, Clk : IN STD_LOGIC;From_core : IN STD_LOGIC_VECTOR (7 DOWNTO 0);To_core : OUT STD_LOGIC_VECTOR (7 DOWNTO 0));END Bidir;ARCHITECTURE Logic OF Bidir ISSIGNAL A : STD_LOGIC_VECTOR (7 DOWNTO 0);SIGNAL B : STD_LOGIC_VECTOR (7 DOWNTO 0);BEGINPROCESS (Clk)BEGINIF Clk = ''1'' AND Clk''EVENT THENA <= From_core;To_core <= B;END IF;END PROCESS;PROCESS (Oe, Bidir)BEGINIF( Oe = ''0'') THENBidir <= "ZZZZZZZZ";B <= Bidir;ELSEBidir <= A;B <= Bidir;END IF;END PROCESS;END Logic;这种设计方式叫做寄存双向信号的方法.本设计中Bidir为双向信号,From_core为数据输入端,To_core为数据输出端,Oe为三态输出使能,Clk为读写数据的时钟.在程序设计中,需要定义两个Signal A和B信号.A信号用于输入数据From_core的寄存器,B用于输出数据To_core的寄存器.采用寄存器的方法需要设计两个进程,一个进程把A, B信号在时钟的控制下负责端口的输入信号From_core和端口输出信号To_core的连接,这一步实现了寄存双向的功能.另外一个进程则负责信号 A,B和双向口之间的赋值关系.本设计只揭示了简单的双向信号操作方式,即Bidir既可以作为From_core的输出,又可以作为To_core的输入2)双向信号既做输出又做输出上例是最简单的双向信号应用的特例.在实际的工程中,双向信号既做信号的输入,又做信号的输出,常见的数据总线就是这种操作模式.Library IEEE;Use IEEE.STD_LOGIC_1164.All;Entity Dir_data IsPort(Clk : In STD_LOGIC;Rst : In STD_LOGIC;Rw : In STD_LOGIC;Address : In STD_LOGIC_VECTOR(1 Downto 0);Data : Inout STD_LOGIC_VECTOR(7 Downto 0));End Dir_data;Architecture Arc_dir Of Dir_data IsSignal Data_in : STD_LOGIC_VECTOR(7 Downto 0);Signal Data_out: STD_LOGIC_VECTOR(7 Downto 0);Signal Reg_a: STD_LOGIC_VECTOR(7 Downto 0);Signal Reg_b: STD_LOGIC_VECTOR(7 Downto 0);BeginData_in<=Data;D1:Process(Clk,Rst,Rw)BeginIf Rst=''1'' ThenReg_a<= (Others=>''0'');Reg_b<= (Others=>''0'');Elsif Clk''Event And Clk=''1'' Then If Rw=''1'' ThenIf Address="00" ThenReg_a<=Data_in;Elsif Address="01" ThenReg_b<=Data_in;Else Null;End If;Else Null;End If;Else Null;End If;End Process D1;D2:Process(Clk,Rw,Reg_a,Reg_b) BeginIf Clk''Event And Clk=''1'' ThenIf Rw=''0'' ThenIf Address="00" ThenData_out<=Reg_a;Elsif Address="01" ThenData_out<=Reg_b;Else Null;End If;Else Null;End If;Else Null;End If;End Process D2;Data<=Data_out When (Rw=''0'' And Address(1)=''0'') Else(Others=>''Z'');End Arc_dir;在程序设计中,首先需要定义Data_in, Data_out, Reg_a, Reg_b四个Signal,我们把Data_in叫做输入寄存器,它是从双向信号Data接收数据的寄存器,Data_out叫做输出寄存器,它是向双向信号Data发送信号的寄存器,Reg_a和Reg_b叫做操作寄存器,它们是在一定的时序控制下把Data_in数据送给Reg_a,Reg_b,在一定的时序控制下从Reg_a和Reg_b读出数据的.这样的处理方式必须有两个进程,因为在Architecture Arc_dir Of Dir_data Is和Begin之间定义了Data_in, Data_out, Reg_a, Reg_b四个Signal,它在同一进程内不支持既赋值,又调用,也就是说它不支持在D1进程中对信号Reg_a, Reg_b赋值,又在D1进程中又调用Reg_a, Reg_b.首先有语句”Data_in<=Data;”它表示输入寄存器无条件的接收双先信号的数据.在D1进程中,首先在Rst信号有效时,对操作寄存器Reg_a,和Reg_b进行清零操作,然后在时钟(Clk)的控制下,在写 (Rw)信号有效的情况下,对Reg_a, Reg_b寄存器在不同的地址控制下写入不同的Data_in值.在D2进程中,在时钟(Clk)的控制下,在读(Rw)信号有效的时候,把不同地址的 Reg_a, Reg_b的值送进Data_out中.最关键的是最后一句:“Data<=Data_out When (Rw=''0'' And Address(1)=''0'') Else (Others=>''Z'');”它表示双向信号的三态输出,而最最关键的是When后面的条件,如果条件限制太宽,就会错误占用双向信号总线,引起总线的误操作,如果条件限制太窄,输出寄存器的数据就不能够正确的送到数据总线上去,会引起数据的丢失.也就是说,只有正确的限制了When语句后面的条件,才能够把输出寄存器的数据正确地送到数据总线上去.仔细查看此条件,有如下的规律:When语句后的条件是操作寄存器写入输出寄存器的条件的公共条件.比如:Rw=’0’是操作寄存器的数据写入输出寄存器的读使能信号,Address(1)是地址线的公共部分.在实际工程应用中,需要设计者在分配地址总线的时候掌握一定的技巧,尽量从地址的低位到到高位,保证地址总线有更多位的公共部分,比如只对四个寄存器操作时,地址线分配为”100”,” 010”,”110”,”001”是不科学的,而”000”,”001”,”010”和”011”则是理想的.两者不同的是前者地址线没有公共部分,这样的设计无法用When语句对条件进行直接的控制,如果置之不理,由于列举不全,在逻辑综合时,电路会利用器件的乘积项和查找表的资源形成一个Latch, Latch不仅会把电路的时序变得复杂,而且电路存在潜在的危险性.虽然When语句后的条件不能够对条件进行直接的控制,但是可以使用枚举法一一把用到的地址线罗列出来,表示只有在这样的地址线的情况下才会用到数据总线,否则其他状态对数据总线送高阻,表示不占用数据总线.总而言之,双向信号是程序设计中尤其重要的基础,设计者在设计程序的时候,要尤其注意,何时会占用数据总线,何时不占用数据总线.。

verilog模块调用端口对应方式

verilog模块调用端口对应方式

verilog模块调用端口对应方式Verilog模块是一种重要的硬件描述语言,可以用来描述数字电路和系统。

模块的输入和输出端口是与其他模块或顶层模块进行连接的关键部分。

在Verilog中,模块的端口有三种类型:输入端口、输出端口和双向端口。

不同类型的端口必须按照不同的方式进行调用和连接。

对于输入端口,可以直接在模块实例化时使用“.”符号进行命名。

例如,如果模块的输入端口名称为“in1”和“in2”,则可以使用以下代码进行实例化:module_inst #(.in1(in1_val), .in2(in2_val))instance_name();其中“in1_val”和“in2_val”是输入信号的变量名,这些变量可以来自其他模块或顶层模块。

对于输出端口,可以使用“wire”类型进行声明,然后在模块实例化时将其连接到其他模块或顶层模块。

例如,如果模块的输出端口名称为“out1”和“out2”,则可以使用以下代码进行声明和实例化: module module_name(output wire out1, output wire out2); module_instinstance_name(.out1(out1_val), .out2(out2_val));其中“out1_val”和“out2_val”是输出信号的变量名,这些变量可以用于其他模块或顶层模块。

对于双向端口,可以使用“inout”类型进行声明,并在模块实例化时对其进行连接。

例如,如果模块的双向端口名称为“inout1”和“inout2”,则可以使用以下代码进行声明和实例化:module module_name(inout inout1, inout inout2);module_instinstance_name(.inout1(inout1_val), .inout2(inout2_val));其中“inout1_val”和“inout2_val”是双向信号的变量名,这些变量可以用于其他模块或顶层模块。

verilog input output inout 用法-概述说明以及解释

verilog input output inout 用法-概述说明以及解释

verilog input output inout 用法-概述说明以及解释1.引言1.1 概述引言是文章开头的一部分,用于介绍文章要讨论的主题。

在这篇文章中,我们将探讨Verilog中的input、output和inout的用法。

Verilog是一种硬件描述语言,被广泛应用于数字电子系统的设计和验证。

在数字电路设计中,输入(input)、输出(output)和双向的输入输出(inout)信号是非常重要的概念。

input关键字用于定义模块的输入信号,它们是外部输入到模块中的信号。

output关键字用于定义模块的输出信号,它们是从模块中输出到外部的信号。

而inout关键字则用于定义双向的输入输出信号,它们既可以从外部输入到模块中,也可以从模块中输出到外部。

在本文的后续部分,我们将详细介绍Verilog中input、output和inout的用法,包括定义变量、使用信号等方面。

通过学习这些内容,读者将能够更好地理解和应用Verilog语言,并能够利用它进行数字电路设计和验证。

接下来我们将进入正文部分,首先介绍Verilog中input的用法。

文章结构部分的内容如下:1.2 文章结构本文将对Verilog中的input、output和inout的用法进行详细介绍。

首先,将在引言部分概述Verilog的基本概念和应用场景。

然后,通过正文部分分别介绍input、output和inout的定义和使用方法。

在每个小节中,将详细说明如何定义相应的变量,并说明如何使用这些变量进行输入、输出和双向信号的传输。

在每个小节结束时,将提供实际示例以帮助读者更好地理解和应用Verilog中的input、output和inout。

在结论部分,将对各个部分进行总结,分别总结input、output和inout的用法,包括定义和使用方法等重要内容。

通过本文的阅读,读者将能够全面了解Verilog中input、output和inout的用法,并能够灵活应用于实际的工程设计中。

Verilog inout 双向口使用和仿真

Verilog inout 双向口使用和仿真

Verilog inout 双向口使用和仿真芯片外部引脚很多都使用inout类型的,为的是节省管腿。

一般信号线用做总线等双向数据传输的时候就要用到INOUT类型了。

就是一个端口同时做输入和输出。

inout在具体实现上一般用三态门来实现。

三态门的第三个状态就是高阻' Z'。

当inout端口不输出时,将三态门置高阻。

这样信号就不会因为两端同时输出而出错了,更详细的内容可以搜索一下三态门tri-state的资料.1 使用inout类型数据,可以用如下写法:inout data_inout;input data_in;reg data_reg;//data_inout的映象寄存器reg link_data;assign data_inout=link_data?data_reg:1’bz;//link_data控制三态门//对于data_reg,可以通过组合逻辑或者时序逻辑根据data_in对其赋值.通过控制link_data的高低电平,从而设置data_inout是输出数据还是处于高阻态,如果处于高阻态,则此时当作输入端口使用.link_data可以通过相关电路来控制.2 编写测试模块时,对于inout类型的端口,需要定义成wire类型变量,而其它输入端口都定义成reg类型,这两者是有区别的.当上面例子中的data_inout用作输入时,需要赋值给data_inout,其余情况可以断开.此时可以用assign语句实现:assign data_inout=link?data_in_t:1’bz;其中的l ink ,data_in_t是reg类型变量,在测试模块中赋值.另外,可以设置一个输出端口观察data_inout用作输出的情况:Wire data_out;Assign data_out_t=(!link)?data_inout:1’bz;else,in RTLinout use in top module(PAD)dont use inout(tri) in sub module也就是说,在内部模块最好不要出现inout,如果确实需要,那么用两个port实现,到顶层的时候再用三态实现。

【FPGA基础】双向端口inout端口的使用指北

【FPGA基础】双向端口inout端口的使用指北

【FPGA基础】双向端⼝inout端⼝的使⽤指北在查阅了各种书和帖⼦之后,总结了以下inout端⼝的使⽤注意事项。

(以下资料来源: 《Xilinx FPGA开发实⽤教程第⼆版》)⾸先是⼀些要先理解的基本概念:0、什么是双向端⼝inout端⼝ 顾名思义,双向端⼝既可以作为输⼊端⼝接收数据,也可以作为输出端⼝发出数据,它对数据的操作是双向的。

双向端⼝在综合时是以三态门的形式存在的,其典型结构如图所⽰。

1、三态门 在Xilinx的《XST User Guide》中给出了三态门的verilog描述1// Tristate Description Using Concurrent Assignment23// Combinatorial Always Block Can be Used too.45module v_three_st_2 (T, I, O);67input T, I;89output O;1011assign O = (~T) ? I: 1’bZ;1213endmodule 上述描述表明,当控制信号T=1时,管⼦被置为⾼阻态,输出O为⾼阻态;当控制信号T=0时,管⼦开通,输出O=输⼊I。

(跟控制信号T是⾼有效或低有效有关)2、⾼阻和悬空 三态门中有⼀个状态是⾼阻。

⾼阻,即可以认为是没有输出,作为输出端⼝⽽⾔,对下级电路没有任何影响。

悬空是针对输⼊端⼝来说的,也就是说没有接输⼊。

这也就意味着,实际上⾼阻和悬空是⼀个状态,在HDL语⾔⾥都表⽰为Z。

也就是说,⼀个输出端⼝在⾼阻态的时候,其状态是由于其相连的其他电路决定的,可以将其看作是输⼊。

双向端⼝⽤作输出时,就和平常⼀样,但双向端⼝作输⼊引脚时需要将此引脚置为⾼阻态,这样其电平就可以由外部输⼊信号决定了(这是⾼阻态的特性)。

在上述基本概念的基础上,讨论三个⽅⾯的问题:⼀、双向端⼝的实现原理 通过上⾯的基本概念应该已经清楚双向端⼝的实现原理了,只要搞清楚上⾯管⼦的开通状态与整个双向端⼝的对外特性之间的关系就⾏了。

Verilog双向口的使用和仿真

Verilog双向口的使用和仿真

Verilog inout 双向口使用和仿真2007-12-01 11:11芯片外部引脚很多都使用inout类型的,为的是节省管腿。

一般信号线用做总线等双向数据传输的时候就要用到INOUT类型了。

就是一个端口同时做输入和输出。

inout在具体实现上一般用三态门来实现。

三态门的第三个状态就是高阻'Z'。

当inout端口不输出时,将三态门置高阻。

这样信号就不会因为两端同时输出而出错了,更详细的内容可以搜索一下三态门tri-state的资料.1 使用inout类型数据,可以用如下写法:inout data_inout;input data_in;reg data_reg;//data_inout的映象寄存器reg link_data;assign data_inout=link_data?data_reg:1’bz;//link_data控制三态门//对于data_reg,可以通过组合逻辑或者时序逻辑根据data_in对其赋值.通过控制link_data的高低电平,从而设置data_inout是输出数据还是处于高阻态,如果处于高阻态,则此时当作输入端口使用.link_data可以通过相关电路来控制.2 编写测试模块时,对于inout类型的端口,需要定义成wire类型变量,而其它输入端口都定义成reg类型,这两者是有区别的.当上面例子中的data_inout用作输入时,需要赋值给data_inout,其余情况可以断开.此时可以用assign语句实现:assign data_inout=link?data_in_t:1’bz;其中的link ,data_in_t是reg类型变量,在测试模块中赋值.另外,可以设置一个输出端口观察data_inout用作输出的情况:Wire data_out;Assign data_out_t=(!link)?data_inout:1’bz;else,in RTLinout use in top module(PAD)dont use inout(tri) in sub module也就是说,在内部模块最好不要出现inout,如果确实需要,那么用两个port 实现,到顶层的时候再用三态实现。

HDL语言的INOUT双向端口仿真暨三态门仿真

HDL语言的INOUT双向端口仿真暨三态门仿真

HDL语言的INOUT双向端口仿真暨三态门仿真HDL语言的INOUT端口仿真暨三态门仿真------VHDL和V erilogHDL韦志恒**********************.cn关键词:inout双向端口三态门原理inout双向端口方针三态门仿真概述三态门是FPGA编程开发中经常遇到的一个问题。

一个典型的应用就是TI的DSP的EMIF总线。

针对HDL语言的三态门应用示例和仿真示例在网上很多,但是往往只讲述一种语言的,没有给予两种语言下三态门的一个综合评述,如讲述二者使用、仿真时的区别等。

特别是V erilogHDL语言下的三态门仿真,很多讲述都是语焉不详,包括使用Force语句等,这些使用人手工干预的仿真方法明显违背了EDA自动化的宗旨,是使用者对其仿真方法不明确的情况下的一种权益之计。

本文将使用一个DSP EMIF接口逻辑的例子,详细讲述:(0)什么叫做Z态?三态的晶体管级实现是怎样的?(1)VHDL语言下同步、异步三态门的实现和仿真;(2)V erilogHDL语言下同步、异步三态门的实现和仿真;(3)综述两种语言下仿真的要点。

一双向管脚INOUT与三态门介绍图1 一个典型的FPGA的管脚由图1可以看出,一个FPGA的管脚由一个输入缓冲器和一个三态输出缓冲器构成。

三态输出缓冲器,即三态门,是指逻辑门的输出除有高、低电平两种状态外,还有第三种状态——高阻状态的门电路。

高阻态相当于隔断状态(电阻很大,相当于开路)。

三态门都有一个EN控制使能端,来控制门电路的通断。

可以具备这三种状态的器件就叫做三态。

准确来讲,三态的高阻态(Z态)指的就是门的输出脚的两个驱动TTL或MOS管都处于截止状态时的输出状态。

参考图2、图3和图4有更详细的理解。

图2 TTL逻辑三态门的构成图当EN端接低电平时,反相器输出一个高电平给T1 ,使整个电路处于工作状态,这样,电路将按与非关系把A,B接受到的信号传送到输出端,使Y或为高电平,或为低电平。

verilog中双向端口inout地使用地心得

verilog中双向端口inout地使用地心得

verilog中双向端口inout的使用的心得见许多问这个问题的,总结一下,希望能对大家有点用处,如果有不对的地方,欢迎指出.芯片外部引脚很多都使用inout类型的,为的是节省管腿。

一般信号线用做总线等双向数据传输的时候就要用到INOUT类型了。

就是一个端口同时做输入和输出。

inout在具体实现上一般用三态门来实现。

三态门的第三个状态就是高阻'Z'。

当inout端口不输出时,将三态门置高阻。

这样信号就不会因为两端同时输出而出错了,更详细的内容可以搜索一下三态门tri-state的资料.1 使用inout类型数据,可以用如下写法:inout data_inout;input data_in;reg data_reg;//data_inout的映象寄存器reg link_data;assign data_inout=link_data?data_reg:1’bz;//link_data控制三态门//对于data_reg,可以通过组合逻辑或者时序逻辑根据data_in对其赋值.通过控制link_data的高低电平,从而设置data_inout是输出数据还是处于高阻态,如果处于高阻态,则此时当作输入端口使用.link_data可以通过相关电路来控制.2 编写测试模块时,对于inout类型的端口,需要定义成wire类型变量,而其它输入端口都定义成reg类型,这两者是有区别的.当上面例子中的data_inout用作输入时,需要赋值给data_inout,其余情况可以断开.此时可以用assign语句实现:assign data_inout=link?data_in_t:1’bz;其中的link ,data_in_t是reg类型变量,在测试模块中赋值.另外,可以设置一个输出端口观察data_inout用作输出的情况:Wire data_out;Assign data_out_t=(!link)?data_inout:1’bz;else,in RTLinout use in top module(PAD)dont use inout(tri) in sub module也就是说,在内部模块最好不要出现inout,如果确实需要,那么用两个port实现,到顶层的时候再用三态实现。

veriloghdl学习心得

veriloghdl学习心得

竭诚为您提供优质文档/双击可除veriloghdl学习心得篇一:Verilog学习心得Verilog学习心得因为Verilog是一种硬件描述语言,所以在写Verilog语言时,首先要有所要写的module在硬件上如何实现的概念,而不是去想编译器如何去解释这个module.比如在决定是否使用reg定义时,要问问自己物理上是不是真正存在这个register,如果是,它的clock是什么?D端是什么?Q端是什么?有没有清零和置位?同步还是异步?再比如上面讨论的三态输出问题,首先想到的应该是在register的输出后面加一个三态门,而不是如何才能让编译器知道要“赋值”给一个信号为三态。

同样,Verilog 中没有“编译”的概念,而只有综合的概念。

写硬件描述语言的目的是为了综合,所以说要想写的好就要对综合器有很深的了解,这样写出来的代码才有效率。

曾经接触过motorola苏州设计中心的一位资深工程师,他忠告了一句:就是用verilog描述电路的时候,一定要清楚它实现的电路,很多人只顾学习verilog语言,而不熟悉它实现的电路,这是设计不出好的电路来的.一般写verilogcode时,对整个硬件的结构应该是很清楚了,最好有详细的电路图画出,时序问题等都应该考虑清楚了。

可以看着图直接写code。

要知道,最初Verilog是为了实现仿真而发明的.不可综合的Verilog语句也是很重要的.因为在实际设计电路时,除了要实现一个可综合的module外,你还要知道它的外围电路是怎样的,以及我的这个电路与这些外围电路能否协调工作.这些外围电路就可以用不可综合的语句来实现而不必管它是如何实现的.因为它们可能已经实际存在了,我仅是用它来模拟的.所以,在写verilog的时候应该要先明确我是用它来仿真的还是综合的.要是用来综合的话,就必须要严格地使用可综合的语句,而且不同的写法可能产生的电路会有很大差别,这时就要懂一些verilog综合方法的知识.就像前面说的,脑子里要有一个硬件的概念.特别是当综合报错时,就要想一想我这种写法能不能用硬件来实现,verilog毕竟还不是c,很多写法是不可实现的.要是这个module仅是用来仿真的,就要灵活得多了,这时你大可不必太在意硬件实现.只要满足它的语法,实现你要的功能就行了.有网友说关于#10clk=~clk的问题,虽然这种语句是不可综合的,但是在做simulation和verification是常常用它在testbench中来产生一个clock信号。

双向既做输入又做输出的FPGA管脚

双向既做输入又做输出的FPGA管脚

双向信号既做输出又做输出- FPGA双向电路设计经验[导读] 2)双向信号既做输出又做输出上例是最简单的双向信号应用的特例.在实际的工程中,双向信号既做信号的输入,又做信号的输出,常见的数据总线就是这种操作在工程应用中,双向电路是设计者不得不面对的问题.在实际应用中,数据总线往往是双向的.如何正确处理数据总线是进行时序逻辑电路设计的基础.在程序设计过程中,关键技术在于:实体部分必须对端口属性进行申明,端口属性必须为Inout类型,在构造体需要对输出信号进行有条件的高阻控制.在双向电路的处理问题上,常用的处理方式有两种,在介绍双向电路的处理方式之前,先看看双向电路的基本格式:ENTITY Bidir_pin IS(Bidir : INOUT Std_logic;Oe, Clk, From_core : IN Std_logic;To_core : OUT Std_logic;……END Bidir_pin;ARCHITECTURE Behavior OF Bidir_pin ISBEGINBidir <= From_core WHEN Oe=‘1’ ELSE “ZZZZ”;To_core <= Bidir;___END Behavior;该程序揭示了双向电路的处理技巧,首先在实体部分Bidir属于双向信号,在端口定义时,端口属性为Inout类型,即把Bidir信号作为输入三态输出. 语句“Bidir <= From_core WHEN Oe=‘1’ ELSE “ZZZZ”;”表示Bidir信号三态输出,语句”To_core <= Bidir;”把Bidir信号作为输入信号.由此可见,双向电路在程序设计中,Didir输入当着普通的In类型,而在输出时,需要加一定的控制条件,三态输出.问题的关键在于:如何确定这个条件?1)双向信号作一个信号的输入,作另一信号的输出ENTITY Bidir ISPORT(Bidir : INOUT STD_LOGIC_VECTOR (7 DOWNTO 0);Oe, Clk : IN STD_LOGIC;From_core : IN STD_LOGIC_VECTOR (7 DOWNTO 0);To_core : OUT STD_LOGIC_VECTOR (7 DOWNTO 0));END Bidir;ARCHITECTURE Logic OF Bidir ISSIGNAL A : STD_LOGIC_VECTOR (7 DOWNTO 0);SIGNAL B : STD_LOGIC_VECTOR (7 DOWNTO 0);BEGINPROCESS (Clk)BEGINIF Clk = ''1'' AND Clk''EVENT THENA <= From_core;To_core <= B;END IF;END PROCESS;PROCESS (Oe, Bidir)BEGINIF( Oe = ''0'') THENBidir <= "ZZZZZZZZ";B <= Bidir;ELSEBidir <= A;B <= Bidir;END IF;END PROCESS;END Logic;这种设计方式叫做寄存双向信号的方法.本设计中Bidir为双向信号,From_core为数据输入端,To_core为数据输出端,Oe为三态输出使能,Clk为读写数据的时钟.在程序设计中,需要定义两个Signal A和B信号.A信号用于输入数据From_core的寄存器,B用于输出数据To_core的寄存器.采用寄存器的方法需要设计两个进程,一个进程把A, B信号在时钟的控制下负责端口的输入信号From_core和端口输出信号To_core的连接,这一步实现了寄存双向的功能.另外一个进程则负责信号 A,B和双向口之间的赋值关系.本设计只揭示了简单的双向信号操作方式,即Bidir既可以作为From_core的输出,又可以作为To_core的输入2)双向信号既做输出又做输出上例是最简单的双向信号应用的特例.在实际的工程中,双向信号既做信号的输入,又做信号的输出,常见的数据总线就是这种操作模式.Library IEEE;Use IEEE.STD_LOGIC_1164.All;Entity Dir_data IsPort(Clk : In STD_LOGIC;Rst : In STD_LOGIC;Rw : In STD_LOGIC;Address : In STD_LOGIC_VECTOR(1 Downto 0);Data : Inout STD_LOGIC_VECTOR(7 Downto 0));End Dir_data;Architecture Arc_dir Of Dir_data IsSignal Data_in : STD_LOGIC_VECTOR(7 Downto 0);Signal Data_out: STD_LOGIC_VECTOR(7 Downto 0);Signal Reg_a: STD_LOGIC_VECTOR(7 Downto 0);Signal Reg_b: STD_LOGIC_VECTOR(7 Downto 0);BeginData_in<=Data;D1:Process(Clk,Rst,Rw)BeginIf Rst=''1'' ThenReg_a<= (Others=>''0'');Reg_b<= (Others=>''0'');Elsif Clk''Event And Clk=''1'' Then If Rw=''1'' ThenIf Address="00" ThenReg_a<=Data_in;Elsif Address="01" ThenReg_b<=Data_in;Else Null;End If;Else Null;End If;Else Null;End If;End Process D1;D2:Process(Clk,Rw,Reg_a,Reg_b) BeginIf Clk''Event And Clk=''1'' ThenIf Rw=''0'' ThenIf Address="00" ThenData_out<=Reg_a;Elsif Address="01" ThenData_out<=Reg_b;Else Null;End If;Else Null;End If;Else Null;End If;End Process D2;Data<=Data_out When (Rw=''0'' And Address(1)=''0'') Else(Others=>''Z'');End Arc_dir;在程序设计中,首先需要定义Data_in, Data_out, Reg_a, Reg_b四个Signal,我们把Data_in叫做输入寄存器,它是从双向信号Data接收数据的寄存器,Data_out叫做输出寄存器,它是向双向信号Data发送信号的寄存器,Reg_a和Reg_b叫做操作寄存器,它们是在一定的时序控制下把Data_in数据送给Reg_a,Reg_b,在一定的时序控制下从Reg_a和Reg_b读出数据的.这样的处理方式必须有两个进程,因为在Architecture Arc_dir Of Dir_data Is和Begin之间定义了Data_in, Data_out, Reg_a, Reg_b四个Signal,它在同一进程内不支持既赋值,又调用,也就是说它不支持在D1进程中对信号Reg_a, Reg_b赋值,又在D1进程中又调用Reg_a, Reg_b.首先有语句”Data_in<=Data;”它表示输入寄存器无条件的接收双先信号的数据.在D1进程中,首先在Rst信号有效时,对操作寄存器Reg_a,和Reg_b进行清零操作,然后在时钟(Clk)的控制下,在写 (Rw)信号有效的情况下,对Reg_a, Reg_b寄存器在不同的地址控制下写入不同的Data_in值.在D2进程中,在时钟(Clk)的控制下,在读(Rw)信号有效的时候,把不同地址的 Reg_a, Reg_b的值送进Data_out中.最关键的是最后一句:“Data<=Data_out When (Rw=''0'' And Address(1)=''0'') Else (Others=>''Z'');”它表示双向信号的三态输出,而最最关键的是When后面的条件,如果条件限制太宽,就会错误占用双向信号总线,引起总线的误操作,如果条件限制太窄,输出寄存器的数据就不能够正确的送到数据总线上去,会引起数据的丢失.也就是说,只有正确的限制了When语句后面的条件,才能够把输出寄存器的数据正确地送到数据总线上去.仔细查看此条件,有如下的规律:When语句后的条件是操作寄存器写入输出寄存器的条件的公共条件.比如:Rw=’0’是操作寄存器的数据写入输出寄存器的读使能信号,Address(1)是地址线的公共部分.在实际工程应用中,需要设计者在分配地址总线的时候掌握一定的技巧,尽量从地址的低位到到高位,保证地址总线有更多位的公共部分,比如只对四个寄存器操作时,地址线分配为”100”,” 010”,”110”,”001”是不科学的,而”000”,”001”,”010”和”011”则是理想的.两者不同的是前者地址线没有公共部分,这样的设计无法用When语句对条件进行直接的控制,如果置之不理,由于列举不全,在逻辑综合时,电路会利用器件的乘积项和查找表的资源形成一个Latch, Latch不仅会把电路的时序变得复杂,而且电路存在潜在的危险性.虽然When语句后的条件不能够对条件进行直接的控制,但是可以使用枚举法一一把用到的地址线罗列出来,表示只有在这样的地址线的情况下才会用到数据总线,否则其他状态对数据总线送高阻,表示不占用数据总线.总而言之,双向信号是程序设计中尤其重要的基础,设计者在设计程序的时候,要尤其注意,何时会占用数据总线,何时不占用数据总线.。

Verilog中inout端口的使用方法

Verilog中inout端口的使用方法

Verilog中inout端口的使用方法Verilog中inout端口的使用方法(本文中所有Verilog描述仅为展示inout端口的用法,实际描述则需要更丰富的功能描述)Inout端口的使用在芯片中为了管脚复用,很多管脚都是双向的,既可以输入也可以输出。

在Verilog中即为inout型端口。

Inout端口的实现是使用三态门,如FPGA中的管脚复用部分:三态门的第三个状态是高阻态Z。

在实际电路中高阻态意味着响应的管脚悬空、断开。

当三态门的控制信号为真时,三态门导通;控制信号为假时,三态门的输出端是高阻态。

Verilog中的inout端口被综合为如下形式:Inout端口是一个很容易出错的地方,理解inout端口模型必须要抓住三点:inout端口不可能独立存在;作为输入必须有reg型缓冲(一个inout两个控制信号);相连的两个inout端口由一对信号交错控制;下面一一分析。

inout端口不可能独立存在:分析inout的端口特性,对于一个模块来说,inout端口既可以当做输入,又可以当做输出,那么,与inout端口相连的另一模块是什么情形呢?显然,另一模块也应该是inout端口,inout 端口不可能独立存在。

但是在实际编写Verilog代码的过程中,却常常忽略这一点,而仅仅是另一模块的一条输出线和一条输入线同时连接到inout端口上,乍看起来符合逻辑,实则不然。

以下图为例:图中的存储器Memory用RAM实现,无论CPU还是RAM都只有一组数据总线,而图中输入给Memory的有WriteData,从Memory输出的有MemData,这两组其实是一组数据总线,而实现此管脚复用功能的就是管脚复用。

在用Verilog描述的过程中,只考虑CPU的数据通路结构时,就容易忽略它的双向端口的具体实现,并非如图中一般,简简单单的与RAM 模块的inout端口相连。

所以,一定要注意到inout端口不能独立存在,用Verilog描述上图中的CPU模块时也要描述一个inout端口及相关逻辑。

Verilog HDL双向端口的使用

Verilog HDL双向端口的使用

互相学习 QQ:1033791679
module data(clk,z,din,dinout,dout);
input clk;
input z;
input[15:0] din;
inout[15:0] dinout;
output[15:0] dout;
reg[15:0] dout;
reg[15:0] din_t;
assign dinout=(!z) ? din_t : 16'bz;
always @(posedge clk)
begin
if(!z)
din_t<=din;
else
dout<=dinout;
end
endmodule
双向端口的使用:
V erilog HDL 语法的I/O 端口分为三类:input 、output 、inout 。

input 端口不能被定义成寄存器变量型,只能是线网型;output 端口信号可定义成寄存器型变量,并在always 块内可以被赋值使用;而inout 型双向端口信号不能被定义成reg 型变量,因此只能采用assign 赋值语句,不能再always 块内使用。

当Z=0时,上面的管子导通,数据从
(dinout)输出。

当Z=1时,上面的管子被置为高阻态,
数据不能从上面的管子输出,此时数据只
可以从下面的管子由外部端口(dinout )向
内部端口(dout )输入。

Z dout din。

verilog电路模块的端口描述

verilog电路模块的端口描述

verilog电路模块的端口描述Verilog电路模块的端口描述在Verilog语言中,模块是电路设计的基本单元。

模块定义了电路的功能和接口,其中端口描述了模块与外部环境的交互方式。

本文将围绕Verilog电路模块的端口描述展开讨论,介绍常见的端口类型和其功能。

一、输入端口(Input Port)输入端口用于接收外部信号输入到模块中,以供模块内部进行处理。

输入端口通常用于接收控制信号、数据信号等。

例如,一个简单的输入端口描述如下:input reg clk;input [7:0] data_in;在上述描述中,input关键字表示该端口为输入端口,reg关键字表示该端口是一个寄存器类型的信号。

clk是一个时钟信号,data_in 是一个8位的数据输入端口。

二、输出端口(Output Port)输出端口用于将模块内部处理的结果输出到外部环境中。

输出端口通常用于输出计算结果、状态信号等。

例如,一个简单的输出端口描述如下:output reg [7:0] data_out;在上述描述中,output关键字表示该端口为输出端口,reg关键字表示该端口是一个寄存器类型的信号。

data_out是一个8位的数据输出端口。

三、双向端口(Inout Port)双向端口可以实现输入和输出的双向传输。

它可以在一个时钟周期内既作为输入端口接收信号,又作为输出端口输出信号。

例如,一个简单的双向端口描述如下:inout [7:0] data_io;在上述描述中,inout关键字表示该端口为双向端口。

data_io是一个8位的双向数据端口,可以同时作为输入和输出。

四、时钟端口(Clock Port)时钟端口用于接收时钟信号,是数字电路设计中非常重要的一个端口。

时钟信号用于同步电路中的时序操作。

例如,一个简单的时钟端口描述如下:input reg clk;在上述描述中,input关键字表示该端口为输入端口,reg关键字表示该端口是一个寄存器类型的信号。

简谈FPGA-Verilog中inout端口使用方法

简谈FPGA-Verilog中inout端口使用方法

简谈FPGA/Verilog中inout端口使用方法
大家好,又到了每日学习的时间了,今天我们来聊一聊
FPGA/Verilog中inout端口使用方法。

 输入端口可以由wire/reg驱动,但输入端口只能是wire;输出端口可以使wire/reg类型,输出端口只能驱动wire;若输出端口在过程块中赋值则为reg型,若在过程块外赋值则为net型。

用关键词inout声明一个双向端口, inout端口不能声明为reg类型,只能是wire类型;输入和双向端口不能声明为寄存器类型。

 INOUT引脚:
 1.FPGA IO在做输入时,可以用作高阻态,这就是所说的高阻输入;
 2.FPGA IO在做输出时,则可以直接用来输入输出。

 芯片外部引脚很多都使用inout类型的,为的是节省管腿。

就是一个端口同时做输入和输出。

inout在具体实现上一般用三态门来实现。

三态门的第三个状态就是高阻’Z’。

当inout端口不输出时,将三态门置高阻。

这样信号就不会因为两端同时输出而出错了,更详细的内容可以搜索一下三态门tri-state的资料.
1 使用inout类型数据,可以用如下写法:。

verilog中双向端口inout的使用的心得全解

verilog中双向端口inout的使用的心得全解

verilog中双向端口inout的使用的心得见许多问这个问题的,总结一下,希望能对大家有点用处,如果有不对的地方,欢迎指出.芯片外部引脚很多都使用inout类型的,为的是节省管腿。

一般信号线用做总线等双向数据传输的时候就要用到INOUT类型了。

就是一个端口同时做输入和输出。

inout在具体实现上一般用三态门来实现。

三态门的第三个状态就是高阻'Z'。

当inout端口不输出时,将三态门置高阻。

这样信号就不会因为两端同时输出而出错了,更详细的内容可以搜索一下三态门tri-state的资料.1 使用inout类型数据,可以用如下写法:inout data_inout;input data_in;reg data_reg;//data_inout的映象寄存器reg link_data;assign data_inout=link_data?data_reg:1’bz;//link_data控制三态门//对于data_reg,可以通过组合逻辑或者时序逻辑根据data_in对其赋值.通过控制link_data 的高低电平,从而设置data_inout是输出数据还是处于高阻态,如果处于高阻态,则此时当作输入端口使用.link_data可以通过相关电路来控制.2 编写测试模块时,对于inout类型的端口,需要定义成wire类型变量,而其它输入端口都定义成reg类型,这两者是有区别的.当上面例子中的data_inout用作输入时,需要赋值给data_inout,其余情况可以断开.此时可以用assign语句实现:assign data_inout=link?data_in_t:1’bz;其中的link ,data_in_t 是reg类型变量,在测试模块中赋值.另外,可以设置一个输出端口观察data_inout用作输出的情况:Wire data_out;Assign data_out_t=(!link)?data_inout:1’bz;else,in RTLinout use in top module(PAD)dont use inout(tri) in sub module也就是说,在内部模块最好不要出现inout,如果确实需要,那么用两个port实现,到顶层的时候再用三态实现。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

verilog中双向端口inout的使用的心得见许多问这个问题的,总结一下,希望能对大家有点用处,如果有不对的地方,欢迎指出.芯片外部引脚很多都使用inout类型的,为的是节省管腿。

一般信号线用做总线等双向数据传输的时候就要用到INOUT类型了。

就是一个端口同时做输入和输出。

inout在具体实现上一般用三态门来实现。

三态门的第三个状态就是高阻'Z'。

当inout端口不输出时,将三态门置高阻。

这样信号就不会因为两端同时输出而出错了,更详细的内容可以搜索一下三态门tri-state的资料.1 使用inout类型数据,可以用如下写法:inout data_inout;input data_in;reg data_reg;//data_inout的映象寄存器reg link_data;assign data_inout=link_data?data_reg:1'bz;//link_data控制三态门//对于data_reg,可以通过组合逻辑或者时序逻辑根据data_in对其赋值.通过控制link_data的高低电平,从而设置data_inout是输出数据还是处于高阻态,如果处于高阻态,则此时当作输入端口使用.link_data可以通过相关电路来控制.2 编写测试模块时,对于inout类型的端口,需要定义成wire类型变量,而其它输入端口都定义成reg类型,这两者是有区别的.当上面例子中的data_inout用作输入时,需要赋值给data_inout,其余情况可以断开.此时可以用assign语句实现:assign data_inout=link?data_in_t:1'bz;其中的link ,data_in_t是reg类型变量,在测试模块中赋值.另外,可以设置一个输出端口观察data_inout用作输出的情况:Wire data_out;bz; ' Assign data_out_t=(!link)?data_inout:1in RTL,elseuse in top module(PAD) inoutdont use inout(tri) in sub module实现,到顶层的,如果确实需要,那么用两个port也就是说,在内部模块最好不要出现inout时候再用三态实现。

理由是:在非顶层模块用双向口的话,该双向口必然有它的上层跟它相连。

既然是双向口,则上层至少有一个输入口和一个输出口联到该双向口上,则发生两个内部输出单元连接到一起的情况出现,这样在综合时往往会出错。

芯片外部引脚很多都使用inout类型的,为的是节省管腿。

一般信号线用做总线等双向数据传输的时候就要用到INOUT类型了。

就是一个端口同时做输入和输出。

inout在具体实现上一般用三态门来实现。

三态门的第三个状态就是高阻'Z'。

当inout端口不输出时,将三态门置高阻。

这样信号就不会因为两端同时输出而出错了,更详细的内容可以搜索一下三态门tri-state的资料.1 使用inout类型数据,可以用如下写法:inout data_inout;input data_in;reg data_reg; //data_inout的映象寄存器reg link_data;assign data_inout=link_data?data_reg:1'bz; //link_data控制三态门//对于data_reg,可以通过组合逻辑或者时序逻辑根据data_in对其赋值.通过控制link_data的高低电平,从而设置data_inout是输出数据还是处于高阻态,如果处于高阻态,则此时当作输入端口使用.link_data可以通过相关电路来控制.2 编写测试模块时,对于inout类型的端口,需要定义成wire类型变量,而其它输入端口都定义成reg类型,这两者是有区别的.当上面例子中的data_inout用作输入时,需要赋值给data_inout,其余情况可以断开.此时可以用assign语句实现:assign data_inout=link?data_in_t:1'bz;其中的link ,data_in_t是reg类型变量,在测试模块中赋值.:用作输出的情况data_inout可以设置一个输出端口观察,另外.Wire data_out;Assign data_out_t=(!link)?data_inout:1'bz;else,in RTLinout use in top module(PAD)dont use inout(tri) in sub module也就是说,在内部模块最好不要出现inout,如果确实需要,那么用两个port实现,到顶层的时候再用三态实现。

理由是:在非顶层模块用双向口的话,该双向口必然有它的上层跟它相连。

既然是双向口,则上层至少有一个输入口和一个输出口联到该双向口上,则发生两个内部输出单元连接到一起的情况出现,这样在综合时往往会出错。

对双向口,我们可以将其理解为2个分量:一个输入分量,一个输出分量。

另外还需要一个控制信号控制输出分量何时输出。

此时,我们就可以很容易地对双向端口建模。

例子:CODE:module dual_port (....inout_pin,....);inout inout_pin;wire inout_pin;wire input_of_inout;wire output_of_inout;wire out_en;assign input_of_inout = inout_pin;assign inout_pin = out_en ? output_of_inout : 高阻;endmodule可见,此时input_of_inout和output_of_inout就可以当作普通信号使用了。

在仿真的时候,需要注意双向口的处理。

如果是直接与另外一个模块的双向口连接,那么只要保证一个模块在输出的时候,另外一个模块没有输出(处于高阻态)就可以了。

如果是在ModelSim中作为单独的模块仿真,那么在模块输出的时候,不能使用force命令将其设为高阻态,而是使用release命令将总线释放掉很多初学者在写testbench进行仿真和验证的时候,被inout双向口难住了。

仿真器老是提示错误不能进行。

下面是我个人对inout端口写testbench仿真的一些总结,并举例进行说明。

在这里先要说明一下inout口在testbench中要定义为wire型变量。

先假设有一源代码为:module xx(data_inout , ........);inout data_inout;........................assign data_inout=(! link)?datareg:1'bz;endmodule方法一:使用相反控制信号inout口,等于两个模块之间用inout双向口互连。

这种方法要注意assign 语句只能放在initial和always块内。

module test();wire data_inout;reg data_reg;reg link;initial begin..........endassign data_inout=link?data_reg:1'bz;endmodule方法二:使用force和release语句,但这种方法不能准确反映双向端口的信号变化,但这种方法可以反在块内。

module test();wire data_inout;reg data_reg;reg link;#xx; //延时force data_inout=1'bx; //强制作为输入端口...............#xx;release data_inout; //释放输入端口endmodule很多读者反映仿真双向端口的时候遇到困难,这里介绍一下双向端口的仿真方法。

一个典型的双向端口如图1所示。

其中inner_port与芯片内部其他逻辑相连,outer_port为芯片外部管脚,out_en 用于控制双向端口的方向,out_en为1时,端口为输出方向,out_en为0时,端口为输入方向。

用Verilog语言描述如下:module bidirection_io(inner_port,out_en,outer_port);input out_en;inout[7:0] inner_port;inout[7:0] outer_port;assign outer_port=(out_en==1)?inner_port:8'hzz;assign inner_port=(out_en==0)?outer_port:8'hzz;endmodule用VHDL语言描述双向端口如下:library ieee;use IEEE.STD_LOGIC_1164.ALL;entity bidirection_io isport ( inner_port : inout std_logic_vector(7 downto 0);out_en : in std_logic;outer_port : inout std_logic_vector(7 downto 0) );end bidirection_io;architecture behavioral of bidirection_io isbeginouter_port<=inner_port when out_en='1' else (OTHERS=>'Z');inner_port<=outer_port when out_en='0' else (OTHERS=>'Z');end behavioral;仿真时需要验证双向端口能正确输出数据,以及正确读入数据,因此需要驱动out_en端口,当out_en端口为1时,testbench驱动inner_port端口,然后检查outer_port端口输出的数据是否正确;当out_en端口为0时,testbench驱动outer_port端口,然后检查inner_port端口读入的数据是否正确。

由于inner_port和outer_port端口都是双向端口(在VHDL和Verilog语言中都用inout 定义),因此驱动方法与单向端口有所不同。

验证该双向端口的testbench结构如图2所示。

这是一个self-checking testbench,可以自动检查仿真结果是否正确,并在Modelsim控制台上打印出提示信息。

相关文档
最新文档