一、实验要求
实现同步FIFO回环测试,通过串口产生数据,写入到FIFO内部,当检测到按键信号到来,将FIFO里面的数据依次读出。
二、信号流向图
三、状态转换图
四、程序设计
(1)按键消抖模块
`timescale 1ns / 1ps
module key_debounce(
input sys_clk ,
input rst_n ,
input key ,
output key_flag
);
// parameter delay = 10_000_00 ;
parameter delay = 10_0;//00_00 ; //测试用
reg[19:0] cnt ;
always@(posedge sys_clk )
if(!rst_n)
cnt <= 0 ;
else if ( key == 0 )begin
if ( cnt == delay -1 )
cnt <= cnt ;
else
cnt <= cnt +1 ;
end
else
cnt <= 0 ;
assign key_flag = ( cnt == delay - 2 )?1:0 ;
endmodule
(2)接收端模块
`timescale 1ns / 1ps
module rx_uart(
input sys_clk ,
input rst_n ,
input rx_data ,//[0]起始位 [12345678]数据位 [9]校验位 [10]停止位
output reg[7:0] uart_data ,
output reg rx_done
);
parameter SYSCLK = 50_000_000 ;
parameter Baud = 115200 ;
parameter COUNT = SYSCLK/Baud;
parameter MID = COUNT/2 ;
//start_flag
wire start_flag ;
reg rx_reg1 ;
reg rx_reg2 ;
always@(posedge sys_clk )
if(!rst_n)begin
rx_reg1 <= 1 ;
rx_reg2 <= 1 ;
end
else
begin
rx_reg1 <= rx_data ;
rx_reg2 <= rx_reg1 ;
end
assign start_flag = ~rx_reg1 & rx_reg2 ;
///rx_flag
reg rx_flag ;
reg[4:0] cnt_bit ;
reg[9:0] cnt ;
always@(posedge sys_clk )
if(!rst_n)
rx_flag <= 0 ;
else if ( start_flag == 1 )
rx_flag <= 1 ;
else if ( cnt_bit == 10 && cnt == COUNT -1 )
rx_flag <= 0 ;
else
rx_flag <= rx_flag ;
///cnt434
always@(posedge sys_clk )
if(!rst_n)
cnt <= 0 ;
else if ( rx_flag == 1 )begin
if ( cnt == COUNT -1 )
cnt <= 0 ;
else
cnt <= cnt +1 ;
end
else
cnt <= 0 ;
//cnt_bit
always@(posedge sys_clk )
if(!rst_n)
cnt_bit <= 0 ;
else if ( rx_flag == 1 )begin
if ( cnt == COUNT - 1 )begin
if ( cnt_bit == 10 )
cnt_bit <= 0 ;
else
cnt_bit <= cnt_bit +1 ;
end
else
cnt_bit <= cnt_bit ;
end
else
cnt_bit <= 0 ;
//data_reg
reg[8:0] data_reg ;
always@(posedge sys_clk )
if(!rst_n) ///cnt_bit : [0] 12345678 [9] [10]
data_reg <= 0 ;///data_reg : 01234567 [8]
else if ( rx_flag == 1 )begin
if ( cnt_bit > 0 && cnt_bit < 10 && cnt == MID - 1 )
data_reg[ cnt_bit - 1 ] <= rx_data ;
else
data_reg <= data_reg ;
end
else
data_reg <= 0 ;
///check
reg check ;
parameter MODE_CHECK = 0 ;
always@(posedge sys_clk )
if(!rst_n)
check <= 0 ;
else if ( rx_flag == 1 )begin
if ( cnt_bit == 10 )
check <= ^data_reg ;
else
check <= check ;
end
else
check <= 0 ;
//uart_data
always@(posedge sys_clk )
if(!rst_n)
uart_data <= 0 ;
else if ( rx_flag == 1 )begin
if ( cnt_bit == 10 && cnt == MID - 1 && check == MODE_CHECK )
uart_data <= data_reg[7:0] ;
else
uart_data <= uart_data ;
end
else
uart_data <= uart_data ;
///rx_done
always@(posedge sys_clk )
if(!rst_n)
rx_done <= 0 ;
else if ( rx_flag == 1 )begin
if ( cnt_bit == 10 && cnt == COUNT -1 )
rx_done <= 1 ;
else
rx_done <= 0 ;
end
else
rx_done <= 0 ;
endmodule
(3)发送端模块
`timescale 1ns / 1ps
module tx_uart(
input sys_clk ,
input rst_n ,
input [7:0] fifo_out ,
input tx_start ,
output reg tx_data ,
output reg tx_done
);
parameter SYSCLK = 50_000_000 ;
parameter Baud = 115200 ;
parameter COUNT = SYSCLK/Baud;
parameter MID = COUNT/2 ;
//start_flag
reg tx_reg1 ;
reg tx_reg2 ;
wire start_flag ;
always@(posedge sys_clk )
if(!rst_n)begin
tx_reg1 <= 0 ;
tx_reg2 <= 0 ;
end
else
begin
tx_reg1 <= tx_start ;
tx_reg2 <= tx_reg1 ;
end
assign start_flag = tx_reg1 & ~tx_reg2 ;
//tx_flag
reg tx_flag ;
reg[4:0] cnt_bit ;
reg[9:0] cnt ;
always@(posedge sys_clk )
if(!rst_n)
tx_flag <= 0 ;
else if ( start_flag == 1 )
tx_flag <= 1 ;
else if ( cnt_bit == 10 && cnt == COUNT -1 )
tx_flag <= 0 ;
else
tx_flag <= tx_flag ;
///cnt
always@(posedge sys_clk )
if(!rst_n)
cnt <= 0 ;
else if ( tx_flag == 1 )begin
if ( cnt == COUNT -1 )
cnt <= 0 ;
else
cnt <= cnt +1 ;
end
else
cnt <= 0 ;
///cnt_bit
always@(posedge sys_clk )
if(!rst_n)
cnt_bit <= 0 ;
else if ( tx_flag == 1 )begin
if ( cnt == COUNT -1 )begin
if ( cnt_bit == 10 )
cnt_bit <= 0 ;
else
cnt_bit <= cnt_bit +1 ;
end
else
cnt_bit <= cnt_bit ;
end
else
cnt_bit <= 0 ;
//tx_data
parameter MODE_CHECK = 0 ;
always@(posedge sys_clk )
if(!rst_n) //cnt_bit:[0] 12345678 [9] [10]
tx_data <= 0 ; //uart_data: 01234567
else if ( tx_flag == 1 )begin
if ( cnt_bit > 0 && cnt_bit < 9 && cnt == MID -1 )
tx_data <= fifo_out[ cnt_bit -1 ] ;
else if ( cnt_bit == 0 )
tx_data <= 0 ;
else if ( cnt_bit == 10)
tx_data <= 1 ;
else if ( cnt_bit == 9 )
tx_data <= ( MODE_CHECK == 0 )?^fifo_out:~^fifo_out ;
else
tx_data <= tx_data ;
end
else
tx_data <= 1 ;
///tx_done
always@(posedge sys_clk )
if(!rst_n)
tx_done <= 0 ;
else if ( tx_flag == 1 )begin
if ( cnt_bit == 10 && cnt == COUNT -1 )
tx_done <= 1 ;
else
tx_done <= 0 ;
end
else
tx_done <= 0 ;
endmodule
(4)fifo控制模块
`timescale 1ns / 1ps
module common_fifo_ctrl(
input sys_clk ,
input rst_n ,
input [7:0] uart_data ,
input rx_done ,
input tx_done ,
input key_flag ,
output reg tx_start ,
output reg[7:0] fifo_out
);
reg [7 : 0] din ;
reg wr_en ;
reg rd_en ;
wire [7 : 0] dout ;
wire full ;
wire wr_ack ;
wire empty ;
wire valid ;
wire [3 : 0] data_count;
localparam IDLE = 3'd0 ;
localparam WRITE = 3'd1 ;
localparam WAIT = 3'd2 ;
localparam TEXT = 3'd3 ;
reg[2:0] cur_state ;
reg[2:0] next_state ;
//state1
always@(posedge sys_clk )
if(!rst_n)
cur_state <= IDLE ;
else
cur_state <= next_state ;
//state2
always@(*)
case(cur_state)
IDLE :
begin
next_state = WRITE ;
end
WRITE :
begin
if( full == 1 )
next_state = WAIT ;
else
next_state = cur_state ;
end
WAIT :
begin
if ( key_flag == 1 )
next_state = TEXT ;
else
next_state = cur_state ;
end
TEXT :
begin
if( empty == 1 )
next_state = IDLE ;
else
next_state = cur_state ;
end
default:;
endcase
///state3
always@(posedge sys_clk )
if(!rst_n)begin
din <= 0 ;
wr_en <= 0 ;
rd_en <= 0 ;
fifo_out <= 0 ;
tx_start <= 0 ;
end
else
case(cur_state)
IDLE :
begin
din <= 0 ;
wr_en <= 0 ;
rd_en <= 0 ;
fifo_out <= 0 ;
tx_start <= 0 ;
end
WRITE :
begin
if ( rx_done )begin
wr_en <= 1 ;
din <= uart_data ;
end
else
wr_en <= 0 ;
end
WAIT :
begin
tx_start <= 0 ;
if (key_flag == 1 ) //只有一个时钟周期能读完吗?
rd_en <= 1 ; //答:此时uart_data是并行数据,传输仅需1个时钟周期
else
rd_en <= 0 ;
end
TEXT :
begin
if(valid)
tx_start <= 1 ;
else
tx_start <= 0 ;
if(tx_done)
rd_en <= 1 ;
else
rd_en <= 0 ;
if(valid)
fifo_out <= dout ;
else
fifo_out <= fifo_out ;
end
default:;
endcase
//----------- Begin Cut here for INSTANTIATION Template ---// INST_TAG
fifo_generator_0 fifo1 (
.clk(sys_clk ), // input wire clk
.srst(~rst_n), // input wire srst
.din(din), // input wire [7 : 0] din
.wr_en(wr_en), // input wire wr_en
.rd_en(rd_en), // input wire rd_en
.dout(dout), // output wire [7 : 0] dout
.full(full), // output wire full
.wr_ack(wr_ack), // output wire wr_ack
.empty(empty), // output wire empty
.valid(valid), // output wire valid
.data_count(data_count) // output wire [3 : 0] data_count
);
// INST_TAG_END ------ End INSTANTIATION Template ---------
endmodule
(5)顶层
`timescale 1ns / 1ps
module TOP(
input sys_clk ,
input rst_n ,
input key ,
input rx_data ,
output tx_data
);
///key_debounce
wire key_flag ;
key_debounce key_debounce_u1(
. sys_clk (sys_clk ) ,
. rst_n (rst_n ) ,
. key (key ) ,
. key_flag (key_flag)
);
///uart_rx
wire [7:0] uart_data ;
wire rx_done ;
rx_uart rx_uart_u1(
. sys_clk ( sys_clk ) ,
. rst_n ( rst_n ) ,
. rx_data ( rx_data ) ,//[0]起始位 [12345678]数据位 [9]校验位 [10]停止位
. uart_data (uart_data) ,
. rx_done ( rx_done )
);
///uart_tx
wire tx_done ;
wire [7:0] fifo_out ;
wire tx_start ;
tx_uart tx_uart_u1(
. sys_clk (sys_clk ) ,
. rst_n (rst_n ) ,
. fifo_out (fifo_out ) ,
. tx_start (tx_start ) ,
. tx_data (tx_data ) ,
. tx_done (tx_done )
);
///fifo
common_fifo_ctrl common_fifo_ctrl_u1(
. sys_clk (sys_clk ) ,
. rst_n (rst_n ) ,
. uart_data (uart_data) ,
. rx_done (rx_done ) ,
. tx_done (tx_done ) ,
. key_flag (key_flag ) ,
. tx_start (tx_start ) ,
. fifo_out (fifo_out )
);
endmodule
五、仿真结果
程序:
`timescale 1ns / 1ps
module test_TOP( );
reg sys_clk ;
reg rst_n ;
reg key ;
reg rx_data ;
wire tx_data ;
parameter SYSCLK = 50_000_000 ;
parameter Baud = 115200 ;
parameter COUNT = SYSCLK/Baud;
parameter MID = COUNT/2 ;
initial
begin
sys_clk = 0 ;
rst_n = 0 ;
key = 1 ;
#10
rst_n = 1 ;
#200000
key = 0 ;
end
always #1 sys_clk = ~sys_clk ;
initial
begin
uart_out ( 8'hCC );
uart_out ( 8'hE8 );
uart_out ( 8'h18 );
uart_out ( 8'h78 );
uart_out ( 8'h66 );
uart_out ( 8'h1E );
uart_out ( 8'hCC );
uart_out ( 8'h9F );
uart_out ( 8'h66 );
uart_out ( 8'h9F );
uart_out ( 8'h33 );
uart_out ( 8'h1E );
uart_out ( 8'hCC );
uart_out ( 8'h9F );
uart_out ( 8'h18 );
uart_out ( 8'h33 );
uart_out ( 8'hCC );
end
//任务函数
task uart_out ;
input [8:0] DATA ;
begin
rx_data = 1 ; ///空闲位初始
#20
rx_data = 0 ;
#(COUNT*2) rx_data = DATA[0] ;
#(COUNT*2) rx_data = DATA[1] ;
#(COUNT*2) rx_data = DATA[2] ;
#(COUNT*2) rx_data = DATA[3] ;
#(COUNT*2) rx_data = DATA[4] ;
#(COUNT*2) rx_data = DATA[5] ;
#(COUNT*2) rx_data = DATA[6] ;
#(COUNT*2) rx_data = DATA[7] ;
#(COUNT*2) rx_data = 0 ;
#(COUNT*2) rx_data = 1 ;
#(COUNT*2) ;
end
endtask
TOP TOP_1(
. sys_clk (sys_clk) ,
. rst_n (rst_n ) ,
. key (key ) ,
. rx_data (rx_data) ,
. tx_data (tx_data)
);
endmodule
实验结果: