尽管您可以使用 C 来描述数字电路(实际上,Verilog HDL 与 C 有一些相似之处),但有一个基本的东西是您无法用纯 C 建模的:并行性。
如果有任何属于数字电路描述的东西,那就是它在描述本身中固有的并行性:功能(实际上是模块),甚至代码块都是并行“执行”的。
任何普通的 C 程序随时间描述一系列操作,因此,任何描述数字操作的尝试,除非它是非常微不足道的,都将被编译为一系列步骤,而不是利用数字电路本质上具有的并行性.
也就是说,确实存在一些与 C 相当接近的 HDL(硬件描述语言)。其中之一是Handel-C。Handel-C 使用从 C 中借用的语法,加上一些附加功能以更好地处理数字设计中存在的固有并行性。
例如:假设你要交换两个变量的值。经典解决方案(除了基于按位运算等的解决方案)是:
temp = a;
a = b;
b = temp;
但是,当有人在学习计算机编程时,将上述序列编码为这样的常见错误:
a = b;
b = a;
因为我们认为在变量交换中是一种并行操作:“ b 的值被复制到 a,同时 a 的值被复制到 b ”。
这种方法的有趣之处在于它确实有效……如果我们设法并行执行这两个任务。在普通 C 中不可能的东西,但在 Handel-C 中是不可能的:
par
{
a = b;
b = a;
}
该par
语句表明每个代码行将相对于其他代码行并行“执行”。
在 Verilog 中,相同的交换会写成这样:
a <= b;
b <= a;
<=
是 Verilog 中的非阻塞赋值:在第一行完成后,第二行没有“执行”,而是同时开始。这个序列通常出现在一个时钟始终(一种循环,每次灵敏度列表中的时钟信号从 0 变为 1 - posedge
- 或从 1 变为 0 - negedge
- 时“执行”的一种循环)。
always @(posedge clk) begin
a <= b;
b <= a;
end
这意味着:每次clock
0 到 1 时,交换 和 之间的a
值b
。
请注意,当我谈到数字设计的语言时,我总是引用“执行”。代码实际上并没有转化为要由处理器执行的一系列操作,但代码是一个电路。将其视为 2D 原理图的 1D 渲染,用句子和运算符代替电子符号,用赋值、参数和“函数调用”代替电线。
如果您熟悉数字电路,您会意识到“总是”循环看起来很相似,实际上可以翻译成这样:

仅将相同的高级描述转换为汇编是您无法做到的(除非目标处理器的 ISA 具有某种XCHG
指令,这实际上并不少见,并且代码保留了两个变量以交换到 CPU寄存器)。