计算机组成原理(Logisim&Verilog部分)-笔记

前言

本人做此笔记一是想记录自己接下来两三年学习的心路历程与心得,二是希望看到这篇笔记的仁人志士能够为我指出一些不妥之处,互相交流,互相点播。

Logisim-pre

元件简述

1、splitter

连着splitter的那一端对应0。
请添加图片描述
2、符号扩展(Bit Extender)

无论如何连接,输入输出的最低位都是右下角的那个数。如图:请添加图片描述
3、奇校验、偶校验(odd parity、even parity)

奇校验:若所传输信号的中第 i 位为1的个数为奇数,则输出对应的第 i 位为1,反之为 0 。
偶校验:若所传输信号的中第 i 位为1的个数为偶数,则输出对应的第 i 位为1,反之为 0 。
下图为奇校验实例图:
奇校验
4、多路选择器、多路分配器(MUX、DMX)

注意长的一端对应使能端,灰色的点对应的是select data。

请添加图片描述
MUX与DMX的功能相反,前者是将其中的一个数据选择下来后传输到下一个元件,后者是将一个数据分配到指定的通路中。

5、译码器(Decd)

功能:将n位的二进制码转换为2^n位的独热吗。

6、位选择器(bit selector)

功能:选择输入数据中的一位输出
作用:可以选择输出一个n位数据的每一位。
ps:如果是将信号选择输出为一位信号,可以采用sel,而不用MUX。
请添加图片描述
7、加法(adder)

注意低位进位进位
请添加图片描述
8、比较器(comparator)
注意将其设置为
请添加图片描述
9、移位器(shifter)

其实可以看做乘或除2的幂次方。
左移:输出=输入*2^移动位数
请添加图片描述
10、位加(bit adder)

功能:计算输入数据中1的个数
请添加图片描述
11、触发器(D、T、J-K、S-R、)

同时具有 输入端、输出端、时钟端、使能端、清零端、置1端
请添加图片描述
12、寄存器(register)

具有 输入端、使能端、输出端、时钟端、清零端,可以设置在时钟的rising edge , falling edge , high level , low level受触发。

13、计数器(counter)

功能:
1、每个时钟周期依次递增1,并具有清零功能
2、通过0/1控制信号和输入端对计数器置数。只有当控制型号为1,且使能端为0时,才能置数成功,接着将控制信号为0,使能端为1,在置完数的基础上继续计数。

14、RAM、ROM
RAM:可读可写,相互分离,将数据接口选择为 Seperatrload and store ports
ROM:只读
文件导入:文件头增加一行 v2.0 raw

组合逻辑

1、真值表实现组合逻辑

通过Window->Combinatinal Analysis可以实现输入真值表自动搭建电路,显示卡诺图与逻辑函数表达式,十分方便。

2、题:实现四个4位的数据的排序

解题步骤:
(a)将一位的swap电路拓展为4位的swap电路。
(b)用comparator和4bit swap实现则大数下沉,小数上浮。
(c)最后用上述功能实现冒泡排序。

tips:在最后搭建main的过程中考虑最坏的输入情况,这样搭建起来思路会清晰一点

时序电路

1、有限状态机

  • Moore型状态机
    特点:一个状态对应一个输出。
  • Mealy型状态机
    特点:一个状态和一个输入对应一个输出。
    如何采用:
    其实两者在逻辑方面是可以相互转换的,但是当规定在输入的同时,输出要同时变化时,就要采用Meally型状态机(即在相邻上升沿的开区间时间内输入输出)。

2、Mealy型状态机举例

  • 输入:B(1 bit 串行输入,先输入高位)

  • 输出:Y0,Y1,Y2,Y3,Y4(Yx的下标x表示2^Bmod5的余数)

  • 状态个数:经过列举前几个数,发现一个规律——仅可能有四种余数可能。分别将其成为S0(余1),S1(余2),S2(余4),S3(余3),分别用一个2位的二进制数表示为00,01,10,11.

  • 状态转换表:
    请添加图片描述

  • 状态转换模块:
    根据状态转换表输入即可自动生成。
    ps:在设定输入输出的时候,输入设为a1a0,输出设为b1b0,则在用splitter的时候0,1就对应于输入的a0,a1以及输出的b0,b1,不易弄错。
    请添加图片描述

  • 输出模块:
    请添加图片描述

  • 主函数模块:

请添加图片描述
3、Moore型状态机举例

  • 输入:N;
  • 输出:对应N的斐波那契数列Fn
  • 状态转换模块
    F(n) = F(n-1) + F (n-2);
  • Logisim实现如下所示:
    请添加图片描述
    笔者发现,若将mux的输出端作为F(n),再和F(n-1)相加后都得到的F(n+1)是不正确的。111
    注意:经过初始化的那一端,连接的是F(n-1)。

ps:需要注意的几点:
1、当小于的时候停止计算,则counter的max_value一定要大于111,故要将Input位扩展为四位作比较。
2、输入初始化的部分一定一定要注意adder的下面的端口不是从mux之后接出来,而是直接F(n)tunnel,因为在起初,会导致两个1相加,从而快一个时钟周期。
3、mux用到清零端的时候要把Disabled Output设置为zero,否则会输出x。(笔者这里卡了好久555),所以还是最好不要用清零端,或许没啥意义。
请添加图片描述
Logisim的内容大致就这么多了,接下来是Verilog部分。

