一、项目要求
要求输入从千位到个位数字给4位数码管,要求分别输入的数字都能显示
二、关键信号流向
三、程序设计
顶层:
`timescale 1ns / 1ps
module TOP(
input sys_clk ,
input rst_n ,
input rx_data ,
output wire[3:0] DIG ,
output wire[7:0] SEG
);
/接收端模块例化
wire [7:0] uart_data ;
wire rx_done ;
uart_rx uart_rx_u1(
. sys_clk (sys_clk ) ,
. rst_n (rst_n ) ,
. rx_data (rx_data ) ,
. uart_data (uart_data) ,
. rx_done (rx_done )
);
//translate模块例化
wire[7:0] trans_data ;
translate translate_u1(
. sys_clk (sys_clk ) ,
. rst_n (rst_n ) ,
. uart_data (uart_data ) ,
. rx_done (rx_done ) ,
. trans_data (trans_data)
);
//conversion模块例化
wire[15:0] number ;
conversion conversion_u1(
. sys_clk ( sys_clk ) ,
. rst_n ( rst_n ) ,
. rx_done ( rx_done ) ,
. trans_data (trans_data) , 0 1 2 3 4
. number ( number )
);
//解码器模块例化
wire [3:0] num ;
wire [7:0] seg ;
decoder decoder_u1(
. num (num) ,
. seg (seg)
);
//数码管模块例化
SEG_state SEG_state_u1(
. sys_clk ( sys_clk) ,
. rst_n ( rst_n ) ,
. number (number ) ,//0~9999
. seg (seg ) ,
. DIG (DIG ) ,
. SEG (SEG ) ,
. num (num )
);
endmodule
接收端模块:
`timescale 1ns / 1ps
module uart_rx(
input sys_clk ,
input rst_n ,
input rx_data ,
output reg[7:0] uart_data,
output reg rx_done
);
parameter SYSCLK = 50_000_000 ;
parameter Baud = 115200 ;
parameter COUNT = SYSCLK/Baud ;//434 传输1比特所需要的时钟周期
parameter MID = COUNT/2 ;
reg rx_reg1 ;
reg rx_reg2 ;
wire start_flag ;
reg rx_flag ;
reg [3:0] cnt_bit ;//0-9
reg [9:0] cnt ;//0-434
reg [7:0] data_reg ;
always@(posedge sys_clk)
if(!rst_n)begin
rx_reg1 <= 1 ;
rx_reg2 <= 2 ;
end
else
begin
rx_reg1 <= rx_data ;
rx_reg2 <= rx_reg1 ;
end
assign start_flag = ~rx_reg1 & rx_reg2 ;
rx_flag
always@(posedge sys_clk)
if(!rst_n)
rx_flag <= 0 ;
else if (start_flag)
rx_flag <= 1 ;
else if ( cnt_bit == 9 && cnt == MID -1)
rx_flag <= 0 ;
else
rx_flag <= rx_flag ;
/cnt 434
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 ;
计数器
always@(posedge sys_clk)
if(!rst_n)
cnt_bit <= 0 ;
else if ( rx_flag)begin
if ( cnt == COUNT -1 )begin
if( cnt_bit == 9 )
cnt_bit <= 0 ;
else
cnt_bit <= cnt_bit +1;
end
else
cnt_bit <= cnt_bit ;
end
else
cnt_bit <= 0 ;
/中间寄存器的赋值
always@(posedge sys_clk)
if(!rst_n)
data_reg <= 0 ;
else if ( rx_flag )begin
if ( cnt == MID -1 && cnt_bit>0 && cnt_bit <9 )
data_reg[cnt_bit -1] <= rx_data ;
else
data_reg <= data_reg ;
end
else
data_reg <= 0 ;
给uart_data赋值
always@(posedge sys_clk )
if(!rst_n)
uart_data <= 0 ;
else if ( rx_flag )begin
if ( cnt_bit == 9 && cnt == MID/4 -1)
uart_data <= data_reg ;
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)begin
if (cnt_bit == 9 && cnt == MID/2 -1)
rx_done <= 1;
else
rx_done <= 0 ;
end
else
rx_done <= 0 ;
endmodule
翻译模块:
这里注释掉了组合逻辑的写法,因为根据仿真,组合逻辑引发了时序问题
`timescale 1ns / 1ps
module translate(
input sys_clk ,
input rst_n ,
input [7:0] uart_data ,
input rx_done ,
output reg[7:0] trans_data
);
// always@(*)
// if(!rst_n)
// trans_data <= 0 ;
// else if (rx_done)
// case(uart_data)
// 8'h30 : trans_data <= 8'd0 ;
// 8'h31 : trans_data <= 8'd1 ;
// 8'h32 : trans_data <= 8'd2 ;
// 8'h33 : trans_data <= 8'd3 ;
// 8'h34 : trans_data <= 8'd4 ;
// default:;
// endcase
// else
// trans_data <= trans_data ;
always@(posedge sys_clk)
if(!rst_n)
trans_data <= 0 ;
else if (rx_done)
case(uart_data)
8'h30 : trans_data <= 8'd0 ;
8'h31 : trans_data <= 8'd1 ;
8'h32 : trans_data <= 8'd2 ;
8'h33 : trans_data <= 8'd3 ;
8'h34 : trans_data <= 8'd4 ;
default:;
endcase
else
trans_data <= trans_data ;
endmodule
转换模块:
`timescale 1ns / 1ps
/*
发送4: 0111 显示4
发送3: 1011 显示3
发送2: 1101 显示2
发送1: 1110 显示1
发送0: 0000 显示0
*/
module conversion(
input sys_clk ,
input rst_n ,
input rx_done ,
input wire[7:0] trans_data , 0 1 2 3 4
output wire[15:0] number
);
/数据处理
reg[14:0] trans_qian ; // 1000-9999
reg[10:0] trans_bai ; //100-999
reg[7:0] trans_shi ; // 10-99
reg[4:0] trans_ge ; //0-9
///状态机///
localparam IDLE = 4'b0000 ;
localparam GE = 4'b0001 ;
localparam SHI = 4'b0010 ;
localparam BAI = 4'b0100 ;
localparam QIAN = 4'b1000 ;
reg[4:0] cur_state ;
reg[4: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 : next_state = QIAN ;
IDLE :
begin
if (rx_done)
next_state = QIAN ;
else
next_state = cur_state ;
end
QIAN :
begin
if(rx_done)
next_state = BAI ;
else
next_state = cur_state ;
end
BAI :
begin
if(rx_done)
next_state = SHI ;
else
next_state = cur_state ;
end
SHI :
begin
if(rx_done)
next_state = GE ;
else
next_state = cur_state ;
end
GE :
begin
if(rx_done)
next_state = IDLE ;
else
next_state = cur_state ;
end
default:;
endcase
state3
always@(posedge sys_clk)
if(!rst_n)
begin
trans_qian <= 0 ;
trans_bai <= 0 ;
trans_shi <= 0 ;
trans_ge <= 0 ;
end
else
case(cur_state)
IDLE :
begin
trans_qian <= 0 ;
trans_bai <= 0 ;
trans_shi <= 0 ;
trans_ge <= 0 ;
end
QIAN : trans_qian <= trans_data * 1000 ;
BAI : trans_bai <= trans_data * 100 ;
SHI : trans_shi <= trans_data * 10 ;
GE : trans_ge <= trans_data * 1 ;
default:;
endcase
assign number = trans_qian + trans_bai + trans_shi + trans_ge ;
endmodule
译码模块:
`timescale 1ns / 1ps
module decoder(
input [3:0] num ,
output reg[7:0] seg
);
always@(*)
case(num)
4'd0: seg = 8'h3f;
4'd1: seg = 8'h06;
4'd2: seg = 8'h5b;
4'd3: seg = 8'h4f;
4'd4: seg = 8'h66;
4'd5: seg = 8'h6d;
4'd6: seg = 8'h7d;
4'd7: seg = 8'h07;
4'd8: seg = 8'h7f;
4'd9: seg = 8'h6f;
default:;
endcase
endmodule
数码管模块:
`timescale 1ns / 1ps
module SEG_state(
input sys_clk ,
input rst_n ,
input wire[15:0] number ,//0~9999
input wire[7:0] seg ,
output wire[3:0] DIG ,
output wire[7:0] SEG ,
output reg[3:0] num
);
parameter MODE = 0 ; ///共阴极
///数据处理
// reg[3:0] num ;
// reg[7:0] seg ;
reg[3:0] dig ;
wire[3:0] num_ge ;
wire[3:0] num_shi ;
wire[3:0] num_bai ;
wire[3:0] num_qian ;
assign num_ge = number%10 ;
assign num_shi = number/10%10 ;
assign num_bai = number/100%10 ;
assign num_qian = number/1000%10 ;
状态机
// parameter TIME_1ms = 16'd50_000 ;
parameter TIME_1ms = 16'd5 ; //测试用
reg[3:0] cur_state ;
reg[3:0] next_state ;
reg[20:0] cnt_1ms ;
localparam IDLE = 4'b0000 ;
localparam GE = 4'b0001 ;
localparam SHI = 4'b0010 ;
localparam BAI = 4'b0100 ;
localparam QIAN = 4'b1000 ;
always@(posedge sys_clk)
if(!rst_n)
cur_state <= IDLE ;
else
cur_state <= next_state ;
always@(*)
case(cur_state)
IDLE :next_state = GE ;
GE :
begin
if( cnt_1ms == TIME_1ms -1 )
next_state = SHI ;
else
next_state = cur_state ;
end
SHI :
begin
if( cnt_1ms == TIME_1ms -1 )
next_state = BAI ;
else
next_state = cur_state ;
end
BAI :
begin
if( cnt_1ms == TIME_1ms -1 )
next_state = QIAN ;
else
next_state = cur_state ;
end
QIAN :
begin
if( cnt_1ms == TIME_1ms -1 )
next_state = GE ;
else
next_state = cur_state ;
end
default:;
endcase
always@(posedge sys_clk )
if(!rst_n)begin
dig <= 0 ;
cnt_1ms <= 0 ;
num <= 0 ;
end
else
case(cur_state)
IDLE :
begin
dig <= 0 ;
cnt_1ms <= 0 ;
num <= 0;
end
GE :
begin
dig <= 4'b1110 ;
num <= num_ge ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
SHI :
begin
dig <= 4'b1101 ;
num <= num_shi ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
BAI :
begin
dig <= 4'b1011 ;
num <= num_bai ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
QIAN :
begin
dig <= 4'b0111 ;
num <= num_qian ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
default:;
endcase
assign DIG = (MODE == 0 ) ? dig : ~dig ;
assign SEG = (MODE == 0 ) ? seg : ~seg ;
endmodule
四、仿真文件
`timescale 1ns / 1ps
module test_bench( );
reg sys_clk ;
reg rst_n ;
reg rx_data ;
wire[3:0] DIG ;
wire[7:0] SEG ;
parameter SYSCLK = 50_000_000 ;
parameter Baud = 115200 ;
parameter COUNT = SYSCLK/Baud ;
parameter MID = COUNT/2 ;
initial
begin
sys_clk = 0 ;
rst_n = 0 ;
#10
rst_n = 1 ;
end
always #1 sys_clk = ~sys_clk ;
initial
begin
uart_out (8'h31) ;
uart_out (8'h32) ;
uart_out (8'h33) ;
uart_out (8'h34) ;
end
任务函数
task uart_out ;
input [7: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 = 1 ;
#(COUNT*2) ;//停止位也需要时间
#200;//0_000 ;
end //2ms数据发送的时间至少要大于点阵屏切换数据的时间(1ms)
endtask
TOP TOP_u1(
. sys_clk (sys_clk) ,
. rst_n (rst_n ) ,
. rx_data (rx_data) ,
. DIG (DIG ) ,
. SEG (SEG )
);
endmodule
仿真结果:
五、绑定管脚
set_property PACKAGE_PIN P20 [get_ports {DIG[0]}]
set_property PACKAGE_PIN N18 [get_ports {DIG[1]}]
set_property PACKAGE_PIN P18 [get_ports {DIG[2]}]
set_property PACKAGE_PIN W16 [get_ports {DIG[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DIG[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DIG[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DIG[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DIG[0]}]
set_property PACKAGE_PIN R18 [get_ports {SEG[0]}]
set_property PACKAGE_PIN N20 [get_ports {SEG[1]}]
set_property PACKAGE_PIN U20 [get_ports {SEG[2]}]
set_property PACKAGE_PIN W20 [get_ports {SEG[3]}]
set_property PACKAGE_PIN R17 [get_ports {SEG[4]}]
set_property PACKAGE_PIN P19 [get_ports {SEG[5]}]
set_property PACKAGE_PIN T20 [get_ports {SEG[6]}]
set_property PACKAGE_PIN V20 [get_ports {SEG[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {SEG[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {SEG[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {SEG[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {SEG[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {SEG[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {SEG[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {SEG[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {SEG[0]}]
set_property PACKAGE_PIN P15 [get_ports rst_n]
set_property PACKAGE_PIN K17 [get_ports sys_clk]
set_property IOSTANDARD LVCMOS33 [get_ports rst_n]
set_property IOSTANDARD LVCMOS33 [get_ports sys_clk]
set_property IOSTANDARD LVCMOS33 [get_ports rx_data]
set_property PACKAGE_PIN W18 [get_ports rx_data]
六、实验结果
0623