我是靠谱客的博主 调皮巨人,最近开发中收集的这篇文章主要介绍手撕代码汇总1. 计数器2. 分频器3. 状态机4. 序列检测器5. 序列生成器6. 伪随机码发生器7. 异步复位,同步释放8. 超前进位加法器9. FIR滤波器10. 自动售卖机11. 红绿灯12. 格雷码计数器13. 并串转换14. 串并转换14. 同步FIFO15. 异步FIFO,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章目录

  • 1. 计数器
  • 2. 分频器
  • 3. 状态机
    •   3.1 Moore状态机(摩尔)
    •   3.2 Mealy状态机(米利)
  • 4. 序列检测器
    •   4.1 状态机描述
    •   4.2 移位寄存器
  • 5. 序列生成器
  • 6. 伪随机码发生器
  • 7. 异步复位,同步释放
  • 8. 超前进位加法器
  • 9. FIR滤波器
  • 10. 自动售卖机
  • 11. 红绿灯
  • 12. 格雷码计数器
  • 13. 并串转换
  • 14. 串并转换
  • 14. 同步FIFO
  • 15. 异步FIFO


!!! 务必搞清楚每一个设计的输入和输出信号 !!!<mark>

1. 计数器

  计数器

2. 分频器

  分频器

3. 状态机

  关于摩尔型状态机与米利型状态机的区别

  3.1 Moore状态机(摩尔)

  摩尔型状态机:输出只取决于当前状态,与输入无直接关系。
在这里插入图片描述

  3.2 Mealy状态机(米利)

  米利型:输出取决于当前状态和输入。
在这里插入图片描述

摩尔型和米利型状态机的对比:
  1)摩尔型更安全
  输出在时钟边沿变化(总是在一个周期后)。在Mealy机器中,输入更改可能会在逻辑完成后立即导致输出更改, 当两台机器互连时出现大问题 - 如果不小心,可能会发生异步反馈。
  2)Mealy机器对输入的反应更快
  在相同的周期内反应 - 不需要等待时钟。 在Moore机器中,可能需要更多逻辑来将状态解码为输出 - 在时钟边沿之后更多的门延迟。
    并非所有时序电路都可以使用Mealy模型实现。 一些时序电路只能作为摩尔机器实现。
    3)对于同一个设计来说,米利型的状态少,减少资源的消耗。但是各个状态间的状态跳转更复杂。

4. 序列检测器

  4.1 状态机描述

    状态机描述_序列检测器

    next_state另一种写法

    这个有电路图

  4.2 移位寄存器

    移位寄存器_序列检测器

    这个带仿真图

两种方法的对比:
   1)跟用状态机实现的区别在于,使用移位寄存器需要存储所有的码字,因此如果序列长度为N,则该方法需要消耗的寄存器就是N个。而使用状态机实现时,每个状态代表部分码字,如果使用十进制编码,则只需要使用log2(N)个寄存器即可编码所有状态,从寄存器资源的角度来看FSM实现起来代价较小。
   2)此外,寄存器版本每来一个码元都要比较所有码字,因此需要消耗N个比较器,而FSM的的状态寄存器每一位在状态转移时都需要不同的译码逻辑,如果状态转移比较简单,组合逻辑可能会比移位寄存器少,状态转移复杂的话就不好说了。
   3)当然,移位寄存器的版本编码更加简洁明了。

5. 序列生成器

   生成序列01011011101111…依次类推
   生成序列01011011101111
思路:有2个0的时候有2个1,有3个0的时候有3个1…

   循环产生序列信号001011
   移位寄存器方法除了可以有一个输入序列的接口,还可以在初始化时将序列填入移位寄存器中。代码如下:
  产生序列信号11010111

module seq_gen(
input                                   clk,
input                                   rst_n,
output                                  seq );

reg [7:0]out_seq;
always@(posedge clk or negedge rst_n)
  if(!rst_n) out_seq <= 8'b11010111;
  else out_seq <= {out_seq[6:0],out_seq[7]};

assign seq = out_seq[7];

6. 伪随机码发生器

  4级伪随机码发生器
  模运算

7. 异步复位,同步释放

  异步复位,同步释放

8. 超前进位加法器

半加器和的输出=A和B的异或;
在这里插入图片描述
图源
在这里插入图片描述

module half_adder(
input  a,
input b, 
output sum,
output c_out
);

assign sum = a^b;
assign cout = a&b;
endmodule

全加器和的输出=A、B、C的异或。
在这里插入图片描述
图源
在这里插入图片描述

module full_adder(
	//输入信号,ain表示被加数,bin表示加数,cin表示低位向高位的进位
	input ain,bin,cin,
	//输出信号,cout表示向高位的进位,sum表示本位的相加和
	output reg cout,sum

);
reg s1,s2,s3;
always @(ain or bin or cin) begin
	sum=(ain^bin)^cin;//本位和输出表达式
	s1=ain&cin;
	s2=bin&cin;
	s3=ain&bin;
	cout=(s1|s2)|s3;//高位进位输出表达式
end
endmodule

两个半加器可以构成一个全加器。
在这里插入图片描述
将多个“一位全加器”级联起来,可以变成“多位全加器”,上一个全加器的“进位输出”连到下一个全加器的“进位输入”。比如8位全加器如下:
图源
在这里插入图片描述
  级联多位全加器高位需要低位的进位位,故位宽增大时,加法的组合逻辑不断增大,延时非常大,超前进位加法器解决了这一问题。
  超前进位加法器 (Carry-Lookahead Adder,CLA)是高速加法器,每一级进位有附加的组合电路产生。高位的运算不需要地位的等待,因此速度很高。
数字电路基础知识(四) 加法器-半加器、全加器与超前进位加法器
在这里插入图片描述
多位超前进位加法器


以全加器代码为例说明门级,数据流级,行为级建模的区别

  • 数据流建模,一般用assign声明描述电路行为(连续赋值语句。因此这里的输出必须设置成wire类型)
  • 行为级建模,一般用initial 或者always (过程连续赋值语句,因为这里有always,输出必须设置成reg类型的)

9. FIR滤波器

10. 自动售卖机

  自动贩售机米利型_B站视频_FPGA探索者
   自动贩售机摩尔型_B站视频

  • 状态机实现方式
      请设计状态机电路,实现自动售卖机功能,A饮料5元钱,B饮料10元钱,售卖机可接收投币5元钱和10元钱,每次投币只可买一种饮料,考虑找零的情况。
    FPGA开发/数字IC求职系列(刷题篇)(8)——牛客网Verilog企业真题01哲K

`timescale 1ns/1ns

module sale(
   input                clk   ,
   input                rst_n ,
   input                sel   ,//sel=0,5$dranks,sel=1,10&=$drinks
   input          [1:0] din   ,//din=1,input 5$,din=2,input 10$
 
   output   reg  [1:0] drinks_out,//drinks_out=1,output 5$ drinks,drinks_out=2,output 10$ drinks
   output  reg        change_out   
);
    
    parameter   IDLE  = 2'b01,
                B_5   = 2'b10;
    reg [1:0] curr_state;
    reg [1:0] next_state;
    
    always@(posedge clk or negedge rst_n)begin
        if(~rst_n)
            curr_state <= IDLE;
        else
            curr_state <= next_state;
    end
    
    always@(*)
        if(~rst_n)
            next_state <= IDLE;
        else begin
            case(curr_state) 
                IDLE:
                    begin
                        case({sel,din}) 
                            3'b101:next_state <= B_5;
                            default:next_state <= IDLE;
                        endcase
                    end
                B_5 :
                    begin
                        case({sel,din})
                            3'b100:next_state <= B_5;
                            default:next_state <= IDLE;
                        endcase
                    end
                default:next_state <= IDLE;
            endcase
        end
    
    always@(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            drinks_out <= 2'd0;
            change_out <= 1'b0;
        end
        else begin
            case(curr_state)
                IDLE:
                    begin
                        case({sel,din})
                            3'b001:begin drinks_out <= 2'd1;change_out <= 1'b0; end
                            3'b010:begin drinks_out <= 2'd1;change_out <= 1'b1; end
                            3'b110:begin drinks_out <= 2'd2;change_out <= 1'b0; end
                            default:begin drinks_out <= 2'd0;change_out <= 1'b0; end
                        endcase
                    end
                B_5:
                    begin
                        case({sel,din})
                            3'b101:begin drinks_out <= 2'd2;change_out <= 1'b0; end
                            3'b110:begin drinks_out <= 2'd2;change_out <= 1'b1; end
                            default:begin drinks_out <= 2'd0;change_out <= 1'b0; end
                        endcase
                    end
                default:
                    begin
                        drinks_out <= 2'd0;
                        change_out <= 1'b0;
                    end
            endcase
        end
    end

endmodule
  • 输入金额累加判断
      设计一个自动贩售机,输入货币有三种,为0.5/1/2元,饮料价格是1.5元,要求进行找零,找零只会支付0.5元。
       ps:投入的货币会自动经过边沿检测并输出一个在时钟上升沿到1,在下降沿到0的脉冲信号,注意rst为低电平复位

11. 红绿灯

12. 格雷码计数器

13. 并串转换

并串转换

14. 串并转换

https://blog.csdn.net/vivid117/article/details/102021707

  1. 利用移位寄存器
module serial_parallel(
    input           clk,
    input           rst_n,en,
    input           data_i,   //一位输入
    output   reg [7:0] data_o	//8位并行输出
    );

always @(posedge clk or negedge rst_n) begin
	if (rst_n == 1'b0)
		data_o <= 8'b0;
	else if (en == 1'b1)
		data_o <= {data_o[6:0], data_i};	//低位先赋值
		//data_o <= {data_i,data_o[7:1],};	//高位先赋值
	else
		data_o <= data_o;
end

endmodule
  1. 利用计数器
module serial_parallel(
    input           clk,
    input           rst_n,
    input           data_i,
    output   reg [7:0] data_o
);

//msb first   most significant bit 表示二进制数据的最高位
reg     [2:0]   cnt; 	//计数器0-7  
always @(posedge clk or negedge rst_n)begin
    if(rst_n == 1'b0)begin
        data_o <= 8'b0;
        cnt <= 3'd0;
    end
    else begin
        data_o[7 - cnt] <= data_i;	高位先赋值
        cnt <= cnt + 1'b1;
    end
end

/*
//lsb first	(least significant bit) 表示二进制数据的最低位

reg     [2:0]   cnt;
always @(posedge clk or negedge rst_n)begin
    if(rst_n == 1'b0)begin
        data_o <= 8'b0;
        cnt <= 3'd0;
    end
    else begin
        data_o[cnt] <= data_i;   //低位先赋值
        cnt <= cnt + 1'b1;
    end
end
*/

endmodule

14. 同步FIFO

15. 异步FIFO

改变字体颜色:
浅红色文字:浅红色文字:
深红色文字:深红色文字
浅绿色文字:浅绿色文字

深绿色文字:深绿色文字

改变字体大小:
size为1:size为1

size为2:size为2

size为10:size为10

改变字体背景:

背景色的设置是按照十六进制颜色值:#7FFFD4
背景色的设置是按照十六进制颜色值:#FF83FA
背景色的设置是按照十六进制颜色值:#D1EEEE
背景色的设置是按照十六进制颜色值:#C0FF3E
背景色的设置是按照十六进制颜色值:#54FF9F

改变字体:
我是黑体字
我是宋体字
我是微软雅黑字
我是fantasy字
我是Helvetica字

最后

以上就是调皮巨人为你收集整理的手撕代码汇总1. 计数器2. 分频器3. 状态机4. 序列检测器5. 序列生成器6. 伪随机码发生器7. 异步复位,同步释放8. 超前进位加法器9. FIR滤波器10. 自动售卖机11. 红绿灯12. 格雷码计数器13. 并串转换14. 串并转换14. 同步FIFO15. 异步FIFO的全部内容,希望文章能够帮你解决手撕代码汇总1. 计数器2. 分频器3. 状态机4. 序列检测器5. 序列生成器6. 伪随机码发生器7. 异步复位,同步释放8. 超前进位加法器9. FIR滤波器10. 自动售卖机11. 红绿灯12. 格雷码计数器13. 并串转换14. 串并转换14. 同步FIFO15. 异步FIFO所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(70)

评论列表共有 0 条评论

立即
投稿
返回
顶部