前进5

191 阅读12分钟

1 四选一多路选择器

两位sel可以选择四个状态。

input [1:0] d1,d2,d3,d0;
input [1:0] sel;
output  [1:0]mux_out
);
    reg [1:0] mux_out_reg;
    always@(*)
    begin
        case(sel)
            2'b00:mux_out_reg = d3;
            2'b01:mux_out_reg = d2;
            2'b10:mux_out_reg = d1;
            2'b11:mux_out_reg = d0;
        default:
            mux_out_reg = d0;
        endcase
     end
     
 assign mux_out = mux_out_reg;
      

endmodule

2 3-8 译码器

三位表示八个状态

moudule 
(a,b,c,out);
input a,b,c;
ouput reg [7:0] out;

always@(a,b,c)
begin
    case({a,b,c})
        3'b000: out = 8'b0000_0001;
        3'b001: out = 8'b0000_0010;
        3'b010: out = 8'b0000_0100;
        3'b011: out = 8'b0000_1000;
        3'b100: out = 8'b0001_0000;
        3'b101: out = 8'b0010_0000;
        3'b110: out = 8'b0100_0000;
        3'b111: out = 8'b1000_0000;
        
    endcase
    
 end
 
endmodule



3 序列检测

检测输入信号满足0111_0001序列

序列缓存,做对比。

将8个时刻的数据缓存,作为一个数组,每个时刻的输入位于数组的末尾,数组其他元素左移,把最早输入的数据移出。然后将数组和目标序列对比,如果数组和目标序列相等,则说明出现目标序列。

/序列缓存,位拼接实现,序列左移。 低7位作为高7位

