文章目录

  • 前言
  • 原语的使用
    • 什么是原语
    • 需要使用原语的情况
      • 时钟相关原语
      • 差分输入、输出原语
      • 接口相关原语
    • 用原语表示IP核的好处
    • UDP 简介

前言

本文节选自《FPGA之道》。

原语的使用

什么是原语

原语,英文名称primitive,是FPGA软件集成开发环境所提供的一系列底层逻辑功能单元。由于是底层逻辑功能单元,所以它们往往跟目标FPGA芯片以及芯片厂商紧密相关,因此不同厂商、不同器件的原语往往不能通用。当编译器对我们的HDL代码进行编译时,其中间环节的一些输出往往就是由原语组成的逻辑网表。因此,原语往往是不参与综合过程的,而使用原语描述的逻辑往往也不会被综合工具所优化。例如,Xilinx公司的ISE软件集成开发环境中的unisims库中定义了所有用于综合的原语,而simprims库中则定义了所有用于实现的原语。需要注意的是,如果我们去ISE安装目录下的verilog\src\unisims或verilog\src\simprims文件夹下去看这些原语的代码,可以发现其实这些并不是真正的原语,而是在原语的基础上又封装了一层,不过人们常常将它们也泛称为原语。
例如,如下为unisims库中一个二输入与门的定义:

`timescale  1 ps / 1 ps
module AND2 (O, I0, I1);output O;input  I0, I1;and A1 (O, I0, I1);
endmodule

至于其中的and是不是真正的原语,则需要找进一步的定义。
而simprims库由于涉及到了实现,因此在建模的时候就需要加入时序信息,例如,如下为simprims库中一个二输入与门的定义:

`timescale 1 ps/1 ps
module X_AND2 (O, I0, I1);parameter LOC = "UNPLACED";output O;input I0, I1;and (O, I0, I1);specify
(I0 => O) = (0:0:0, 0:0:0);
(I1 => O) = (0:0:0, 0:0:0);
specparam PATHPULSE$ = 0;endspecify
endmodule

可见,这里面用到了我们在【本篇->编程语法->Verilog基本语法->Verilog的并行语句->Verilog模块说明语句】小节中介绍的specify语法,来在原语的基础上,对该功能模块进行时序建模,这应该也是为什么库里面不提供直接的原语调用的原因之一。不过上述定义中的时间延迟信息均为0,这是由于不同系列器件或不同等级器件中的延迟不相等,所以这些参数会在编译的时候根据具体目标器件进行替换。
再多观察一些库中的基本逻辑单元,可以发现其中一些是带有真正的原语定义的,例如simprims库下的一个两输入查找表的定义:

