位操作小结与宏定义

讲道理,在没接触arm裸机前一直觉得位运算挺鸡肋的,就算是当年的汇编课设也没怎么用位操作。但是在统一编址的arm平台,操作外设主要靠操作寄存器,这时候位操作真的是必不可少,当然位操作和位运算是分不开的。


(1).位运算: 位与&,位或 | ,位取反~,位异或^(奇数个1异或结果为1,其他为0).

            算数运算(逻辑运算):算数与&&,算数或  | | ,算数取反!。(逻辑里无符号要么0,要么都是1)

    位移操作:左移<<,右移>>。


(2).常说的置位指的是置1,清除指的是置0。

           特定位置1:位或一个特定位为1,其他位为0的数即可。-------------------------------------------->a  |=(b<<c)

           特定位置0:位与一个特定位为0,其他为为1的数即可。(常用取反获得) ---------------------->a &=~(b<<c)

           取出特定位:位与一个特定位为1,其他位为0 的数即可。------------------------------------------> d = a &  (b<<c)

有没有发现上面的数互为取反,对的!要构造这样的多用取反和移位操作。


具体实例:   

a 为一寄存器值。

//现在我要让他bit 4 ~bit 7置为0;bit 8~bit 11写入965;再取出bit 8 ~ bit 11.

a & =~(0xf<<4)        (从多少bit开始就移多少位)

a | =~(0xf<<8)  ; a | =(965<<8)

int b= (a & ( 0xf<<8) >>8)



    (3).如何构造任意位的1;例如bit n到 bit m位为1。

 a =  ~(~(0U)<<(m-n+1));                                                                         //U代表无符号数,~(0U)表示0xFFFF

或者

a = ~(0U)>>(32-(m-n+1));                                                                  


    (4).与宏定义结合的位操作解析。注意宏定义的外面一定要加上括号。

// 将x的第n位置位                                                                                    //这里的第n位实际上是bit (n-1) ,下同         

         #define SET_NTH_BIT(x, n)               (x | ((1U)<<(n-1)))


//将x的第n位清除

#define CLEAR_NTH_BIT(x, n)           (x & ~((1U)<<(n-1)))


//截取x的第n到第m位

#define GETBITS(x, n, m)                      ((x & ~(~(0U)<<(m-n+1))<<(n-1)) >> (n-1)) 


分析第三个:~(~(0U)<<(m-n+1))                                            //获得m-n+1位的1 ,~优先级大于<<

                       x &       ~(~(0U)<<(m-n+1))     <<(n-1)              // 获得n到m位          ,<<优先级大于&

       (x & ~(~(0U)<<(m-n+1))<<(n-1)) >> (n-1)        //将获得到的数右移n-1位,即得到截取部分。


注意:~(0U)表示0xFFFF

优先级:~             >                  移位(<<,>>)               >   按位操作(&>|) 



<think>嗯,用户这次在问Verilog宏定义名能否包含方括号[]的问题。从引用材料看,用户提供的三个参考资料都聚焦在Verilog语法基础层面,特别是引用[3]详细说明了标识符的命名规则。用户可能正在编写Verilog代码时遇到了宏定义命名问题。考虑到方括号在Verilog中通常是位选操作符,用户应该是担心特殊字符是否允许出现在宏定义名称中。这个问题看似简单,但涉及到编译器的词法分析规则。根据之前对Verilog标准的了解,需要确认两个关键点:一是标识符的合法字符集,二是宏定义名称是否属于标识符范畴。引用[3]明确指出普通标识符由字母、数字、下划线和$符组成,且不能以数字或$开头。方括号不在允许字符之列,这意味着类似`define[MACRO]的写法肯定会报错。不过用户提到的.v文件扩展名提示可能在使用主流EDA工具(如Vivado或Quartus),这类工具通常遵循IEEE1364标准。查证标准文档确认:名称必须使用简单标识符(simple_identifier),其定义确实排除了方括号。有趣的是,类似SynopsysVCS的部分工具支持扩展标识符,但即使是转义标识符(escaped_identifier)用反斜杠包裹时,方括号也会被解释为普通字符而非位选符,这和用户原始需求不符。考虑到用户专业术语使用准确(如“.v文件”、“宏定义”),应该是有Verilog开发经验的工程师。回复时需要强调标准规定,同时指出实际工具可能存在的差异。可以再补充一个具体示例说明编译时的报错现象,比如当使用`define[CLK]时Typemate会提示“illegalcharacter'['”之类。最后要提醒用户注意宏定义名和内容的区别——方括号出现在内容里是完全合法的。之前有案例显示,新手容易混淆`defineWIDTH[7:0]这样的写法(这里非法的是名称被省略了,不是方括号问题),这个细节值得在回答中说明。</think> 在Verilog HDL中,宏定义名(即`define指令后的标识符)**不允许包含方括号[]**,原因如下: ### 合法性分析 1. **标识符命名规则** 根据IEEE 1364标准(引用[3]),Verilog的普通标识符(包括名)必须遵守: - **合法字符**:仅限字母(a-z, A-Z)、数字(0-9)、下划线(_)和美元符号($) - **首字符限制**:不能以数字或$开头 - **特殊字符禁止**:方括号`[]`属于操作符,**不可用于标识符命名** 2. **宏定义语法规范** `define指令的语法为: ```verilog `define <macro_name> <macro_value> ``` 其中`<macro_name>`必须是一个**简单标识符(simple_identifier)**,且需严格符合上述命名规则。 --- ### 错误示例正确写法 | **错误写法** | **编译错误原因** | **正确写法** | |----------------------|--------------------------|------------------| | `` `define DATA[7:0] 8 `` | `[ ]` 在名中非法 | `` `define DATA_W 8 `` | | `` `define [SIZE] 16 `` | 名包含非法字符`[ ]` | `` `define SIZE 16 `` | > **特殊说明**: > 方括号`[ ]`在**值**中合法(用于位选操作),例如: > ```verilog > `define BUS [7:0] // 合法:值包含位选 > wire `BUS data; // 等效于 wire [7:0] data; > ``` --- ### 编译器行为验证 - **主流EDA工具**(Vivado/Quartus/Verilator)会直接报错: ```log Error: macro name contains illegal character '[' ``` - 唯一允许包含特殊字符的标识符是**转义标识符(escaped_identifier)**(如`\data[0]`),但其**不适用于宏定义名**。 --- ### 小结 | **规则类型** | 宏定义名 | 值 | |-------------------|---------------------|-------------------| | **允许字符** | A-Z, a-z, _, $, 0-9 | 任意合法Verilog语法 | | **允许[]** | ❌ 禁止 | ✔️ 允许(位选操作) | | **标准依据** | IEEE 1364
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值