项目要求:实现心碎小丑动画
之前有写过点亮一个点阵屏灯的博客,是这次实验的基础https://blog.csdn.net/loveyousosad/article/details/139747255?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22139747255%22%2C%22source%22%3A%22loveyousosad%22%7D
爱心状态机:
Matlab
`timescale 1ns / 1ps
module state_love(
input sys_clk ,
input rst_n ,
output reg[15:0] data_reg
);
// 0xFF,0x99,0x00,0x00,0x81,0xC3,0xE7,0xFF,
reg [15:0] data_reg_1 = 16'h01FF ; //16'b0000_0001_1111_1111 // 4'h01FF
reg [15:0] data_reg_2 = 16'h0299 ;
reg [15:0] data_reg_3 = 16'h0400 ;
reg [15:0] data_reg_4 = 16'h0800 ; ///0000_1000 08
reg [15:0] data_reg_5 = 16'h1081 ; ///0001_0000 10
reg [15:0] data_reg_6 = 16'h20C3 ; ///0010_0000 20
reg [15:0] data_reg_7 = 16'h40E7 ; ///0100_0000 40
reg [15:0] data_reg_8 = 16'h80FF ; ///1000_0000 80
//视觉效应1ms
reg [15:0] cnt_1ms ;
parameter TIME_1ms = 16'd50_000 ;
//状态机
reg [7:0] cur_state ;
reg [7:0] next_state ;
localparam IDLE = 8'b0000_0000 ;
localparam S1 = 8'b0000_0001 ;
localparam S2 = 8'b0000_0010 ;
localparam S3 = 8'b0000_0100 ;
localparam S4 = 8'b0000_1000 ;
localparam S5 = 8'b0001_0000 ;
localparam S6 = 8'b0010_0000 ;
localparam S7 = 8'b0100_0000 ;
localparam S8 = 8'b1000_0000 ;
always@(posedge sys_clk)
if(!rst_n)
cur_state <= IDLE ;
else
cur_state <= next_state ;
always@(*)
case(cur_state)
IDLE :
begin
next_state = S1 ;
end
S1 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state = S2 ;
else
next_state = cur_state ;
end
S2 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state = S3 ;
else
next_state = cur_state ;
end
S3 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state = S4 ;
else
next_state = cur_state ;
end
S4 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state = S5 ;
else
next_state = cur_state ;
end
S5 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state = S6 ;
else
next_state = cur_state ;
end
S6 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state = S7 ;
else
next_state = cur_state ;
end
S7 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state = S8 ;
else
next_state = cur_state ;
end
S8 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state = S1 ;
else
next_state = cur_state ;
end
default:;
endcase
always@(posedge sys_clk)
if (!rst_n)begin
cnt_1ms <= 0 ;
data_reg <= 0 ;end
else
case(cur_state)
IDLE :
begin
cnt_1ms <= 0 ;
data_reg <= 0 ;
end
S1 :
begin
data_reg <= data_reg_1 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
S2 :
begin
data_reg <= data_reg_2 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
S3 :
begin
data_reg <= data_reg_3 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
S4 :
begin
data_reg <= data_reg_4 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
S5 :
begin
data_reg <= data_reg_5 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
S6 :
begin
data_reg <= data_reg_6 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
S7 :
begin
data_reg <= data_reg_7 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
S8 :
begin
data_reg <= data_reg_8 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
default:;
endcase
endmodule
心碎状态机:
Matlab
`timescale 1ns / 1ps
module state_d_love(
input sys_clk ,
input rst_n ,
output reg[15:0] data_d_love
);
// 0xBD,0x18,0x18,0x18,0x89,0xC9,0xEB,0xFF,
reg [15:0] data_d_love_1 = 16'h01BD ; //16'b0000_0001_1111_1111 // 4'h01FF
reg [15:0] data_d_love_2 = 16'h0218 ;
reg [15:0] data_d_love_3 = 16'h0418 ;
reg [15:0] data_d_love_4 = 16'h0818 ; ///0000_1000 08
reg [15:0] data_d_love_5 = 16'h1089 ; ///0001_0000 10
reg [15:0] data_d_love_6 = 16'h20C9 ; ///0010_0000 20
reg [15:0] data_d_love_7 = 16'h40EB ; ///0100_0000 40
reg [15:0] data_d_love_8 = 16'h80FF ; ///1000_0000 80
//视觉效应1ms
reg [15:0] cnt_1ms ;
parameter TIME_1ms = 16'd50_000 ;
//状态机
reg [7:0] cur_state_2 ;
reg [7:0] next_state_2 ;
localparam IDLE_2 = 8'b0000_0000 ;
localparam S1_2 = 8'b0000_0001 ;
localparam S2_2 = 8'b0000_0010 ;
localparam S3_2 = 8'b0000_0100 ;
localparam S4_2 = 8'b0000_1000 ;
localparam S5_2 = 8'b0001_0000 ;
localparam S6_2 = 8'b0010_0000 ;
localparam S7_2 = 8'b0100_0000 ;
localparam S8_2 = 8'b1000_0000 ;
always@(posedge sys_clk)
if(!rst_n)
cur_state_2 <= IDLE_2 ;
else
cur_state_2 <= next_state_2 ;
always@(*)
case(cur_state_2)
IDLE_2 :
begin
next_state_2 = S1_2 ;
end
S1_2 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state_2 = S2_2 ;
else
next_state_2 = cur_state_2 ;
end
S2_2 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state_2 = S3_2 ;
else
next_state_2 = cur_state_2 ;
end
S3_2 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state_2 = S4_2;
else
next_state_2 = cur_state_2 ;
end
S4_2 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state_2 = S5_2 ;
else
next_state_2 = cur_state_2 ;
end
S5_2 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state_2 = S6_2 ;
else
next_state_2 = cur_state_2 ;
end
S6_2 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state_2 = S7_2 ;
else
next_state_2 = cur_state_2 ;
end
S7_2 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state_2 = S8_2 ;
else
next_state_2 = cur_state_2 ;
end
S8_2 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state_2 = S1_2 ;
else
next_state_2 = cur_state_2 ;
end
default:;
endcase
always@(posedge sys_clk)
if (!rst_n)begin
cnt_1ms <= 0 ;
data_d_love <= 0 ;end
else
case(cur_state_2)
IDLE_2 :
begin
cnt_1ms <= 0 ;
data_d_love <= 0 ;
end
S1_2 :
begin
data_d_love <= data_d_love_1 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
S2_2 :
begin
data_d_love <= data_d_love_2 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
S3_2 :
begin
data_d_love <= data_d_love_3 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
S4_2 :
begin
data_d_love <= data_d_love_4 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
S5_2 :
begin
data_d_love <= data_d_love_5 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
S6_2 :
begin
data_d_love <= data_d_love_6 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
S7_2 :
begin
data_d_love <= data_d_love_7 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
S8_2 :
begin
data_d_love <= data_d_love_8 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
default:;
endcase
endmodule
小丑状态机:
Matlab
`timescale 1ns / 1ps
module state_sad(
input sys_clk ,
input rst_n ,
output reg[15:0] data_sad
);
// 0xBD,0x58,0xBD,0xC3,0xDB,0xC3,0xFF,0xFF,
reg [15:0] data_sad_1 = 16'h01BD ; //16'b0000_0001_1111_1111 // 4'h01FF
reg [15:0] data_sad_2 = 16'h0258 ;
reg [15:0] data_sad_3 = 16'h04BD ;
reg [15:0] data_sad_4 = 16'h08C3 ; ///0000_1000 08
reg [15:0] data_sad_5 = 16'h10DB ; ///0001_0000 10
reg [15:0] data_sad_6 = 16'h20C3 ; ///0010_0000 20
reg [15:0] data_sad_7 = 16'h40FF ; ///0100_0000 40
reg [15:0] data_sad_8 = 16'h80FF ; ///1000_0000 80
//视觉效应1ms
reg [15:0] cnt_1ms ;
parameter TIME_1ms = 16'd50_000 ;
//状态机
reg [7:0] cur_state_3 ;
reg [7:0] next_state_3 ;
localparam IDLE_3 = 8'b0000_0000 ;
localparam S1_3 = 8'b0000_0001 ;
localparam S2_3 = 8'b0000_0010 ;
localparam S3_3 = 8'b0000_0100 ;
localparam S4_3 = 8'b0000_1000 ;
localparam S5_3 = 8'b0001_0000 ;
localparam S6_3 = 8'b0010_0000 ;
localparam S7_3 = 8'b0100_0000 ;
localparam S8_3 = 8'b1000_0000 ;
always@(posedge sys_clk)
if(!rst_n)
cur_state_3 <= IDLE_3 ;
else
cur_state_3 <= next_state_3 ;
always@(*)
case(cur_state_3)
IDLE_3 :
begin
next_state_3 = S1_3 ;
end
S1_3 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state_3 = S2_3 ;
else
next_state_3 = cur_state_3 ;
end
S2_3 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state_3 = S3_3 ;
else
next_state_3 = cur_state_3 ;
end
S3_3 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state_3 = S4_3 ;
else
next_state_3 = cur_state_3 ;
end
S4_3 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state_3 = S5_3 ;
else
next_state_3 = cur_state_3 ;
end
S5_3 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state_3 = S6_3 ;
else
next_state_3 = cur_state_3 ;
end
S6_3 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state_3 = S7_3 ;
else
next_state_3 = cur_state_3 ;
end
S7_3 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state_3 = S8_3 ;
else
next_state_3 = cur_state_3 ;
end
S8_3 :
begin
if ( cnt_1ms == TIME_1ms - 1 )
next_state_3 = S1_3 ;
else
next_state_3 = cur_state_3 ;
end
default:;
endcase
always@(posedge sys_clk)
if (!rst_n)begin
cnt_1ms <= 0 ;
data_sad <= 0 ;end
else
case(cur_state_3)
IDLE_3 :
begin
cnt_1ms <= 0 ;
data_sad <= 0 ;
end
S1_3 :
begin
data_sad <= data_sad_1 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
S2_3 :
begin
data_sad <= data_sad_2 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
S3_3 :
begin
data_sad <= data_sad_3 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
S4_3 :
begin
data_sad <= data_sad_4 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
S5_3 :
begin
data_sad <= data_sad_5 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
S6_3 :
begin
data_sad <= data_sad_6 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
S7_3 :
begin
data_sad <= data_sad_7 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
S8_3 :
begin
data_sad <= data_sad_8 ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
default:;
endcase
endmodule
顶层状态机
Matlab
`timescale 1ns / 1ps
module state_u(
input sys_clk ,
input rst_n ,
input wire[15:0] data_reg ,
input wire[15:0] data_d_love,
input wire[15:0] data_sad ,
output reg [15:0] data
);
///状态机
reg [3:0] cur_state_u ;
reg [3:0] next_state_u ;
reg [30:0] cnt_1s ;
localparam IDLE_u =4'b0000 ;
localparam love =4'b0010 ;
localparam d_love =4'b0100 ;
localparam sad =4'b1000 ;
parameter TIME_1s = 26'd50_000_000;//_000 ;
//状态机第一段
always@(posedge sys_clk )
if(!rst_n)
cur_state_u <= IDLE_u ;
else
cur_state_u <= next_state_u ;
//状态机第二段
always@(*)
case(cur_state_u)
IDLE_u :begin
next_state_u = love ;
end
love :
begin
if (cnt_1s == TIME_1s -1)
next_state_u = d_love ;
else
next_state_u = cur_state_u ;
end
d_love :
begin
if (cnt_1s == TIME_1s -1)
next_state_u = sad ;
else
next_state_u = cur_state_u ;
end
sad :
begin
if (cnt_1s == TIME_1s -1)
next_state_u = love ;
else
next_state_u = cur_state_u ;
end
default:;
endcase
///状态机第三段
always@(posedge sys_clk)
if(!rst_n)begin
cnt_1s <= 0 ;
data <= 0 ;
end
else
case(cur_state_u)
IDLE_u :
begin
cnt_1s <= 0 ;
data <= 0 ;
end
love :
begin
data <= data_reg ;
if ( cnt_1s == TIME_1s -1 )
cnt_1s <= 0 ;
else
cnt_1s <= cnt_1s +1 ;
end
d_love :
begin
data <= data_d_love ;
if ( cnt_1s == TIME_1s -1 )
cnt_1s <= 0 ;
else
cnt_1s <= cnt_1s +1 ;
end
sad :
begin
data <= data_sad ;
if ( cnt_1s == TIME_1s -1 )
cnt_1s <= 0 ;
else
cnt_1s <= cnt_1s +1 ;
end
default:;
endcase
///例化state_love
state_love state_love_u1(
. sys_clk (sys_clk ) ,
. rst_n (rst_n ) ,
. data_reg (data_reg)
);
///例化state_d_love
state_d_love state_d_love_u1(
. sys_clk (sys_clk ) ,
. rst_n (rst_n ) ,
. data_d_love (data_d_love)
);
///例化state_sad
state_sad state_sad_u1(
. sys_clk (sys_clk ) ,
. rst_n (rst_n ) ,
. data_sad (data_sad)
);
endmodule
顶层输出给74HC595
Matlab
`timescale 1ns / 1ps
module HC595(
input sys_clk ,
input rst_n ,
output SCK ,
output reg RCK ,
output reg DI
);
wire locked ;
wire en ;
reg [3:0] cnt ;
reg [3:0] cnt_bit ;//16位
wire [15:0] data_reg ;
wire [15:0] data_d_love ;
wire [15:0] data_sad ;
wire [15:0] data ;
assign en = ( locked & rst_n )? 1 : 0 ;
/DI模块 需要赋初值/15位的cnt_bit/
在SCK的上升沿赋值
always@(posedge SCK)
if(!rst_n)
cnt_bit <= 0 ;
else if ( en == 1 )begin
if ( cnt_bit == 4'd15 )
cnt_bit <= 0 ;
else
cnt_bit <= cnt_bit +1 ;
end
else
cnt_bit <= 0 ;
always@(negedge SCK)
if(!rst_n)
DI <= 0 ;
else if ( en == 1 )
DI <= data[ cnt_bit ] ;
else
DI <= 0 ;
///RCK模块,每一个16位数据传输完毕后都会拉高3~5个时钟周期
always@(posedge sys_clk)
if(!rst_n)
cnt <= 0 ;
else if ( en == 1 )begin
if ( cnt_bit == 0 )begin
if ( cnt == 9 )
cnt <= 0 ;
else
cnt <= cnt +1 ;
end
else
cnt <= 0 ;
end
else
cnt <= 0 ;
always@(posedge sys_clk )
if (!rst_n)
RCK <= 0 ;
else if ( en == 1 )begin
if (cnt_bit == 0 && cnt >= 5 && cnt <= 7 )
RCK <= 1 ;
else
RCK <= 0 ;
end
else
RCK <= 0 ;
/大家千万别像我一样例化锁相环出来的信号,会不稳定大概率会导致实验失败
// /SCK模块例化
// PLL_clk_5M PLL_clk_5M_u1(
// . sys_clk(sys_clk) ,
// . rst_n (rst_n ) ,
// . locked (locked ) ,
// . SCK (SCK )
// );
//心碎小丑状态机
state_u state_u_u1(
. sys_clk ( sys_clk ) ,
. rst_n ( rst_n ) ,
. data_reg ( data_reg ) ,
. data_d_love ( data_d_love) ,
. data_sad ( data_sad ) ,
. data ( data )
);
//----------- Begin Cut here for INSTANTIATION Template ---// INST_TAG
clk_wiz_0 instance_name
(
// Clock out ports
.clk_5M(SCK), // output clk_5M
// Status and control signals
.resetn(rst_n), // input resetn
.locked(locked), // output locked
// Clock in ports
.sys_clk(sys_clk)); // input sys_clk
// INST_TAG_END ------ End INSTANTIATION Template ---------
endmodule
实验结果:
619