sky06笔记下

发布于:2024-04-05 ⋅ 阅读:(100) ⋅ 点赞:(0)

1.边沿检测
检测输入信号din的上升沿,并输出pulse

module edge_check (
clk,
rstn,
din,
pulse
);
input wire clk,rstn;
input wire din;
output reg pulse;

wire din_dly;

always @(posedge clk or negedge rstn)begin
	if(!rstn)
		din_dly <= 1'b0;
	else
		din_dly <= din;		
end

pulse = din & (!din_dly);
endmodule

2.计数器

module counter(
clk,
rstn,
en,
cnt
);
input wire clk,rstn,en;
output reg [3:0] cnt;
always @(posedge clk or negedge rstn)begin
	if (!rstn)
		cnt <= 4'b0;
	else if (en)
		cnt <= cnt + 1;
	else 
		cnt <= cnt;
end
endmodule

testbench:

module tb_counter();

reg clk,rstn,en;

always #5 clk = ~clk;

initial begin
    clk = 0;
    rstn = 1;
    en = 0;
    #20;
    #1;
    rstn = 0;
    #30;
    rstn = 1;
    en = 1;
    #500;
    en = 0;
    #200;
    $finish();
end

counter u_counter(
    .clk    (clk),
    .rstn   (rstn),
    .en     (en),
    .cnt    (  )
);
endmodule

sim:
在这里插入图片描述

3.时序逻辑电路有rstn端,为什么组合电路没有?
电路由一堆时序逻辑和组合逻辑组成,如果时序逻辑全都复位到固定值,组合逻辑的输入也是固定值,那么组合逻辑的输出也是固定值。

4.移位寄存器shift-register
shift to higher bit

reg [3:0] sf;
always @(posedge clk)begin
	sf <= {sf[2:0],din};
end

shift to lower bit

reg [3:0] sf;
always @(posedge clk)begin
	sf <= {din,sf[3:1]};
end

双向shift:

reg [3:0] sf;
wire dir;
always @(posedge clk)begin
	if (dir == 0)
		sf <= {sf[2:0],din};
	else
		sf <= {din,sf[3:1]};
end

5.状态机类型
Mearly型:输出由当前状态和输入共同决定;
Moore型:输出只与当前状态有关。
实际工程设计中,主要关心逻辑功能,不太关心类型。因为在PPA上,没有明显优劣。
6.用FSM实现“1011”序列检测,每周期输入1bit,检测到1011后,在下一周期输出一个周期的高电平。

module detect(
clk,
rstn,
din,
en,
dout
);
input wire clk,rstn,din,en;
output reg dout;
reg [1:0] state,nstate;

parameter [1:0] s_idle = 00;
parameter [1:0] s_1 = 01;
parameter [1:0] s_10 = 10;
parameter [1:0] s_101 = 11;
//简洁写法parameter [1:0]  s_idle = 'd0, s_1 = 'd1, s_10 = 'd2, s_101 = 'd3;
//时序逻辑
always @(posedge clk or negedge rstn)begin
	if (!rstn)
		state <= s_idle;
	else if (en)
	  state <= nstate;	
end
always @(posedge clk or negedge rstn)
	if (!rstn)
		dout <= 1'b0;
	else if(en &&(state == s_101)&&din)
		dout <= 1'b1;
	else 
		dout <= 1'b0;
//组合逻辑
always @(*)begin
if(en)begin
	case(state)
		s_idle:if (din == 1) nstate = s_1; else nstate = s_idle;
		s_1:   if (din == 1) nstate = s_1; else nstate = s_10;
		s_10:  if (din == 1) nstate = s_101; else nstate = s_idle;
		s_101: if (din == 1) nstate = s_1; else nstate = s_10;
		default:nstate = s_idle;
	endcase
end
else 
	nstate = state;//en无效的话,次态等于现态。
endmodule

if ,else if 要配全,否则会综合出latch。
testbench:

module tb_detect();
    reg clk,rstn,din,en;
    wire dout;

    always #5 clk = ~clk;
    initial begin
        clk = 0;
        rstn = 1;
        din = 0;
        en =0;
        #20;
        #1;
        rstn = 0;
        #20;
        rstn = 1;
        en = 1;
        repeat(20)begin
			@(posedge clk) din <= {$random}%2; //产生20个随机1bit数
		end
        repeat(5) @(posedge clk);
        $finish();
    end
detect u_detect(
.clk (clk),
.rstn (rstn),
.din (din),
.en (en),
.dout (dout)
);
endmodule

在这里插入图片描述也可以s_idle,s_1,s_10,s_101,s_1011五种状态来写,但是state和nstate就需要3bit位宽来储存,会消耗更多的资源。
7.较长的序列检测,比如0110101,且中间有重叠部分。
用shift_register,以1011为例:

module detect_shift(
clk,
rstn,
en,
din,
match
);
input wire clk,rstn,en,din;
output reg match;

reg [2:0] shift_reg;
always @(posedge clk or negedge rstn)begin
	if(!rstn)
		shift_reg <= 3'b0;
	else
		shift_reg <= {shift_reg[1:0],din};
end
always @(posedge clk or negedge rstn)begin
	if(!rstn)
		match <= 1'b0;
	else if (en&&(shift_reg == 3'b101)&&din)
		match <= 1'b1;
	else
		match <= 1'b0;
end

//second way
/*
reg [3:0] shift_reg;
always @(posedge clk or negedge rstn)begin
	if(!rstn)
		shift_reg <= 4'b0;
	else
		shift_reg <= {shift_reg[2:0],din};
end
always @(posedge clk or negedge rstn)begin
	if(!rstn)
		match <= 1'b0;
	else if (en&&(shift_reg == 4'b1011))
		match <= 1'b1;
	else
		match <= 1'b0;
end

endmodule

在这里插入图片描述
在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到