Verilog-pre

数据类型以及运算符

assign 语句不能在 always 和initail块中使用。
assign通常与三目运算符配合使用来建立组合逻辑,且只能够对wire型变量赋值。可以用 reg型变量对 wire型变量赋值。
(verilog中无自增自减运算符)

需要注意的几种运算符:
1、逻辑右移运算符 >>算数右移运算符>>>
区别:>>在最高位补0>>>在最高位补符号位
2、相等比较运算符
==!= 的比较结果可能会有不定值 x ,而 ===!==的结果是确定的0或1。
3、位拼接运算
例如{4{w}}等价于{w,w,w,w},还可多层嵌套。
4、缩减运算符
对一个操作数每一位汇总运算的结果。

模块的引用

modulename uut(.a(x),.b(y),.c(z));

阻塞赋值与非阻塞赋值
  • 阻塞赋值是立即赋值,即clk来临时,立即计算RHS并将其赋值给LHS。
  • 非阻塞赋值是在clk开始的时候计算RHS,计算好后RHS不变,直到赋值时刻结束时,RHS被赋值。
    避免出现冒险与竞争的几点编程要求
    a. 时序电路用非阻塞;
    b. always块建立组合逻辑,用阻塞
    c. 同一个always块中,有时序逻辑,全用非阻塞
    d. 同一个always块中,不要既有非阻塞,又有阻塞
    e. 不要在一个以上的always块中为同一个变量赋值
    f. 赋值时不用#0来延迟
有符号数的处理

对有符号数的处理就是每个数都加上 $signed(a),无论是在比大小,还是在做运算,每个数都要套上signed,否则verilog自动将符号数转化为无符号数,就会功亏一篑。

宏定义