a_temp <= {a_temp[6:0],a};

	input clk,
	input rst_n,
	input a,
	output reg match
	);

    reg [7:0]a_temp;
    //序列检测 输出
    always@(posedge clk or negedge rst_n)
        if(rst_n == 1'b0)
            match <= 1'b0;
        else if(a_temp == 8'b0111_0001)   
            match <= 1'b1;
        else
             match <= 1'b0;
    //序列缓存,位拼接实现,序列左移。 低7位作为高7位
    always@(posedge clk or negedge rst_n)
        if(rst_n == 1'b0)
            a_temp <= 8'b0;
        else 
            a_temp <= {a_temp[6:0],a};

  
endmodule

4 含有无关项的序列检测

检测序列 011xxx 100序列。

序列缓存法: 将九个时刻的数据缓存,作为数组,每个时刻的输入位于数据末尾,数组其他元素左移,把最早输入的数据移出,然后截取数组前三位和目标序列011对比,截取数组后三位与目标序列110对比。

移位可以通过位截取和位拼接操作实现,{a_temp[7:0],a}

	input clk,
	input rst_n,
	input a,
	output reg match
	);

    reg [8:0]a_temp;
    
    always@(posedge clk or negedge rst_n)
        if(!rst_n)
            match <= 1'b0;
        else if(a_temp[8:6] == 3'b011 && a_temp[2:0] == 3'b110)
            match <= 1'b1;
        else
             match <= 1'b0;
   
    
    always@(posedge clk or negedge rst_n)
        if(!rst_n)
            a_temp <= 9'b0;
        else 
            a_temp <= {a_temp[7:0],a};
   
endmodule

5 时钟分频偶数

使用D触发器设计2/4/8分频的占空比为百分之50的时钟分频器。

基于计数器的原理,通过计数实现时钟的分频。 要实现2/4/8分频,可以使用三位的计数器来实现。2分频一个时钟周期反转,4分频两个时钟周期反转,8分频4个时钟周期实现反转。

三位计数器 三位对应三个分频信号的。

module even_div
    (
    input     wire rst ,
    input     wire clk_in,
    output    wire clk_out2,
    output    wire clk_out4,
    output    wire clk_out8
    );
    
    reg [2:0]cnt;
    always@(posedge clk_in or negedge rst)
        if(!rst)
            cnt <= 3'b011;
        else
            cnt <= cnt + 1'b1;
        
    assign clk_out2 = ~cnt[0];
    assign clk_out4 = ~cnt[1];
    assign clk_out8 = cnt[2];
    

endmodule

6 时钟分频奇数分频 7分频 两个六分频输出的或

实现7分频是两个6分频的输出的或,两个6分频一个上升沿计数,上升沿分频,一个下降沿计数,下降沿分频。

   (
    input    wire  rst ,
    input    wire  clk_in,
    output   wire  clk_out7
    );
    reg [2:0] count_p;
    reg [2:0] count_n;
    reg clk_p;
    reg clk_n;
    
    //上升沿计数
    always@(posedge clk_in or negedge rst)
        if(!rst)
            count_p <= 3'b0;
        else if(count_p == 3'd6)
            count_p <= 3'b0;
        else
             count_p <= count_p + 1'b1;
    always@(posedge clk_in or negedge rst)
        if(!rst)
            clk_p <= 1'b0;
        else if(count_p == 3'd3 || count_p == 3'd6)
            clk_p <= ~clk_p;
        else
            clk_p <= clk_p;
    
    
     //下降沿计数
    always@(negedge clk_in or negedge rst)
        if(!rst)
            count_n <= 3'b0;
        else if(count_n == 3'd6)
            count_n <= 3'b0;
        else
             count_n <= count_n + 1'b1;
    
    always@(negedge clk_in or negedge rst)
        if(!rst)
            clk_n <= 1'b0;
        else if(count_n == 3'd3 || count_n == 3'd6)
            clk_n <= ~clk_n;
        else
            clk_n <= clk_n;
    
    assign clk_out7 = clk_n | clk_p;
    


endmodule

7 小数分频

双模小数分频原理是取该频次两边的两个分频器拼接组成小数分频器,以5.3分频为例,即使用5分频和6分频道分频器拼接可以组成5.3分频分频器。 即a+b = 10 5a+6b = 53. 即可求出需要五分频7个6分频3个。

module div_M_N(
 input  wire clk_in,
 input  wire rst,
 output wire clk_out
);
parameter M_N = 8'd87; 
parameter c89 = 8'd24; // 8/9时钟切换点
parameter div_e = 5'd8; //偶数周期
parameter div_o = 5'd9; //奇数周期

//先输出8分频三个周期,24个周期后输出9分频7个。 分频点为C89。
    //完成偶数和奇数的计数
    reg [3:0]clk_cnt;
    //对clk_in计数,计满清零
    reg [6:0]cyc_cnt;
    //8/9分频的分频标志
    reg div_flag;
    reg clk_out_r;
    
    //切换8分频 9分频。通过div_flag信号进行切换.  切换偶数或者奇数计数器
    always@(posedge clk_in or negedge rst)
        if(!rst)
            clk_cnt <= 0;
        else if(~div_flag)
            clk_cnt <= clk_cnt == (div_e-1) ? 0: clk_cnt + 1;
        else
            clk_cnt <= clk_cnt == (div_o-1) ? 0: clk_cnt + 1;
        
    // 计数整个周期  统计87个周期
     always@(posedge clk_in or negedge rst)
        if(!rst)
            cyc_cnt <= 1'b0;
        else
            cyc_cnt <= cyc_cnt == (M_N-1)?0:cyc_cnt+1;
    //切换8分频和9分频,标志信号div_flag  使得偶数分频时候div_flag一直为0,奇数分频时为1。
    always@(posedge clk_in or negedge rst)
        if(!rst)
            div_flag <= 1'b0;
        else
            div_flag <= cyc_cnt == (M_N-1)|| cyc_cnt == (c89-1) ? ~div_flag:div_flag;
    //确定输出  右移两位为2. 小于等于3  0123 对于偶数分频为百分之50占空比,对于奇数分频不是百分之50占空比
    always@(posedge clk_in or negedge rst)
        if(!rst)
            clk_out_r<=1'b0;
        else if(~div_flag)
            clk_out_r <= clk_cnt <= ((div_e>>2)+1);
        else
            clk_out_r <= clk_cnt <= ((div_o>>2)+1);
            
        
    assign clk_out = clk_out_r;



endmodule

8 存储器

ROM:只读寄存器,手机,计算机等设备的存储器。

EEPROM: 电可擦除可编程只读存储器。

RAM:随机存取存储器,手机,计算机的运行内存。

SRAM:静态随机存取存储器,只要供电就会保持,但断电数据就会消失。

DRAM:动态随机存储器,利用电容存储电荷的多少来存储,需要不断进行刷新。SRAM不需要刷新也会保持数据,但是两者断电后数据都会消失。

SDRAM:同步动态随机存储器,同时写入和读出的DRAM。

DDR:Double data sdram 双倍速率同步动态随机存储器,双倍速率传输的SDRAM,在时钟上升沿和下降沿都可以进行数据传输。电脑内存条都是DDR芯片。

FLASH:闪存,内存卡或u盘。

9 数字电路基础

1 byte = 8bit

1word = 2byte

1dword 双字 = 2word

1qword = 4word

原码、反码、补码 以8bit为例

原码为 符号位+真值,最高位为符号位 -127 - +127

反码,正数的反码为他本身,负数的反码为原码除符号位外,逐位取反。

补码,正数的表示与原码相同。 对于负数,补码的计算方式为,除符号位外,原码取反加1。即反码加1。

对于无符号数,原码反码补码都是其本身。

数值转换:

十进制转R进制: 整数部分,除R取余法,除到商为为止。小数部分,乘R取整法,乘到积为为止。

二进制转八进制: 三位一组,整数部分左边补0,小数部分右边补0。

二进制转十六进制: 四位一组,整数左边补0,小数右边补0。

逻辑函数及其化简

公式法:

卡诺图:

10 FPGA与CPLD的区别

FPGA和CPLD都属于高密度可编程逻辑器件。

FPGA 以查找表 结构方式构成逻辑行为, 适合完成时序逻辑,即适用于实现触发器丰富的逻辑电路。程序存储: FPGA大部分基于SRAM编程,系统断电后编程信息丢失,需要外挂EEPROM来存储配置信息,每次上电后,将配置信息重新写入SRAM。

CPLD 以乘积项 结构方式构成逻辑行为, 适合完成各种算法和组合逻辑,即适用于触发器有限而乘积项丰富的逻辑电路。程序存储:内部EEPROM或者FLASH存储器编程。

CPLD比FPGA速度快,保密性好。

FPGA比CPLD集成度高,功耗低,编程灵活性大。

CPLD是逻辑块级编程,通过修改固定内连电路的逻辑功能来编程,而FPGA是门级编程,主要通过改变内部连线来编程。FPGA比CPLD灵活。

FPGA: 查找表 -- 时序逻辑 编程灵活性高,功耗低

CPLD: 乘积项--组合逻辑和各种算法 速度快,保密性好

11 锁存器latch和触发器flip-flop的区别?

锁存器:对脉冲电平敏感,在时钟脉冲的电平作用下改变状态。

锁存器是电平触发的存储单元,数据的存储取决于输入时钟信号的电平值,当锁存器处于使能状态,数据才会随着数据输入而变化。两个输入信号,一个有效使能信号,一个输入数据信号。在使能信号有效时,将D的值给Q。

触发器对脉冲边沿敏感,其状态只在时钟脉冲的上升沿或下降沿的瞬间变化。

触发器一直保持它们的状态,直到它们收到输入脉冲,当收到输入脉冲时,触发器输出,然后保持这个状态直到收到下一个触发。

12 寄存器----串转并---并转串

寄存器: 用来存放数据的一些小型存储区域。因为一个锁存器或触发器能存储一位二进制数,所以N个锁存器或者触发器可以构成N位寄存器。

寄存器可以完成数据的串并转换,串并转换。

串转并: 移位寄存器。。移位的方式为: 位拼接+计数

采用位拼接技术,移位寄存器,将串行的数据数据先表示出来,然后发送一位数据加1。一般八位数据,每次取低7七位为最高位,新数据为最低位。(低位先赋值) 然后利用计数器计数,每过一个时钟数据给低一位,8个时钟后,得到并行的八位数据。

并转串:通过移位寄存器,八位数据,用八位寄存器寄存。

通过<<1,左移操作。每次取最高位数据,第一次赋值数据,通过取最高位。

13 自动饮料贩卖机

请设计状态机电路,实现自动售卖机功能,A饮料5元钱,B饮料10元钱,售卖机可接收投币5元钱和10元钱,每次投币只可买一种饮料,考虑找零的情况。

电路的接口如下图所示。sel信号会先于din信号有效,且在购买一种饮料时值不变。 sel为选择信号,用来选择购买饮料的种类,sel=0,表示购买A饮料,sel=1,表示购买B饮料; din表示投币输入,din=0表示未投币,din=1表示投币5元,

  • din=2表示投币10元,不会出现din=3的情况;
  • drinks_out表示饮料输出,drinks_out=0表示没有饮料输出,drinks_out=1表示输出A饮料,drinks_out=2表示输出B饮料,不出现drinks_out =3的情况,输出有效仅保持一个时钟周期;
  • change_out表示找零输出,change_out=0表示没有找零,change_out=1表示找零5元,输出有效仅保持一个时钟周期。

mealy状态机的输出不仅与当前状态值有关,而且与当前输入有关。
moore状态机的输出仅与当前状态值有关,而与此时的输入无关

我们使用mealy型状态机 减少状态数:

//两个状态,饮料机空闲和饮料机输出饮料B但只投了五块钱

14 morre型状态机和mealy型状态机

moore 与mealy摩尔型和米勒型状态机:

Moore有限状态机的输出只与当前状态有关,与输入信号的当前值无关。从时序上看,Moore状态机属于同步输出状态机,Moore有限状态机的特点是将输入与输出信号隔离开来。

Mealy型状态机的输出是当前状态和输入的函数,随输入变化而随时变化。从时序上看,Mealy状态机属于异步输出,它不依赖于时钟。

15 程序下载到FPGA的方式有哪种,JTAG有几根线

JTAG: 下载sof,掉电丢失。 可以将sof文件转为jic文件,通过外部存储器EPCSx配置,掉电不丢失。

AS:下载pof文件,配置EPCSx,掉电不丢失。

PS:由外部计算机或控制器 控制配置过程。

JTAG有以下几根线:TCK,TMS,TDI,TDO,TRST五根线

TCK:测试时钟输入,TRST测试复位输入,TMS测试模式选择,TDI测试数据输入,TDO测试数据输出。

16格雷码计数器

格雷码转二进制

二进制计数加一

二进制转格雷码

17 FPGA中同步逻辑和异步逻辑

同步逻辑:
时钟之间有固定的因果关系,各触发器的是何种端全部连接在一起,并接在系统时钟端,只有当时钟脉冲到来时,电路的状态才能改变。

异步逻辑:
各时钟之间没有固定的因果关系。电路状态的改变由外部输入的变化直接引起。

同步逻辑是时钟之间有固定的因果关系。异步逻辑是各时钟之间没有固定的因果关系。

同步时序逻辑的特点:各触发器的时钟端全部连接在一起,并接在系统时钟端,只有当时钟脉冲到来时,电路的状态才能改变。改变后的状态一直保持在下一个时钟脉冲端的到来。

异步时序逻辑电路的特点:电路中除可以使用带时钟的触发器外,还可以使用不带时钟的触发器和延迟元件作为存储元件,电路中没有统一的时钟,电路状态的改变由外部输入的变化直接引起。

18 FPGA中同步电路和异步电路

同步电路:
存储电路中所有触发器的是何种输入都接在一个时钟脉冲源,因为所有触发器的状态的变化都与所加时钟脉冲信号同步。

异步电路:
电路没有统一的时钟,有些触发器的时钟输入端与时钟脉冲相连,只有这些触发器的状态与时钟脉冲同步,而其他的触发器的状态不与时钟脉冲同步。

同步电路: 存储电路中所有触发器的时钟输入端都接同一个时钟脉冲源,因而所有触发器的状态的变化都与所加的时钟脉冲信号同步。

异步电路:电路没有统一的时钟,有些触发器的时钟输入端与时钟脉冲源相连,这些触发器的状态变化与时钟脉冲同步,而其他触发器的状态变化不与时钟脉冲同步。异步电路主要是组合逻辑电路

19 线与逻辑

线与逻辑是两个输出信号相连可以实现与的功能。

在硬件上,要用OC门来实现(漏极开路 门电路),在输出端口应加一个上拉电阻。

OC(open collector)门,又称 集电极开路门。

漏极开路 门电路

OC门或三态门实现。OC门需要在输出端口加一个上拉电阻。

20 时序设计的实质

电路设计的难点在于时序设计,时序设计的实质就是满足每一个触发器的建立/保持时间的要求。

21 为什么触发器要满足建立时间和保持时间

因为触发器内部数据的形成需要一定的时间,如果不满足建立和保持时间,触发器将进入亚稳态,进入亚稳态后触发器的输出将不稳定,在0和1之间变化,这时需要经过一个恢复时间,其输出才能稳定,但稳定后的值不一定是你的输入值。

通过两级触发器来同步异步输入信号,可以防止异步输入信号对于本级时钟可能不满足建立、保持时间而使本级触发器产生的亚稳态传播到后续的逻辑中,导致亚稳态的传播。

亚稳态 --- 使得输出数据不稳定

22 亚稳态,两级触发器防止亚稳态。

亚稳态是指触发器无法在某个规定的时间段到达一个可以确认的状态。

使用两级触发器来使异步电路同步化的电路叫做一步同位器,只能用来对一位异步信号进行同步。两级触发器可防止亚稳态传播的原理是:

假设第一级触发器的输入不满足其建立保持时间,它在第一脉冲到来后输出的数据为亚稳态,那么在下一个脉冲沿到来之前,其输出的亚稳态数据在一段恢复时间后必须稳定下来。而且稳定的数据必须满足第二级触发器的建立时间。

第二级触发器,第二个时钟脉冲到来之前的一段时间,数据从亚稳态稳定,且满足第二个触发器的建立保持时间,则两级触发器可以防止亚稳态。

23 两级同步器有效的条件

同步器有效的条件:第一级触发器进入亚稳态后的恢复时间 + 第二级触发器的建立时间<=时钟周期。

更确切的说输入脉冲宽度必须大于同步时钟周期与第一级触发器所需保持时间之和。

所以,这样的同步电路对于从较慢的时钟域来的异步信号进入较快的时钟域比较有效,对于进入一个较慢的时钟域,则没有作用。