`timescale 1 ps/1 ps
module X_LUT2 (O, ADR0, ADR1);parameter INIT = 4'h0;parameter LOC = "UNPLACED";output O;input ADR0, ADR1;wire out, a0, a1;buf b0 (a0, ADR0);buf b1 (a1, ADR1);x_lut2_mux4 (O, INIT[3], INIT[2], INIT[1], INIT[0], a1, a0);specify(ADR0 => O) = (0:0:0, 0:0:0);(ADR1 => O) = (0:0:0, 0:0:0);specparam PATHPULSE$ = 0;endspecify
endmoduleprimitive x_lut2_mux4 (o, d3, d2, d1, d0, s1, s0);output o;input d3, d2, d1, d0;input s1, s0;table// d3  d2  d1  d0  s1  s0 : o;?   ?   ?   1   0   0  : 1;?   ?   ?   0   0   0  : 0;?   ?   1   ?   0   1  : 1;?   ?   0   ?   0   1  : 0;?   1   ?   ?   1   0  : 1;?   0   ?   ?   1   0  : 0;1   ?   ?   ?   1   1  : 1;0   ?   ?   ?   1   1  : 0;?   ?   0   0   0   x  : 0;?   ?   1   1   0   x  : 1;0   0   ?   ?   1   x  : 0;1   1   ?   ?   1   x  : 1;?   0   ?   0   x   0  : 0;?   1   ?   1   x   0  : 1;0   ?   0   ?   x   1  : 0;1   ?   1   ?   x   1  : 1;0   0   0   0   x   x  : 0;1   1   1   1   x   x  : 1;endtable
endprimitive

上述定义中,primitive关键字定义的就是真正的原语,我们将在后续的【UDP简介】小节中具体介绍primitive的语法。

需要使用原语的情况

一般来说,在进行HDL代码编写时,不需要直接或间接的进行原语调用,因为随着FPGA设计规模的越来越庞杂,人脑应该集中于抽象层次较高的工作中去,而将这些具体实现细节交给编译器来完成。不过有些时候,原语或者库中底层模块的调用还是十分必要的。例如,在Xilinx的ISE工具中,可以通过edit->Language Templates菜单调出语法模板,在其中的VHDL或Verilog子菜单下,都可以看到一个Device Primitive Instantiation子项,里面列举出了所有我们在Xilinx FPGA平台上开发项目时可能会用到的原语例化方式。举例简介如下:

时钟相关原语

如果时钟信号不是由FPGA芯片的专用时钟pin(或pad)引入FPGA的,那么它通常就需要在FPGA内部被显式的连接到时钟树资源上,否则,直接使用这种不经过时钟树的时钟信号,会给FPGA设计的时序带来非常麻烦的问题,进而导致逻辑行为失败。
可是HDL代码仅仅描述功能,无法向编译器表达“希望将某一时钟信号连接到时钟树资源”这样的一层意思,那么此时,就需要使用类似BUFG这样的库里提供的底层模块来进行指示。例如:

-- VHDL example
singal innerclk, gclk : std_logic;onToGlobalClockTree: BUFG
port map (I => innerclk,  -- in  std_logicO => gclk);    -- out std_logicprocess(gclk)
begin……
end process;
// Verilog example
wire innerclk, gclk;BUFG onToGlobalClockTree(.I (innerclk),.O (gclk));always@(posedge gclk)
begin……
end

那么,像上例这样,通过显式调用BUFG这样一个库中的底层模块,就可以告诉编译器,我们希望将innerclk信号引入全局时钟树,而其经过全局时钟树后的名字就改为gclk。后续HDL代码便可以放心的基于gclk编写逻辑。需要说明的是,直接从全局时钟pin(或pad)引入的时钟信号,对于xilinx的FPGA芯片来说,实际上是通过IBUFG+BUFG这样的组合直接连接到全局时钟树上的,只不过此时我们不需要显式例化这两个原语。
类似的时钟相关原语还有BUFR、BUFIO等,它们分别对应区域时钟树和IO时钟树资源,这里就不再赘述。

差分输入、输出原语

FPGA的接口具有单端和差分两种形式,同样,HDL代码只能描述功能,无法表达“某两个pin(或pad)脚互为一个差分对”这样的一层意思。那么此时,就需要使用类似IBUFDS、IBUFGDS、OBUFDS这样的库里提供的底层模块或原语来进行指示。例如:

-- VHDL exampleclklvds : IBUFGDSgeneric map (DIFF_TERM => TRUE, IBUF_DELAY_VALUE => "0", IOSTANDARD => "DEFAULT")port map (I  => LVDSClk_p,   IB => LVDSClk_n,    O  => sclk);
onToGlobalClockTree: BUFGport map (I => sclk,  -- in  std_logicO => gclk);    -- out std_logic
// Verilog example
IBUFGDS clklvds(.I (LVDSClk_p),.IB (LVDSClk_n),.O (sclk));
BUFG onToGlobalClockTree(.I (sclk),.O (gclk));

上述代码通过调用原语IBUFGDS,表达了“LVDSClk_p、LVDSClk_n是一对差分时钟输入信号且它们是经由FPGA芯片的专用差分时钟输入管脚引入FPGA芯片”的意思,这样编译器就会采用接口资源中的专用差分时钟输入电路来接入这对时钟输入信号,并转换成为一个单端时钟sclk,紧接着,在通过一个BUFG原语将其引致全局时钟网络,这样全局时钟网络输出的gclk就可以作为后续内部逻辑的时钟源。

接口相关原语

当需要使用接口资源中的寄存器来实现高速数据采集时,除了使用【本篇->编程思路->代码中的约束信息->HDL中的常用约束示例->寄存器的相关约束】小节中介绍的方法外,如果直接调用相关的原语,编译器便会利用接口资源中的寄存器来做事情。例如,使用ODDR、IDDR、IDDR2CLK、ISERDES、OSERDES等原语后,编译器便会利用接口资源的寄存器来实现相关接口功能,这样便能达到比较高的性能。例如:

-- VHDL exampleis0 : ISERDES_NODELAYgeneric map (BITSLIP_ENABLE => TRUE, -- TRUE/FALSE to enable bitslip controller-- Must be "FALSE" in interface type is "MEMORY" DATA_RATE => "DDR", -- Specify data rate of "DDR" or "SDR" DATA_WIDTH => 6, -- Specify data width - -- NETWORKING SDR: 2, 3, 4, 5, 6, 7, 8 : DDR 4, 6, 8, 10-- MEMORY SDR N/A : DDR 4INTERFACE_TYPE => "NETWORKING", -- Use model - "MEMORY" or "NETWORKING" NUM_CE => 2, -- Define number or clock enables to an integer of 1 or 2SERDES_MODE => "MASTER") --Set SERDES mode to "MASTER" or "SLAVE" port map (Q1 => data0Line(0),     -- 1-bit registered SERDES outputQ2 => data0Line(1),    -- 1-bit registered SERDES outputQ3 => data0Line(2),    -- 1-bit registered SERDES outputQ4 => data0Line(3),    -- 1-bit registered SERDES outputQ5 => data0Line(4),    -- 1-bit registered SERDES outputQ6 => data0Line(5),    -- 1-bit registered SERDES outputSHIFTOUT1 => open,     -- 1-bit cascade Master/Slave outputSHIFTOUT2 => open,      -- 1-bit cascade Master/Slave outputBITSLIP => '0',           -- 1-bit Bitslip enable inputCE1 => '1',              -- 1-bit clock enable inputCE2 => '1',            -- 1-bit clock enable inputCLK => clkFast,          -- 1-bit master clock inputCLKB => clkFastInvert,   -- 1-bit secondary clock input for DATA_RATE=DDRCLKDIV => clkSlow,     -- 1-bit divided clock inputD => din,               -- 1-bit data input, connects to IODELAY or input bufferOCLK => '0',              -- 1-bit fast output clock inputRST => rst,         -- 1-bit asynchronous reset inputSHIFTIN1 => '0',         -- 1-bit cascade Master/Slave inputSHIFTIN2 => '0'        -- 1-bit cascade Master/Slave input);
// Verilog example
ISERDES_NODELAY #(.BITSLIP_ENABLE("FALSE"),  // "TRUE"/"FALSE" to enable bitslip controller // Must be "FALSE" if INTERFACE_TYPE set to "MEMORY" .DATA_RATE("DDR"), // Specify data rate of "DDR" or "SDR" .DATA_WIDTH(4),      // Specify data width - // NETWORKING SDR: 2, 3, 4, 5, 6, 7, 8 : DDR 4, 6, 8, 10// MEMORY SDR N/A : DDR 4.INTERFACE_TYPE("MEMORY"), // Use model - "MEMORY" or "NETWORKING" .NUM_CE(2),           // Number of clock enables used, 1 or 2.SERDES_MODE("MASTER") // Set SERDES mode to "MASTER" or "SLAVE"
) is0 (.Q1(data0Line[0]),       // 1-bit registered SERDES output.Q2(data0Line[1]),     // 1-bit registered SERDES output.Q3(data0Line[2]),     // 1-bit registered SERDES output.Q4(data0Line[3]),     // 1-bit registered SERDES output.Q5(data0Line[4]),     // 1-bit registered SERDES output.Q6(data0Line[5]),     // 1-bit registered SERDES output.SHIFTOUT1(open),  // 1-bit cascade Master/Slave output.SHIFTOUT2(open),   // 1-bit cascade Master/Slave output.BITSLIP(1'b0),        // 1-bit Bitslip enable input.CE1(1'b1),               // 1-bit clock enable input.CE2(1'b1),             // 1-bit clock enable input.CLK(clkFast),           // 1-bit master clock input.CLKB(clkFastInvert),    // 1-bit secondary clock input for DATA_RATE=DDR.CLKDIV(clkSlow),      // 1-bit divided clock input.D(din),                // 1-bit data input, connects to IODELAY or input buffer.OCLK('0'),           // 1-bit fast output clock input.RST(rst),             // 1-bit asynchronous reset input.SHIFTIN1(1'b0),       // 1-bit cascade Master/Slave input.SHIFTIN2(1'b0)     // 1-bit cascade Master/Slave input
);

使用上述原语后,编译器便会利用接口资源中的寄存器实现一个针对输入接口的高性能1:6串并转换器。当然了,为了保证串并处理的成功,仅仅使用ISERDES原语还远远不够,时钟信号也必须按照要求来处理,具体的要求大家可以去查阅Xilinx公司相应器件的用户手册。

用原语表示IP核的好处

其实,FPGA软件集成开发环境中提供的IP核基本上都具有原语的表示形式。相比于调用IP核智能生成器对IP核进行配置、生成、例化等一系列过程,直接通过原语调用显得要简便得多,当然了,前提是你要对IP核的各个属性和参数配置比较熟悉。尤其是碰到版本升级或者整体细微修改这样的情况,如果采用在HDL中调用原语的方式,将会使修改的工作量大大降低。
例如,使用原语例化一个锁相环如下:

-- VHDL example
BUFG_COut0 : BUFG
port map (O => clkOut0,     -- Clock buffer outputI => pllClkOut0      -- Clock buffer input
);BUFG_FB : BUFG
port map (O => feedBackG,     -- Clock buffer outputI => feedBack      -- Clock buffer input
);PLL_ADV_inst : PLL_ADV
generic map (BANDWIDTH => "OPTIMIZED",    -- "HIGH", "LOW" or "OPTIMIZED" CLKFBOUT_MULT => 7,           -- Multiplication factor for all output clocksCLKFBOUT_PHASE => 0.0,        -- Phase shift (degrees) of all output clocksCLKIN1_PERIOD => 16.67,        -- Clock period (ns) of input clock on CLKIN1CLKIN2_PERIOD => 10.00,        -- Clock period (ns) of input clock on CLKIN2CLKOUT0_DIVIDE => 1,           -- Division factor for CLKOUT0  (1 to 128)CLKOUT0_DUTY_CYCLE => 0.5,    -- Duty cycle for CLKOUT0 (0.01 to 0.99)CLKOUT0_PHASE => 45.0,          -- Phase shift (degrees) for CLKOUT0 (0.0 to 360.0)CLKOUT1_DIVIDE => 1,         -- Division factor for CLKOUT1 (1 to 128)CLKOUT1_DUTY_CYCLE => 0.5,     -- Duty cycle for CLKOUT1 (0.01 to 0.99)CLKOUT1_PHASE => 0.0,       -- Phase shift (degrees) for CLKOUT1 (0.0 to 360.0)CLKOUT2_DIVIDE => 1,         -- Division factor for CLKOUT2 (1 to 128)CLKOUT2_DUTY_CYCLE => 0.5,     -- Duty cycle for CLKOUT2 (0.01 to 0.99)CLKOUT2_PHASE => 0.0,       -- Phase shift (degrees) for CLKOUT2 (0.0 to 360.0)CLKOUT3_DIVIDE => 1,         -- Division factor for CLKOUT3 (1 to 128)CLKOUT3_DUTY_CYCLE => 0.5,     -- Duty cycle for CLKOUT3 (0.01 to 0.99)CLKOUT3_PHASE => 0.0,       -- Phase shift (degrees) for CLKOUT3 (0.0 to 360.0)CLKOUT4_DIVIDE => 1,         -- Division factor for CLKOUT4 (1 to 128)CLKOUT4_DUTY_CYCLE => 0.5,     -- Duty cycle for CLKOUT4 (0.01 to 0.99)CLKOUT4_PHASE => 0.0,       -- Phase shift (degrees) for CLKOUT4 (0.0 to 360.0)CLKOUT5_DIVIDE => 1,         -- Division factor for CLKOUT5 (1 to 128)CLKOUT5_DUTY_CYCLE => 0.5,     -- Duty cycle for CLKOUT5 (0.01 to 0.99)CLKOUT5_PHASE => 0.0,       -- Phase shift (degrees) for CLKOUT5 (0.0 to 360.0)COMPENSATION => "SYSTEM_SYNCHRONOUS",  -- "SYSTEM_SYNCHRNOUS", --"SOURCE_SYNCHRNOUS", "INTERNAL", -- "EXTERNAL", "DCM2PLL", "PLL2DCM" DIVCLK_DIVIDE => 1,              -- Division factor for all clocks (1 to 52)EN_REL => FALSE,                 -- Enable release (PMCD mode only)PLL_PMCD_MODE => FALSE,   -- PMCD Mode, TRUE/FASLEREF_JITTER => 0.000,            -- Input reference jitter (0.000 to 0.999 UI%)RST_DEASSERT_CLK => "CLKIN1")   -- In PMCD mode, clock to synchronize RST releaseport map (CLKFBDCM => open,        -- Output feedback signal used when PLL feeds a DCMCLKFBOUT => feedBack,        -- General output feedback signalCLKOUT0 => pllClkOut0,     -- One of six general clock output signalsCLKOUT1 => open,          -- One of six general clock output signalsCLKOUT2 => open,          -- One of six general clock output signalsCLKOUT3 => open,          -- One of six general clock output signalsCLKOUT4 => open,          -- One of six general clock output signalsCLKOUT5 => open,          -- One of six general clock output signalsCLKOUTDCM0 => open,   -- One of six clock outputs to connect to the DCMCLKOUTDCM1 => open,    -- One of six clock outputs to connect to the DCMCLKOUTDCM2 => open,    -- One of six clock outputs to connect to the DCMCLKOUTDCM3 => open,    -- One of six clock outputs to connect to the DCMCLKOUTDCM4 => open,    -- One of six clock outputs to connect to the DCMCLKOUTDCM5 => open,    -- One of six clock outputs to connect to the DCMDO => open,            -- Dynamic reconfig data output (16-bits)DRDY => open,          -- Dynamic reconfig ready outputLOCKED => locked,       -- Active high PLL lock signalCLKFBIN => feedBackG,     -- Clock feedback inputCLKIN1 => clkIn,             -- Primary clock inputCLKIN2 => '0',              -- Secondary clock inputCLKINSEL => '1',              -- Selects CLKIN1 or CLKIN2DADDR => "00000",          -- Dynamic reconfig address input (5-bits)DCLK => '0',                -- Dynamic reconfig clock inputDEN => '0',                -- Dynamic reconfig enable inputDI => "0000000000000000", -- Dynamic reconfig data input (16-bits)DWE => '0',               -- Dynamic reconfig write enable inputREL => '0',                 -- Clock release input (PMCD mode only)RST => rst                   -- Asynchronous PLL reset
);
// Verilog example
BUFG BUFG_COut0(.I (pllClkOut0), .O (clkOut0));
BUFG BUFG_FB(.I (feedBack), .O (feedBackG));
PLL_ADV #(.BANDWIDTH("OPTIMIZED"),        // "HIGH", "LOW" or "OPTIMIZED" .CLKFBOUT_MULT(7),            // Multiplication factor for all output clocks.CLKFBOUT_PHASE(0.0),         // Phase shift (degrees) of all output clocks.CLKIN1_PERIOD(16.67),         // Clock period (ns) of input clock on CLKIN1.CLKIN2_PERIOD(10.00),         // Clock period (ns) of input clock on CLKIN2.CLKOUT0_DIVIDE(1),        // Division factor for CLKOUT0 (1 to 128).CLKOUT0_DUTY_CYCLE(0.5),  // Duty cycle for CLKOUT0 (0.01 to 0.99).CLKOUT0_PHASE(45.0),       // Phase shift (degrees) for CLKOUT0 (0.0 to 360.0).CLKOUT1_DIVIDE(1),          // Division factor for CLKOUT1 (1 to 128).CLKOUT1_DUTY_CYCLE(0.5),  // Duty cycle for CLKOUT1 (0.01 to 0.99).CLKOUT1_PHASE(0.0),        // Phase shift (degrees) for CLKOUT1 (0.0 to 360.0).CLKOUT2_DIVIDE(1),          // Division factor for CLKOUT2 (1 to 128).CLKOUT2_DUTY_CYCLE(0.5),  // Duty cycle for CLKOUT2 (0.01 to 0.99).CLKOUT2_PHASE(0.0),        // Phase shift (degrees) for CLKOUT2 (0.0 to 360.0).CLKOUT3_DIVIDE(1),          // Division factor for CLKOUT3 (1 to 128).CLKOUT3_DUTY_CYCLE(0.5),  // Duty cycle for CLKOUT3 (0.01 to 0.99).CLKOUT3_PHASE(0.0),        // Phase shift (degrees) for CLKOUT3 (0.0 to 360.0).CLKOUT4_DIVIDE(1),          // Division factor for CLKOUT4 (1 to 128).CLKOUT4_DUTY_CYCLE(0.5),  // Duty cycle for CLKOUT4 (0.01 to 0.99).CLKOUT4_PHASE(0.0),        // Phase shift (degrees) for CLKOUT4 (0.0 to 360.0).CLKOUT5_DIVIDE(1),          // Division factor for CLKOUT5 (1 to 128).CLKOUT5_DUTY_CYCLE(0.5),  // Duty cycle for CLKOUT5 (0.01 to 0.99).CLKOUT5_PHASE(0.0),        // Phase shift (degrees) for CLKOUT5 (0.0 to 360.0).COMPENSATION("SYSTEM_SYNCHRONOUS"), // "SYSTEM_SYNCHRONOUS", // "SOURCE_SYNCHRONOUS", "INTERNAL", // "EXTERNAL", "DCM2PLL", "PLL2DCM" .DIVCLK_DIVIDE(1),              // Division factor for all clocks (1 to 52).EN_REL("FALSE"),              // Enable release (PMCD mode only).PLL_PMCD_MODE("FALSE"),    // PMCD Mode, TRUE/FASLE.REF_JITTER(0.100),             // Input reference jitter (0.000 to 0.999 UI%).RST_DEASSERT_CLK("CLKIN1")     // In PMCD mode, clock to synchronize RST release
) PLL_ADV_inst (.CLKFBDCM(open),            // Output feedback signal used when PLL feeds a DCM.CLKFBOUT(feedBack),      // General output feedback signal.CLKOUT0(pllClkOut0),     // One of six general clock output signals.CLKOUT1(open),           // One of six general clock output signals.CLKOUT2(open),           // One of six general clock output signals.CLKOUT3(open),           // One of six general clock output signals.CLKOUT4(open),           // One of six general clock output signals.CLKOUT5(open),           // One of six general clock output signals.CLKOUTDCM0(open),        // One of six clock outputs to connect to the DCM.CLKOUTDCM1(open),         // One of six clock outputs to connect to the DCM.CLKOUTDCM2(open),         // One of six clock outputs to connect to the DCM.CLKOUTDCM3(open),         // One of six clock outputs to connect to the DCM.CLKOUTDCM4(open),         // One of six clock outputs to connect to the DCM.CLKOUTDCM5(open),         // One of six clock outputs to connect to the DCM.DO(open),                 // Dynamic reconfig data output (16-bits).DRDY(open),               // Dynamic reconfig ready output.LOCKED(locked),          // Active high PLL lock signal.CLKFBIN(feedBackG),        // Clock feedback input.CLKIN1(clkIn),              // Primary clock input.CLKIN2(1'b0),           // Secondary clock input.CLKINSEL(1'b1),           // Selects '1' = CLKIN1, '0' = CLKIN2.DADDR(5'b0),               // Dynamic reconfig address input (5-bits).DCLK(1'b0),              // Dynamic reconfig clock input.DEN(1'b0),                // Dynamic reconfig enable input.DI(16'b0),                // Dynamic reconfig data input (16-bits).DWE(1'b0),                // Dynamic reconfig write enable input.REL(1'b0),                  // Clock release input (PMCD mode only).RST(rst)                    // Asynchronous PLL reset
);

如果今后我们需要将锁相环的倍频系数改为5的话,直接修改CLKFBOUT_MULT属性的值即可,非常方便。

UDP 简介

这里的UDP不是网络协议,而是用户自定义原语的意思,英文全称为User Defined Primitive。对于FPGA开发者来说的,其实没有必要去写什么自定义原语,因为FPGA芯片底层的硬件都已经明确,但对于从事ASIC芯片开发的工程师来说会比较有用。因此这里,我们仅简单介绍一下Verilog中关于UDP的语法如下:

primitive <primitive_name>(<output_port_name>, <input_port_name_list>);<输出端口类型说明>;
<输入端口类型说明>;
<输出端寄存器变量说明>;
<原语初始状态说明>;
table<table element 1>;<table element 2>;……<table element n>;
endtableendprimitive

上述即为UDP的语法,table的内容其实就是该原语的真值表。关于UDP有一些注意事项,诸如:每个UDP只能有一个输出;最多有10个输入,但尽量控制在5个以内,否则table将会巨大无比;端口只能是标量,不能是向量,即均为1bit宽的;不支持高阻(z)逻辑;不能被综合等等。以下即为一个使用UDP语法描述的2输入1输出多路复用器的原语例子:

primitive mux2in1(dOut, dIn1, dIn2, sel);
output dOut;
input dIn1, dIn2, sel;table//dIn1   dIn2        sel :   dOut0       ?       0   :   01      ?       0   :   1?      0       1   :   0?      1       1   :   1endtable
endprimitive

其中,“?”号表示该输入的值不需要关心。

FPGA之道(68)原语的使用相关推荐

  1. FPGA之道(80)静态时序分析(六)常用时序约束介绍(基于ISE的UCF文件语法)

    文章目录 前言 常用时序约束介绍 时序环境约束 分组时序约束 TNM TNM_NET TIMEGRP 常用时序约束 周期约束 输入时钟周期约束 内部时钟周期约束 关联时钟周期约束 差分时钟周期约束 输 ...

  2. FPGA之道(58)关于外界接口的编程思路

    文章目录 前言 关于外界接口的编程思路 按传递方向分类 输入接口 输出接口 双向接口 原理简介 工作模式 主从模式 对等模式 简单示例 按电气特性分类 单端接口 差分接口 无线接口 按功能特性分类 时 ...

  3. FPGA之道(47)时钟及时钟域

    文章目录 前言 时钟及时钟域 时钟,时序逻辑的心跳 时钟信号基本特征 时钟信号基本特征参数介绍 如何区分时钟和数据 时钟信号的分类 按来源分 外部时钟 再生时钟 门控时钟 行波时钟 按波形分 连续时钟 ...

  4. FPGA之道(41)HDL的三种描述方式

    文章目录 前言 三种描述方式 结构化描述方式 数据流描述方式 行为级描述方式 前言 常编写Verilog代码的就会知道,我们对于某一功能的描述,可以通过门电路来描述,也可以直接描述其功能等,这就牵扯到 ...

  5. FPGA之道(35)Verilog中的并行与串行语句

    文章目录 前言 Verilog的并行语句 Verilog连续赋值语句 普通连续赋值语句 条件连续赋值语句 Verilog程序块语句 沿事件 纯组合always 纯时序always 具有同步复位的alw ...

  6. FPGA之道(30)编写自己的vhdl库文件

    文章目录 前言 编写自己的vhdl库文件 Work库 记录数据类型 子程序介绍 函数 过程 子程序使用总结 程序包 自定义程序包范例 前言 本文节选自<FPGA之道>来一起学习下高阶Ver ...

  7. FPGA之道(22)VHDL基本程序框架

    文章目录 前言 VHDL基本程序框架 VHDL基本程序框架模板 Library Entity Architecture 声明与定义部分 语句部分 VHDL基本程序框架范例 VHDL注释语法 前言 VH ...

  8. FPGA之道(84)功能仿真之Verilog Test Fixture

    文章目录 前言 Verilog Test Fixture "Hello world"之Verilog Test Fixture 待仿真设计 仿真示例 示例详解 仿真结果 继承描述语 ...

  9. FPGA之道(83)功能仿真之仿真语法(Graphic Waveform )

    文章目录 前言 仿真语法 Graphic Waveform 数字波形简介 从实际到仿真 实际系统检测 软件仿真模拟 "Hello world"之Graphic Waveform 待 ...

最新文章

  1. ps用法linux,在linux上使用ps(转载)
  2. Open3D DbScanClustering聚类算法
  3. ORA-01747: user.table.column, table.column 或列说明无效 异常解决方法总结
  4. 深度学习框架PyTorch快速开发与实战
  5. 算法系列之住酒店最少天数问题
  6. Linux常用命令笔记2---文件管理4
  7. JavaScript编程:文档对象模型DOM
  8. [转]ubuntu下ATI/Intel双显卡切换的方法
  9. 提升领导力 六商是基础
  10. iOS开发常用的RGB色值和宏
  11. JS性能分析(测试代码运行时间)
  12. vue 无法进入response拦截器_vue拦截器的一次实践
  13. 利用python批量修改文件名称
  14. [VSCode] 编辑 markdown 推荐插件
  15. 【答题卡识别】基于matlab GUI hough变换答题卡成绩统计(带面板)【含Matlab源码 1828期】
  16. CTFMON。exe
  17. 自己写微信小程序MQTT模拟器
  18. JavaSE学生教师管理系统
  19. 《VERSE Versatile Graph Embeddings from Similarity Measures》阅读笔记
  20. OpenGauss数据库的安装与运行

热门文章

  1. 读书笔记之:Boost程序库完全开发指南(Ch1-4)
  2. Android中removeCallbacks失效原因
  3. linux 编译sqlitecpp,编译安装sqlite3数据库
  4. mysql PHP注册代码_求分享简单的php注册+mysql数据库登录源码
  5. ssha java接口_java – 从Spring在LDAP中设置SSHA密码
  6. 声音大小与振幅的关系_原来声音的属性有这三种!
  7. 基于Python下的Apriltag检测
  8. 2021年春季学期-信号与系统-第五次作业参考答案-第四小题
  9. 三极管的发射极与集电极之间的关系
  10. 2020年信号与系统课程批改工作处理程序