一、实验要求
实现同步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 )beginif ( cnt == delay -1 )cnt <= cnt ;elsecnt <= cnt +1 ;endelsecnt <= 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_flagwire start_flag ;reg rx_reg1 ;reg rx_reg2 ;always@(posedge sys_clk )if(!rst_n)beginrx_reg1 <= 1 ;rx_reg2 <= 1 ;endelsebeginrx_reg1 <= rx_data ;rx_reg2 <= rx_reg1 ;endassign start_flag = ~rx_reg1 & rx_reg2 ;///rx_flagreg 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 ;elserx_flag <= rx_flag ;///cnt434always@(posedge sys_clk )if(!rst_n)cnt <= 0 ;else if ( rx_flag == 1 )beginif ( cnt == COUNT -1 )cnt <= 0 ;elsecnt <= cnt +1 ;endelsecnt <= 0 ;//cnt_bitalways@(posedge sys_clk )if(!rst_n)cnt_bit <= 0 ;else if ( rx_flag == 1 )beginif ( cnt == COUNT - 1 )beginif ( cnt_bit == 10 )cnt_bit <= 0 ;elsecnt_bit <= cnt_bit +1 ;endelsecnt_bit <= cnt_bit ; endelsecnt_bit <= 0 ;//data_regreg[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 )beginif ( cnt_bit > 0 && cnt_bit < 10 && cnt == MID - 1 )data_reg[ cnt_bit - 1 ] <= rx_data ;elsedata_reg <= data_reg ;endelsedata_reg <= 0 ;///checkreg check ;parameter MODE_CHECK = 0 ; always@(posedge sys_clk )if(!rst_n)check <= 0 ;else if ( rx_flag == 1 )beginif ( cnt_bit == 10 )check <= ^data_reg ;elsecheck <= check ;endelsecheck <= 0 ;//uart_dataalways@(posedge sys_clk )if(!rst_n)uart_data <= 0 ;else if ( rx_flag == 1 )beginif ( cnt_bit == 10 && cnt == MID - 1 && check == MODE_CHECK )uart_data <= data_reg[7:0] ;elseuart_data <= uart_data ;endelseuart_data <= uart_data ;///rx_donealways@(posedge sys_clk )if(!rst_n)rx_done <= 0 ;else if ( rx_flag == 1 )beginif ( cnt_bit == 10 && cnt == COUNT -1 )rx_done <= 1 ;elserx_done <= 0 ;endelserx_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_flagreg tx_reg1 ;reg tx_reg2 ;wire start_flag ;always@(posedge sys_clk )if(!rst_n)begintx_reg1 <= 0 ;tx_reg2 <= 0 ;endelsebegintx_reg1 <= tx_start ;tx_reg2 <= tx_reg1 ;endassign start_flag = tx_reg1 & ~tx_reg2 ;//tx_flagreg 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 ;elsetx_flag <= tx_flag ;///cntalways@(posedge sys_clk )if(!rst_n)cnt <= 0 ;else if ( tx_flag == 1 )beginif ( cnt == COUNT -1 )cnt <= 0 ;elsecnt <= cnt +1 ;endelsecnt <= 0 ;///cnt_bit always@(posedge sys_clk )if(!rst_n)cnt_bit <= 0 ;else if ( tx_flag == 1 )beginif ( cnt == COUNT -1 )beginif ( cnt_bit == 10 )cnt_bit <= 0 ;elsecnt_bit <= cnt_bit +1 ;endelsecnt_bit <= cnt_bit ;endelsecnt_bit <= 0 ;//tx_dataparameter MODE_CHECK = 0 ;always@(posedge sys_clk )if(!rst_n) //cnt_bit:[0] 12345678 [9] [10]tx_data <= 0 ; //uart_data: 01234567else if ( tx_flag == 1 )beginif ( 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 ;elsetx_data <= tx_data ; endelsetx_data <= 1 ;///tx_donealways@(posedge sys_clk )if(!rst_n)tx_done <= 0 ;else if ( tx_flag == 1 )beginif ( cnt_bit == 10 && cnt == COUNT -1 )tx_done <= 1 ;elsetx_done <= 0 ;endelsetx_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 ;//state1always@(posedge sys_clk )if(!rst_n)cur_state <= IDLE ;elsecur_state <= next_state ;//state2always@(*)case(cur_state)IDLE :beginnext_state = WRITE ;endWRITE :beginif( full == 1 )next_state = WAIT ;elsenext_state = cur_state ;endWAIT :beginif ( key_flag == 1 )next_state = TEXT ;elsenext_state = cur_state ;endTEXT :beginif( empty == 1 )next_state = IDLE ;elsenext_state = cur_state ;enddefault:;endcase///state3always@(posedge sys_clk )if(!rst_n)begindin <= 0 ;wr_en <= 0 ; rd_en <= 0 ; fifo_out <= 0 ;tx_start <= 0 ; endelsecase(cur_state)IDLE :begindin <= 0 ; wr_en <= 0 ; rd_en <= 0 ; fifo_out <= 0 ; tx_start <= 0 ; endWRITE :beginif ( rx_done )beginwr_en <= 1 ; din <= uart_data ;endelsewr_en <= 0 ;endWAIT :begintx_start <= 0 ;if (key_flag == 1 ) //只有一个时钟周期能读完吗?rd_en <= 1 ; //答:此时uart_data是并行数据,传输仅需1个时钟周期elserd_en <= 0 ;endTEXT : beginif(valid)tx_start <= 1 ;elsetx_start <= 0 ;if(tx_done)rd_en <= 1 ;elserd_en <= 0 ;if(valid)fifo_out <= dout ;elsefifo_out <= fifo_out ;enddefault:;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_debouncewire key_flag ;key_debounce key_debounce_u1(. sys_clk (sys_clk ) ,. rst_n (rst_n ) ,. key (key ) ,. key_flag (key_flag) );///uart_rxwire [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 ));///fifocommon_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 ;initialbeginsys_clk = 0 ;rst_n = 0 ;key = 1 ;#10rst_n = 1 ;#200000key = 0 ;endalways #1 sys_clk = ~sys_clk ;initialbeginuart_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 ;beginrx_data = 1 ; ///空闲位初始#20rx_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) ;endendtaskTOP TOP_1(. sys_clk (sys_clk) ,. rst_n (rst_n ) ,. key (key ) ,. rx_data (rx_data) ,. tx_data (tx_data) );endmodule
实验结果: