一、项目要求
要求输入从千位到个位数字给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