接上次学习记录,从Module cseladd开始
Module cseladd
选择进位加法器(CSA: Carry-Select Adder)
Module addsub
由加法器构建减法器:a+b=a+(-b)
-b即b取反加一
首先复习一下补码
原码-3 = 1 011
反码-3 = 1 100 除了符号位取反
补码-3 = 1 101 再加一
原码不能计算减法,反码不能计算跨0减法,补码都可以。
例如 -3 + 5
1 101
+ 0 101
————
1 0 010
将0 010等于2结果正确
如何判断溢出:溢出是指有符号数的进位,而减法器则需要用符号数表示
有符号数溢出判断
微机原理中的判断有符号数溢出规则:最高位进位状态⊕次高位进位状态=1,则溢出
"⊕"表示异或:相同为0,相异为1
那么上述判断规则翻译白话后为:最高位和次高位,一个有进位一个没有进位,则他们的状态异或值是1,则结果就有溢出。
module top_module(
input [31:0] a,
input [31:0] b,
input sub,
output [31:0] sum
);
wire [15:0]sum0;
wire cout;
wire [15:0]sum1;
wire [31:0]bs;
assign bs=b^{32{sub}};
add16 u1(a[15:0],bs[15:0],sub,sum0,cout);
add16 u2(a[31:16],bs[31:16],cout,sum1,);
assign sum = {sum1,sum0};
endmodule
procedures
always block1
使用always过程块的组合逻辑
always @(*) = assign
Alwaysblock2
always时序逻辑与阻塞非阻塞赋值
Always if
if语句通常对应一个二选一多路复用器,如果条件为真,则选择其中一个输入作为输出;反之如果条件为假,则选择另一个输入所谓输出。if语句必须在过程块内使用。
和问号表达式等价
Practic
module top_module(
input a,
input b,
input sel_b1,
input sel_b2,
output wire out_assign,
output reg out_always );
assign out_assign = sel_b1? sel_b2?b:a:a;
always @(*)begin
if(sel_b1 == 1'b1 && sel_b2 == 1'b1)begin
out_always = b;end
else begin
out_always = a;
end
end
Always if2
常见的错误来源:如何避免引入锁存器
除了你指定的情况以外,会发生些什么,答案是什么也不会发生,输出保持不变。而这往往就导致了电路的错误,所以说语法正确的代码不一定能产生合理的电路(组合逻辑+触发器)。
输出保持不变,这就意味着电路需要记住当前状态,从而产生锁存器。组合逻辑(比如逻辑门)不能记住任何状态。
Always case
无优先级的if else
Always casex
Always casez
case项允许重复和部分重叠,执行程序匹配到的第一个。
asez语句和case语句的用法非常相似,其唯一的区别在于,状态z在casez语句中不会被视为正常的z状态,而是将表达式中,标记为z的那个(或那些)bit视为不在乎(dont care)。
Always nolatches
题目:
代码:
// synthesis verilog_input_version verilog_2001
module top_module (
input [15:0] scancode,
output reg left,
output reg down,
output reg right,
output reg up );
always @(*)begin
up = 1'b0; down = 1'b0; left = 1'b0; right = 1'b0;
case(scancode)
16'he06b: left = 1'b1;
16'he072: down = 1'b1;
16'he074: right = 1'b1;
16'he075: up = 1'b1;
endcase
end
endmodule
Conditional ternary operator(Conditional)
问号表达式 a ? b:c
Reduction
前面已经讲过两个变量之间的按位运算,例如a&b或a^b。有时候,我们想要构建一个输入比较多的门,对一个向量的所有位进行操作,如(a[0]&a[1]&a[2]&a[3]...),但这对于长的标量来说,这很麻烦。
归约运算符(Reduction Operators)可以对向量的每一位位进行AND,OR和XOR,产生一位输出: