文章目录
!!! 务必搞清楚每一个设计的输入和输出信号 !!!<\mark>
1. 计数器
2. 分频器
3. 状态机
3.1 Moore状态机(摩尔)
摩尔型状态机:输出只取决于当前状态,与输入无直接关系。
3.2 Mealy状态机(米利)
米利型:输出取决于当前状态和输入。
摩尔型和米利型状态机的对比:
1)摩尔型更安全。
输出在时钟边沿变化(总是在一个周期后)。在Mealy机器中,输入更改可能会在逻辑完成后立即导致输出更改, 当两台机器互连时出现大问题 - 如果不小心,可能会发生异步反馈。
2)Mealy机器对输入的反应更快
在相同的周期内反应 - 不需要等待时钟。 在Moore机器中,可能需要更多逻辑来将状态解码为输出 - 在时钟边沿之后更多的门延迟。
并非所有时序电路都可以使用Mealy模型实现。 一些时序电路只能作为摩尔机器实现。
3)对于同一个设计来说,米利型的状态少,减少资源的消耗。但是各个状态间的状态跳转更复杂。
4. 序列检测器
4.1 状态机描述
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. 伪随机码发生器
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
- 利用移位寄存器
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
- 利用计数器
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字