一、实验要求
将生成好的voe文件里的数据使用rom读取出来,采用串口工具发送给电脑(当按键来临时)。
二、程序设计
按键消抖模块:
`timescale 1ns / 1ps
module key_debounce(
input sys_clk ,
input rst_n ,
input key ,
output key_flag
);
// parameter delay = 100_000_0 ; //20ms
parameter delay = 100;// 测试用
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
接收端模块:
`timescale 1ns / 1ps
module uart_tx(
input sys_clk ,
input rst_n ,
input [7:0] ram_out ,
input tx_start ,
output reg tx_done ,
output reg tx_data
);
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)
tx_data <= 0 ;
else if ( tx_flag == 1 )begin
if ( cnt_bit > 0 && cnt_bit < 9 )
tx_data <= ram_out[cnt_bit -1] ;
else if ( cnt_bit == 0 )
tx_data <= 0 ;
else if ( cnt_bit == 9 )
tx_data <= ( MODE_CHECK == 0 )?^ram_out : ~^ram_out ;
else if ( cnt_bit == 10 )
tx_data <= 1 ;
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
顶层(ROM)模块:
IP参数:
`timescale 1ns / 1ps
///按键来临时,将rom中的数据读出,并通过tx模块返回给PC端
module rom(
input sys_clk ,
input rst_n ,
input key ,
output tx_data
);
wire key_flag ;
wire tx_done ;
reg tx_start ;
reg ena ;
reg[4:0] addra ;
wire[7:0] douta ;
always@(posedge sys_clk )
if(!rst_n)
addra <= 0 ;
else if ( tx_done && addra == 15 )
addra <= 15 ; ///保持在15,不连续输出
else if ( tx_done || key_flag )//key_flag 是因为第一个数据要输出,地址要+1
addra <= addra +1 ;
else
addra <= addra ;
always@(posedge sys_clk )
if(!rst_n)
ena <= 0 ;
else if ( key_flag )
ena <= 1 ;
else if ( tx_done && addra <= 14 )
ena <= 1 ;
else if ( addra == 15 )
ena <= 0 ;
else
ena <= 0 ;
always@(posedge sys_clk )
if (!rst_n)
tx_start <= 0 ;
else if ( key_flag )
tx_start <= 1 ; ///发送第一个数据
else if ( tx_done && addra <= 14)///发送后面的数据
tx_start <= 1 ;
else
tx_start <= 0 ;
//----------- Begin Cut here for INSTANTIATION Template ---// INST_TAG
blk_mem_gen_0 rom (
.clka(sys_clk ), // input wire clka
.ena(ena), // input wire ena
.addra(addra), // input wire [3 : 0] addra
.douta(douta) // output wire [7 : 0] douta
);
// INST_TAG_END ------ End INSTANTIATION Template ---------
key_debounce key_debounce_u1(
. sys_clk (sys_clk ) ,
. rst_n (rst_n ) ,
. key (key ) ,
. key_flag (key_flag)
);
uart_tx uart_tx_u1(
. sys_clk (sys_clk ) ,
. rst_n (rst_n ) ,
. ram_out (douta ) ,
. tx_start(tx_start) ,
. tx_done (tx_done ) ,
. tx_data (tx_data )
);
endmodule
三、仿真结果
仿真程序:
`timescale 1ns / 1ps
module test_rom( );
reg sys_clk ;
reg rst_n ;
reg key ;
wire tx_data ;
initial
begin
sys_clk = 0 ;
rst_n = 0 ;
key = 1 ;
#10
rst_n = 1 ;
#1000
key = 0 ;
end
always #1 sys_clk = ~sys_clk ;
rom rom_1(
. sys_clk (sys_clk) ,
. rst_n (rst_n ) ,
. key (key ) ,
. tx_data (tx_data)
);
endmodule
实验结果: