我是靠谱客的博主 调皮巨人,这篇文章主要介绍手撕代码汇总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.内容请搜索靠谱客的其他文章。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部