Verilog与数电[1]-74HC595

保命声明:笔者在校属于中低水平学生,代码能力有限,若行文中有错漏之处欢迎大家指出。

逻辑芯片介绍

逻辑芯片:74系列和54系列。74系列用于民用,54系列可以适用于极端环境。
[https://wenwen.sogou.com/z/q539212579.htm]
54/74系列器件采用单一的5V供电。54系列的TTL电路和74系列的TTL电路具有完全相同的电路结构和电气参数,二者的差别仅为工作温度范围和电源电压范围。54系列的工作温度范围为-55到+125摄氏度,电源电压范围为5V +-10%。74系列的工作温度范围为0到70摄氏度,电源电压范围为5V +-5%。

逻辑芯片目录

74系列目录
74系列目录-TI公司

74HC和74LS区别

[https://www.elecfans.com/dianzichangshi/20180802721454.html]
74LS属于TTL类型的集成电路,而74HC属于CMOS集成电路。

LS是低功耗肖特基,HC是高速COMS。LS的速度比HC略快。HCT输入输出与LS兼容,但是功耗低;F是高速肖特基电路.
74LS是TTL电路的一个系列,TTL电路以双极型 晶体管为开关元件所以以称双极型(电子和空穴)集成电路。
74HC是CMOS电路,CMOS电路是MOS电路中的主导产品。MOS电路以绝缘栅场效应晶体管为开关元件。所以又称单极型集成电路。按其导电沟道的类型,MOS电路可分为PMOST 、NMOS和CMOS电路。CMOS电路沿着4000A--4000B/4500B(统一称为4000B)--74HC--74HCT系列高速发展。 HCT系列还同TTL电平兼容,扩大了应用范围。

Verilog介绍

[https://zhuanlan.zhihu.com/p/550710744]
Verilog HDL(简称 Verilog )是一种硬件描述语言,用于数字电路的系统设计。可对算法级、门级、开关级等多种抽象设计层次进行建模。形式上类似C语言。
Verilog可以从五个层次对电路(系统)进行描述,包括:系统级、算法级、寄存器传输级(即RTL级)、门级、开关级。我们平时用的最多的为RTL级,故Verilog代码也经常被称为RTL代码。

为什么很多特定算法,用 Verilog 设计并且硬件化之后,要比用软件实现的运算速度快很多?
简单的说越是底层的东西越快,效率越高,因为中间步骤少!从另外一个方面来说,硬件化是一种定制化,在某一方面具有特别突出的能力,例如CPU软解码和GPU硬解码,两者的效率天差地别。

Verilog实现74HC595

[https://vlab.ustc.edu.cn/guide/doc_verilog.html]

环境搭建(macOS)

[https://zhuanlan.zhihu.com/p/151433928]

  1. 代码编译工具
    brew install icarus-verilog

  2. 代码仿真工具
    brew install verilator

  3. 代码波形图查看工具
    brew cask install xquartz
    brew cask insatll gtkwave

  4. 上述工具的综合工具
    git clone https://github.com/YosysHQ/yosys.git
    brew tap Homebrew/bundle && brew bundle
    make && make install

  5. 然后vscode安装插件
    Verilog-HDL/SystemVerilog/Bluespec SystemVerilog(mshr-h)
    Verilog_Testbench(Truecrab)
    Verilog HDL(leafvmaple)

  6. 测试安装
    counter.v

module counter (clk, rst, en, count);

	input clk, rst, en;
	output reg [1:0] count;

	always @(posedge clk)
		if (rst)       //复位信号
			count <= 2'd0;
		else if (en)   //使能信号
			count <= count + 2'd1;

endmodule

counter_tb.v

`timescale 1ns / 1ps
module counter_tb;

reg clk;
reg reset;
reg enable;
wire [1:0] counter_out;

counter c1(clk,reset,enable,counter_out);

/*iverilog */
initial
begin            
    $dumpfile("wave.vcd");        //生成的vcd文件名称
    $dumpvars(0, counter_tb);     //tb模块名称
end
/*iverilog */

initial
begin
  clk=0;
  reset=1;
  enable=1;
  clk=1;
  #10
  reset=0;
end

always
#5 clk=~clk;

initial
  #200 $finish;

endmodule

编译:
iverilog -o wave counter.v counter_tb.v

#! /usr/local/Cellar/icarus-verilog/11.0/bin/vvp
:ivl_version "11.0 (stable)";
:ivl_delay_selection "TYPICAL";
:vpi_time_precision + 0;
:vpi_module "/usr/local/Cellar/icarus-verilog/11.0/lib/ivl/system.vpi";
:vpi_module "/usr/local/Cellar/icarus-verilog/11.0/lib/ivl/vhdl_sys.vpi";
:vpi_module "/usr/local/Cellar/icarus-verilog/11.0/lib/ivl/vhdl_textio.vpi";
:vpi_module "/usr/local/Cellar/icarus-verilog/11.0/lib/ivl/v2005_math.vpi";
:vpi_module "/usr/local/Cellar/icarus-verilog/11.0/lib/ivl/va_math.vpi";
S_0x7f8a29505340 .scope module, "counter" "counter" 2 1;
 .timescale 0 0;
    .port_info 0 /INPUT 1 "clk";
    .port_info 1 /INPUT 1 "rst";
    .port_info 2 /INPUT 1 "en";
    .port_info 3 /OUTPUT 2 "count";
o0x7f8a29632008 .functor BUFZ 1, C4<z>; HiZ drive
v0x7f8a295054c0_0 .net "clk", 0 0, o0x7f8a29632008;  0 drivers
v0x7f8a29515570_0 .var "count", 1 0;
o0x7f8a29632068 .functor BUFZ 1, C4<z>; HiZ drive
v0x7f8a29515610_0 .net "en", 0 0, o0x7f8a29632068;  0 drivers
o0x7f8a29632098 .functor BUFZ 1, C4<z>; HiZ drive
v0x7f8a295156c0_0 .net "rst", 0 0, o0x7f8a29632098;  0 drivers
E_0x7f8a29504f00 .event posedge, v0x7f8a295054c0_0;
    .scope S_0x7f8a29505340;
T_0 ;
    %wait E_0x7f8a29504f00;
    %load/vec4 v0x7f8a295156c0_0;
    %flag_set/vec4 8;
    %jmp/0xz  T_0.0, 8;
    %pushi/vec4 0, 0, 2;
    %assign/vec4 v0x7f8a29515570_0, 0;
    %jmp T_0.1;
T_0.0 ;
    %load/vec4 v0x7f8a29515610_0;
    %flag_set/vec4 8;
    %jmp/0xz  T_0.2, 8;
    %load/vec4 v0x7f8a29515570_0;
    %addi 1, 0, 2;
    %assign/vec4 v0x7f8a29515570_0, 0;
T_0.2 ;
T_0.1 ;
    %jmp T_0;
    .thread T_0;
# The file index is used to find the file name in the following table.
:file_names 3;
    "N/A";
    "<interactive>";
    "counter.v";

74HC595介绍

74HC595是一个8位串行输入、平行输出的位移缓存器:平行输出为三态输出。在SCK的上升沿,单行数据由SDL输入到内部的8位位移缓存器,并由Q7‘输出,而平行输出则是在LCK的上升沿将在8位位移缓存器的数据存人到8位平行输出缓存器。当串行数据输人端OE的控制信号为低使能时,平行输出端的输出值等于平行输出缓存器所存储的值。而当OE为高电位,也就是输出关闭时,平行输出端会维持在高阻抗状态。

图中的SRA——SRH是移位寄存器(ShiftRegister),数据从它们的D引脚输入,从Q引脚输出,每次移位脉冲引脚(ShiftClock)提供一个脉冲,D引脚的数据就会输出并保持到Q引脚,因为这里的移位脉冲引脚(ShiftClock)是连到每一个SR上的,所以自然每次给一个移位脉冲的时候,所有的数据都向后移动了一位。
然后我们看到LRA——LRH,它们是锁存寄存器(LatchRegister),每次锁存脉冲引脚(LatchClock)给一个脉冲,Q脚就会输出并保持D脚的值。LR和SR其实是差不多的功能,只是SR多了个复位脚。
我们可以把LR看成是照相机,锁存脉冲引脚就相当于是照相机的快门,我们给一个锁存脉冲,那么数据就被锁存在了对应的Q脚。而当我们没有操作锁存引脚的时候,照相机只是摆在那里,不管队伍怎么前进了,照相机的输出始终是不变的。只有某次按下了快门,所有的照相机的照片就都更新了一次。

Verilog实现

逻辑表达式分析

需要实现的模块:移位寄存器、锁存寄存器、非门、D触发器

模块例化

可通过实例化已经设计好的模块来达到重用模块,简化设计的目的。可将一个模块重用多次,在同一模块中,实例化名称(本例中为lsbmux、msbmux)可任意指定,但不能相同,也不能使用verilog中的关键字。

module d_flip_flop(d,clk,q);
    input d;
    input clk;
    output q;

    reg q;

    always @ (posedge clk)//我们用正的时钟沿做它的敏感信号
    begin
        q <= d;//上升沿有效的时候,把d捕获到q
    end
endmodule

测试代码

`timescale 1ns / 1ns

module d_flip_flop_tb;
    reg clk,d;
    wire q;

    d_flip_flop u1(.d(d),.clk(clk),.q(q));

    initial
    begin
        clk = 1;
        d <= 0;
        forever
        begin
            #60 d <= 1;//人为生成毛刺 
            #22 d <= 0;
            #2  d <= 1;
            #2  d <= 0;
            #16 d <= 0;//维持16ns的低电平,然后让它做周期性的循环
        end
    end

    always #20 clk <= ~clk;//半周期为20ns,全周期为40ns的一个信号
endmodule
  • 锁存寄存器
module d_latch(d,clk,q);
    input d;
    input clk;
    output q;

    reg q;

    always @ (d,clk)
        if(clk)
            q <= d;
endmodule

测试代码

`timescale 1ns / 1ns

module d_latch_tb;
    reg clk,d;
    wire q;

    d_latch u1(.d(d),.clk(clk),.q(q));

    initial
    begin
        clk = 1;
        d <= 0;
        forever
        begin
            #60 d <= 1;//人为生成毛刺 
            #22 d <= 0;
            #2  d <= 1;
            #2  d <= 0;
            #16 d <= 0;//维持16ns的低电平,然后让它做周期性的循环
        end
    end

    always #20 clk <= ~clk;//半周期为20ns,全周期为40ns的一个信号
endmodule
  • 非门
module or_gate(A,Y);
  input[2:0] A;
  output[2:0] Y;
  assign Y=~A;//非门
endmodule

或者使用内置输出

 not (OUTZ3, IN3) ;

模块组合

[https://www.dssz.com/2713131.html]
文件:Chip_74HC595.v

module Chip_74HC595(
	shift_clk,
	serial_data,
	reset,
	latch_clk,
	output_enable,
	q,
	qh
);

input shift_clk;
input serial_data;
input reset;
input latch_clk;
input output_enable;
output wire[7:0] q;

reg[7:0]tmp;
reg[7:0]q_pre;
output reg qh;

always@(negedge latch_clk or negedge reset)
begin
	if(!reset)
		qh<=0;
	else
		qh<=q_pre[6];
end

always@(posedge latch_clk or negedge reset)
begin
	q_pre<=tmp;
end

assign q=output_enable?8'bzzzzzzzz:q_pre;

always@(posedge shift_clk or negedge reset)
begin
	if(!reset)
		tmp<=8'd0;
	else
		tmp<={tmp[6:0],serial_data};
end

endmodule

文件:Chip_74HC595_tb.v
注:tb(Testbench)

`timescale 1ns/1ps
module Chip_74HC595_tb();

reg clk;
reg serial_data;
reg reset;
reg latch_clk;
reg output_enable;

wire[7:0] q;
wire qh;

Chip_74HC595 DUT(
	.shift_clk(clk),
	.serial_data(serial_data),
	.reset(reset),
	.latch_clk(latch_clk),
	.output_enable(output_enable),
	.q(q),
	.qh(qh)
);

initial
begin
clk=0;
end
always#1 clk<=~clk;


initial
begin
serial_data=0;
#2 serial_data=1;
#2 serial_data=0;
#18 serial_data=1;
#2 serial_data=0;
end

initial
begin
reset=0;
#2 reset=1;
#27 reset=0;
#2 reset=1;
end

initial
begin
latch_clk=0;
#4 latch_clk=1;
#1 latch_clk=0;
#1 latch_clk=1;
#1 latch_clk=0;
#1 latch_clk=1;
#1 latch_clk=0;
#1 latch_clk=1;
#1 latch_clk=0;
#1 latch_clk=1;
#1 latch_clk=0;
#1 latch_clk=1;
#1 latch_clk=0;
#1 latch_clk=1;
#1 latch_clk=0;
#1 latch_clk=1;
#1 latch_clk=0;
#1 latch_clk=1;
#1 latch_clk=0;
#3 latch_clk=1;
#1 latch_clk=0;
#5 latch_clk=1;
#1 latch_clk=0;
end

initial
begin
output_enable=0;
#21 output_enable=1;
#4 output_enable=0;
end


// initial
// begin
// clk=0;
// latch_clk=1;
// end
// always#1 clk<=~clk;
// always#1 latch_clk<=~latch_clk;

// initial
// begin
// serial_data=0;
// #2 serial_data=1;
// #4 serial_data=0;
// #8 serial_data=1;
// #12 serial_data=0;
// end

// initial
// begin
// reset=0;
// #2 reset=1;
// #27 reset=0;
// #2 reset=1;
// end


// initial
// begin
// output_enable=0;
// #22 output_enable=1;
// #4 output_enable=0;
// end

endmodule

posted @ 2022-09-26 23:39  qsBye  阅读(389)  评论(0编辑  收藏  举报