注意在引用的时候也要加上`。

组合逻辑
  • assign
  • always @(*)+ case语句 + 阻塞赋值
HdlBits Verilog笔记

下面的部分是FSM之前的,FSM我还没做,做好了再更~

1、Gates(门)
  • NOR gate: assign out = ~(a | b);
  • NOR-或非
  • XOR-异或 (^)
  • XNOR-异或非
2、default_nettype none

放在module开头可以转换缺省类型

3、Bitwise and logical(位运算和逻辑运算)
按位或: a | b   return a number with 4bits
逻辑或: a || b  return 1 or 0
same as &.&&.
4、Concatenations(位拼接)

If we’re certain about the width of each signal, using the concatenation operator is equivalent and shorter: assign {w,x,y,z} = {a,b,b,c};
unsized constants are not allowed in concatenations!!
注意 {}字符串中的24{in[7]}外面还有一个大括号{}!!

assign out = {{24{in[7]}},in[7:0]};
assign {o2, o1, o0} = vec;//表示分别输出vec的第2位、第1位、第0位
5、Module -instantiate(模块实例)
  • By position
mod_a instance1 ( wa, wb, wc );

One drawback of this syntax is that the module’s port list changes , all instantiations of the module will also need to be found and changes to match the new module.

  • By name
mod_a instance2 ( .out(wc), .in1(wa), .in2(wb) );

调用module的时候,要对临时调用的module命名,例如上述的 instance1instance2

6、Full adder(全加器)
module add1 ( input a, input b, input cin, output sum, output cout );

// Full adder module here
	assign sum = a^b^cin;
    assign cout = (a&b)|(a&cin)|(b&cin);
endmodule

另一种写法:(这种写法的好处在于无论输入输出是几位的都成立)

module top_module( 
    input a, b, cin,
    output cout, sum );
    assign {cout,sum}=a+b+cin;
endmodule
7、Signed two 32bits numbers adder(有符号的两数相加)
 module top_module(
    input [31:0] a,
    input [31:0] b,
    input sub,
    output [31:0] sum
);
    wire cout1;
    wire cout2;

    wire [31:0] b_final;

    always @(*)
        begin
            case(sub)
                1'b0:b_final = b ;
                1'b1:b_final = ~b + 1;
            endcase
        end
    add16 uut1 (a[15:0],b_final[15:0],0,sum[15:0],cout1);
    add16 uut2 (a[31:16],b_final[31:16],cout1,sum[31:16],cout2);
endmodule
8、Avoid to make latches(防止产生锁存器)
  • case-endcase最好要有 default
  • if语句最好要有else语句
  • casez
// synthesis verilog_input_version verilog_2001
module top_module (
    input [7:0] in,
    output reg [2:0] pos  );
    always@(*)
        begin
            casez(in)
                8'b???????1:pos = 3'b000;
                8'b??????10:pos = 3'b001;
                8'b?????100:pos = 3'b010;
                8'b????1000:pos = 3'b011;
                8'b???10000:pos = 3'b100;
                8'b??100000:pos = 3'b101;
                8'b?1000000:pos = 3'b110;
                8'b10000000:pos = 3'b111;
				default:pos = 3'b000;
            endcase
        end
endmodule

!!!防治锁存的最好的方法是再case语句之前将其赋初值!!!见下例

// 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
           left = 0;down = 0;right = 0;up = 0;
            case(scancode)
                16'he06b:left = 1;
                16'he072:down = 1;
                16'he074:right = 1;
                16'he075:up = 1;
            endcase
        end
endmodule
9、Reduction(简化)
module top_module (
    input [7:0] in,
    output parity); 
    assign parity = ^ in[7:0];//表示对in的八位同时取xor
endmodule
module top_module( 
    input [99:0] in,
    output out_and,
    output out_or,
    output out_xor 
);
    assign out_and = & in[99:0];
    assign out_or  = | in[99:0];
    assign out_xor = ^ in[99:0];
endmodule
10、MUX(多路选择器)
  • 同样防止锁存
module top_module( 
    input [15:0] a, b, c, d, e, f, g, h, i,
    input [3:0] sel,
    output reg [15:0] out );
    always @(*)begin
        out=16'hffff;//防止锁存,无需用到default
        case(sel)
            4'd0:out = a;
            4'd1:out = b;
            4'd2:out = c;
            4'd3:out = d;
            4'd4:out = e;
            4'd5:out = f;
            4'd6:out = g;
            4'd7:out = h;
            4'd8:out = i;
            
        endcase
    end
endmodule
  • 设置一个256位的左路选择器(此方法很妙)叫做 向量索引
module top_module (
	input [255:0] in,
	input [7:0] sel,
	output  out
);
 
	assign out = in[sel];
	
endmodule
  • 再看个1024位的
module top_module( 
    input [1023:0] in,
    input [7:0] sel,
    output [3:0] out );
    assign out = {in[sel*4+3], in[sel*4+2], in[sel*4+1], in[sel*4+0]};
 
endmodule
11、Overflow(溢出)
module top_module (
    input [7:0] a,
    input [7:0] b,
    output [7:0] s,
    output overflow
); //
    // assign s = ...
    // assign overflow = ...
	assign s = a + b;
    assign overflow = (a[7]&b[7]&~s[7])|(~a[7]&~b[7]&s[7]);
endmodule

溢出与否只需要比较一个两个数的最高位和加完之后的数的最高位。

12、Asynchronous reset(异步复位)
module top_module (
    input clk,
    input areset,   // active high asynchronous reset
    input [7:0] d,
    output [7:0] q
);
    always@(posedge clk or posedge areset)
        begin
            if(areset)
                q <= 0;
            else 
                q <= d;
        end
endmodule
13、Decimal adder(十进制加法器)

转自https://blog.csdn.net/haojie_duan/article/details/113469349

module top_module (
    input clk,
    input reset,   // Synchronous active-high reset
    output [3:1] ena,
    output [15:0] q);

 	reg [3:0]	ones;
    reg [3:0]	tens;
    reg [3:0]	hundreds;
    reg [3:0]	thousands;
    
    always@(posedge clk)begin
        if(reset)begin
            ones <= 4'd0;
        end
        else if(ones == 4'd9)begin
            ones <= 4'd0;
        end
        else begin
            ones <= ones + 1'b1;
        end
    end
    
    always@(posedge clk)begin
        if(reset)begin
            tens <= 4'd0;
        end
        else if(tens == 4'd9 && ones == 4'd9)begin
            tens <= 4'd0;
        end
        else if(ones == 4'd9) begin
            tens <= tens + 1'b1;
        end
    end
    
    always@(posedge clk)begin
        if(reset)begin
            hundreds <= 4'd0;
        end
        else if(hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9)begin
            hundreds <= 4'd0;
        end
        else if(tens == 4'd9 && ones == 4'd9) begin
            hundreds <= hundreds + 1'b1;
        end
    end
    
    always@(posedge clk)begin
        if(reset)begin
            thousands <= 4'd0;
        end
        else if(thousands == 4'd9 && hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9)begin
            thousands <= 4'd0;
        end
        else if(hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9) begin
            thousands <= thousands + 1'b1;
        end
    end
    
    assign q = {thousands, hundreds, tens, ones};
    assign ena[1] = (ones == 4'd9) ? 1'b1 : 1'b0;
    assign ena[2] = (tens == 4'd9 && ones == 4'd9) ? 1'b1 : 1'b0;
    assign ena[3] = (hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9) ? 1'b1 : 1'b0;

endmodule
14、 Arthmetic Shift(算数移位器)
module top_module(
    input clk,
    input load,
    input ena,
    input [1:0] amount,
    input [63:0] data,
    output reg [63:0] q); 
    always@(posedge clk)begin
        if(load)begin
        	q <= data;
        end
        else if(ena)begin
            case(amount)
                2'b00:q <= {q[62:0],1'd0};
                2'b01:q <= {q[55:0],8'd0};
                2'b10:q <= {q[63],q[63:1]};
                2'b11:q <= {{8{q[63]}},q[63:8]};
            endcase
        end
    end

endmodule
总结

先写这么多,verilog的FSM部分和mips部分有空再更。写得较为草率,若有错误,请求指出 ~

  • 8
    点赞
  • 78
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值