一、RS485简介
RS-485是双向、半双工通信协议,信号采用差分传输方式,允许多个驱动器和接收器挂接在总线上,其中每个驱动器都能够脱离总线
二、实验内容
1.实验目标
2.实验原理图分析
所需模块 :RS485总控模块
按键消抖模块:
呼吸灯模块:
流水灯模块:
UART_RX模块:
UART_TX模块 :
LED_CTRL模块 :
整体框图:
3.关于LED_CTRL模块的两种工作模式:
4.代码实现
按键消抖模块:
`timescale 1ns / 1ns
//
// Company:
// Engineer:
//
// Create Date: 2021/09/05 19:58:40
// Design Name:
// Module Name: key_filter
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module key_filter#(
parameter CNT_MAX = 20'd999_999
)
(
input wire sys_clk ,
input wire rst_n ,
input wire key_in ,
output reg key_flag
);
reg [19:0] cnt_20ms ;
always @(posedge sys_clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
// reset
cnt_20ms <= 20'd0;
end
else if (key_in == 1'b1) begin
cnt_20ms <= 20'd0;
end
else if (cnt_20ms == CNT_MAX) begin
cnt_20ms <= cnt_20ms;
end
else begin
cnt_20ms <= cnt_20ms + 20'd1;
end
end
always @(posedge sys_clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
// reset
key_flag <= 1'b0;
end
else if (cnt_20ms == (CNT_MAX - 20'd1)) begin
key_flag <= 1'b1;
end
else begin
key_flag <= 1'b0;
end
end
endmodule
流水灯模块:
//
// Company:
// Engineer:
//
// Create Date: 2021/09/05 20:36:16
// Design Name:
// Module Name: water_led
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module water_led#(
parameter M = 25'd24999999
)
(clk,rst_n,LED_L);
reg [24:0] CNT1;
reg [2:0] CNT2;
input wire clk;
input wire rst_n;
output reg [3:0] LED_L;
always @(posedge clk or negedge rst_n)begin
if (rst_n == 1'b0) begin
CNT1 <= 25'd0;
end
else if (CNT1 == 25'd24999999) begin
CNT1 <= 25'd0;
end
else begin
CNT1 <= CNT1 + 25'd1;
end
end
always @(posedge clk or negedge rst_n)begin
if (rst_n == 1'b0) begin
CNT2 <= 3'd0;
end
else if ((CNT2 == 3'd4) && (CNT1 == (M-25'd1))) begin
CNT2 <= 3'd0;
end
else if ((CNT1 == (M-1))) begin
CNT2 <= CNT2 + 3'd1;
end
else begin
CNT2 <= CNT2;
end
end
always @(posedge clk)
if (CNT2 == 3'd0) begin
LED_L <= 4'd0;
end
else if (CNT2 == 3'd1) begin
LED_L <= 4'd1;
end
else if (CNT2 == 3'd2) begin
LED_L <= 4'd2;
end
else if (CNT2 == 3'd3) begin
LED_L <= 4'd4;
end
else if (CNT2 == 3'd4) begin
LED_L <= 4'd8;
end
else begin
LED_L <= LED_L;
end
endmodule
呼吸灯模块:
`timescale 1ns / 1ns
//
// Company:
// Engineer:
//
// Create Date: 2021/08/24 13:39:06
// Design Name:
// Module Name: breath_led
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module breath_led#(
parameter CNT_1US_MAX = 7'd99,
parameter CNT_1MS_MAX = 10'd999,
parameter CNT_1S_MAX = 10'd999
)
(
input wire sys_clk,
input wire sys_rst_n,
output reg led_out
);
reg [9:0] cnt_1s;
reg [9:0] cnt_1ms;
reg [6:0] cnt_1us;
reg cnt_en;
always @(posedge sys_clk or negedge sys_rst_n) begin
if (sys_rst_n == 1'b0) begin
cnt_1us <= 7'd0;
end
else if (cnt_1us == CNT_1US_MAX) begin
cnt_1us <= 7'd0;
end
else begin
cnt_1us <= cnt_1us + 7'd1;
end
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if (sys_rst_n == 1'b0) begin
cnt_1ms <= 10'd0;
end
else if ((cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX)) begin
cnt_1ms <= 10'd0;
end
else if (cnt_1us == CNT_1US_MAX) begin
cnt_1ms <= cnt_1ms + 10'd1;
end
else begin
cnt_1ms <= cnt_1ms;
end
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if (sys_rst_n == 1'b0) begin
cnt_1s <= 10'd0;
end
else if ((cnt_1s == CNT_1S_MAX) && (cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX)) begin
cnt_1s <= 10'd0;
end
else if ((cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX)) begin
cnt_1s <= cnt_1s + 10'd1;
end
else begin
cnt_1s <= cnt_1s;
end
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if (sys_rst_n == 1'b0) begin
cnt_en <= 1'b0;
end
else if ((cnt_1s == CNT_1S_MAX) && (cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX)) begin
cnt_en <= ~cnt_en;
end
else begin
cnt_en <= cnt_en;
end
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if (sys_rst_n == 1'b0) begin
led_out <= 1'b0;
end
else if (((cnt_en == 1'b0) && (cnt_1ms <= cnt_1s)) || ((cnt_en == 1'b1) && (cnt_1ms >= cnt_1s))) begin
led_out <= 1'b1;
end
else begin
led_out <= 1'b0;
end
end
endmodule
UART_RX模块:
`timescale 1ns / 1ns
//
// Company:
// Engineer:
//
// Create Date: 2021/09/03 12:36:32
// Design Name:
// Module Name: uart_rx
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module uart_rx
#(
parameter UART_BPS = 'd9600,
parameter CLK_FREQ = 'd100_000_000
)
(
input wire sys_clk ,
input wire rst_n ,
input wire rx ,
output reg [7:0] Po_data ,
output reg Po_flag
);
parameter BAUD_CNT_MAX = CLK_FREQ/UART_BPS;
reg rx_reg1; // åŒæ¥åˆ°ç³»ç»Ÿæ—¶é’Ÿä¸‹
reg rx_reg2;
reg rx_reg3; // 打两æ‹ï¼Œå‡å°äºšç¨³æ€å±å®?
reg Start_flag; // å¼?始一个数æ®å¸§çš„ä¼ è¾“æ ‡å¿—ä¿¡å?
reg Work_en; // æ ‡è¯†æ•°æ®é‡‡é›†èŒƒå›´ï¼ŒæŽ¥æ”¶æ•°æ®å·¥ä½œä½¿èƒ½ä¿¡å?
reg [15:0] baud_cnt; // 计数1ç å…ƒæ‰?éœ?è¦çš„æ—¶é’Ÿå‘¨æœŸæ•?(在本实验ä¸ï¼Œ1ç å…ƒ=1bit)
reg Bit_flag; // æ¯bitæ•°æ®ç¨³å®šç‚¹æ‹‰é«˜ä¸€æ‹?
reg [3:0] Bit_cnt; // bit计数�
reg [7:0] rx_data;
reg rx_flag;
always @(posedge sys_clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
// reset
rx_reg1 <= 1'b1;
rx_reg2 <= 1'b1;
rx_reg3 <= 1'b1;
end
else begin
rx_reg1 <= rx;
rx_reg2 <= rx_reg1;
rx_reg3 <= rx_reg2;
end
end
always @(posedge sys_clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
Start_flag <= 1'b0;
end
else if ((rx_reg3 == 1'b1) && (rx_reg2 == 1'b0) && (Work_en == 1'b0)) begin
Start_flag <= 1'b1;
end
else begin
Start_flag <= 1'b0;
end
end
always @(posedge sys_clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
Work_en <= 1'b0;
end
else if (Start_flag == 1'b1) begin
Work_en <= 1'b1;
end
else if ((Bit_cnt == 4'd8) && (Bit_flag == 1'b1)) begin
Work_en <= 1'b0;
end
else begin
Work_en <= Work_en;
end
end
always @(posedge sys_clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
baud_cnt <= 16'd0;
end
else if ((baud_cnt == BAUD_CNT_MAX - 1) || (~Work_en)) begin
baud_cnt <= 16'd0;
end
else begin
baud_cnt <= baud_cnt + 1'b1;
end
end
always @(posedge sys_clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
Bit_flag <= 1'b0;
end
else if (baud_cnt == BAUD_CNT_MAX / 2 - 1) begin
Bit_flag <= 1'b1;
end
else begin
Bit_flag<= 1'b0;
end
end
always @(posedge sys_clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
Bit_cnt <= 1'b0;
end
else if ((Bit_flag) && (Bit_cnt == 4'd8)) begin
Bit_cnt <= 1'b0;
end
else if (Bit_flag) begin
Bit_cnt <= Bit_cnt + 1'b1;
end
else begin
Bit_cnt <= Bit_cnt;
end
end
always @(posedge sys_clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rx_data <= 8'd0;
end
else if (((Bit_cnt >= 4'd1) && (Bit_cnt <= 4'd8)) && (Bit_flag == 1'b1))begin
rx_data <= {rx_reg3,rx_data[7:1]};
end
else begin
rx_data <= rx_data;
end
end
always @(posedge sys_clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
rx_flag <= 1'b0;
end
else if ((Bit_cnt == 4'd8) && (Bit_flag == 1'b1)) begin
rx_flag <= 1'b1;
end
else
rx_flag <= 1'b0;
end
always @(posedge sys_clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
Po_data <= 8'd0;
end
else if (rx_flag == 1'b1) begin
Po_data <= rx_data;
end
else begin
Po_data <= Po_data;
end
end
always @(posedge sys_clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
Po_flag <= 1'd0;
end
else begin
Po_flag <= rx_flag;
end
end
endmodule
UART_TX模块 :
//
// Company:
// Engineer:
//
// Create Date: 2021/09/04 19:36:40
// Design Name:
// Module Name: uart_tx
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module uart_tx
#(
parameter UART_BPS = 'd9600,
parameter CLK_FREQ = 'd100_000_000
)
(
input wire sys_clk ,
input wire rst_n ,
input wire [7:0] Pi_data ,
input wire Pi_flag ,
output reg tx,
output reg Work_en
);
parameter BAUD_CNT_MAX = CLK_FREQ/UART_BPS;
reg [15:0] baud_cnt ;
reg [3:0] Bit_cnt ;
reg Bit_flag ;
always @(posedge sys_clk or negedge rst_n)begin
if (rst_n == 1'b0) begin
Work_en <= 1'b0;
end
else if (Pi_flag == 1'b1) begin
Work_en <= 1'b1;
end
else if ((Bit_cnt == 4'd9) && (Bit_flag == 1'b1)) begin
Work_en <= 1'b0;
end
else begin
Work_en <= Work_en;
end
end
always @(posedge sys_clk or negedge rst_n)begin
if (rst_n == 1'b0) begin
baud_cnt <= 16'd0;
end
else if ((baud_cnt == BAUD_CNT_MAX - 1'b1) || (~Work_en)) begin
baud_cnt <= 16'd0;
end
else begin
baud_cnt <= baud_cnt + 1'b1;
end
end
always @(posedge sys_clk or negedge rst_n)begin
if (rst_n == 1'b0) begin
Bit_flag <= 1'b0;
end
else if (baud_cnt == (BAUD_CNT_MAX - 1'b1)) begin
Bit_flag <= 1'b1;
end
else begin
Bit_flag <= 1'b0;
end
end
always @(posedge sys_clk or negedge rst_n)begin
if (rst_n == 1'b0) begin
Bit_cnt <= 1'b0;
end
else if ((Bit_cnt == 4'd9) && (Bit_flag == 1'b1)) begin
Bit_cnt <= 4'd0;
end
else if ((Bit_flag == 1'b1) && (Work_en == 1'b1)) begin
Bit_cnt <= Bit_cnt + 1'b1;
end
else begin
Bit_cnt <= Bit_cnt;
end
end
always @(posedge sys_clk or negedge rst_n)begin
if (rst_n == 1'b0) begin
tx <= 1'b1;
end
else if (Work_en == 1'b1) begin
case(Bit_cnt)
0 : tx <= 1'b0;
1 : tx <= Pi_data[0];
2 : tx <= Pi_data[1];
3 : tx <= Pi_data[2];
4 : tx <= Pi_data[3];
5 : tx <= Pi_data[4];
6 : tx <= Pi_data[5];
7 : tx <= Pi_data[6];
8 : tx <= Pi_data[7];
9 : tx <= 1'b1;
default:tx<=1'b1;
endcase
end
end
endmodule
LED_CTRL模块 :
//
// Company:
// Engineer:
//
// Create Date: 2021/09/05 21:27:03
// Design Name:
// Module Name: led_ctrl
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module led_ctrl(
input wire sys_clk ,
input wire rst_n ,
input wire key_flag_w ,
input wire key_flag_b ,
input wire [7:0] pi_data ,
input wire [3:0] led_out_w ,
input wire led_out_b ,
output reg [3:0] led ,
output wire [7:0] po_data ,
output wire po_flag
);
reg w_en ;
reg b_en ;
always @(posedge sys_clk or negedge rst_n)
if (~rst_n) begin
w_en <= 1'b0;
end
else if (key_flag_b == 1'b1) begin
w_en <= 1'b0;
end
else if (key_flag_w == 1'b1) begin
w_en <= ~w_en;
end
else begin
w_en <= w_en;
end
always @(posedge sys_clk or negedge rst_n)
if (~rst_n) begin
b_en <= 1'b0;
end
else if (key_flag_w == 1'b1) begin
b_en <= 1'b0;
end
else if (key_flag_b == 1'b1) begin
b_en <= ~b_en;
end
else begin
b_en <= b_en;
end
always @(posedge sys_clk or negedge rst_n)
if (~rst_n) begin
led <= 4'b0000;
end
else if (pi_data[0] == 1'b1) begin
led <= led_out_w;
end
else if (pi_data[1] == 1'b1) begin
led <= {led_out_b,led_out_b,led_out_b,led_out_b};
end
else begin
led <= 4'b0000;
end
assign po_data = {6'b000_000,b_en,w_en};
assign po_flag = {key_flag_w || key_flag_b};
endmodule
RS485总控模块
`timescale 1ns / 1ns
//
// Company:
// Engineer:
//
// Create Date: 2021/09/05 21:52:41
// Design Name:
// Module Name: rs485
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module rs485(
input wire sys_clk ,
input wire rst_n ,
input wire key_in_w ,
input wire key_in_b ,
input wire rx ,
output wire tx ,
output wire [3:0] led ,
output wire re
);
parameter KEY_CNT_MAX = 20'd999_999;
parameter WATER_LED_CNT_MAX = 25'd24999999;
parameter B_CNT_1US_MAX = 7'd99,
B_CNT_1MS_MAX = 10'd999,
B_CNT_1S_MAX = 10'd999;
parameter UART_BPS = 9600 ,
CLK_FREQ = 100_000_000 ;
wire w_flag ;
wire b_flag ;
wire [3:0] w_led ;
wire b_led ;
wire [7:0] rx_data ;
wire [7:0] po_data ;
wire po_flag ;
key_filter#(
.CNT_MAX(KEY_CNT_MAX)
)key_filter_inst_w
(
.sys_clk (sys_clk),
.rst_n (rst_n),
.key_in (key_in_w),
.key_flag(w_flag)
);
key_filter#(
.CNT_MAX(KEY_CNT_MAX)
)key_filter_inst_b
(
.sys_clk (sys_clk),
.rst_n (rst_n),
.key_in (key_in_b),
.key_flag(b_flag)
);
water_led
#(
.M(WATER_LED_CNT_MAX)
)water_led_inst
(
.clk (sys_clk),
.rst_n(rst_n),
.LED_L(w_led)
);
breath_led#(
.CNT_1US_MAX(B_CNT_1US_MAX),
.CNT_1MS_MAX(B_CNT_1MS_MAX),
.CNT_1S_MAX (B_CNT_1S_MAX )
)breath_led_inst
(
.sys_clk(sys_clk),
.sys_rst_n(rst_n),
.led_out(b_led)
);
uart_tx
#(
.UART_BPS (UART_BPS),
.CLK_FREQ (CLK_FREQ)
)uart_tx_inst
(
.sys_clk(sys_clk),
.rst_n (rst_n),
.Pi_data(po_data),
.Pi_flag(po_flag),
.tx (tx),
.Work_en(re)
);
uart_rx
#(
.UART_BPS (UART_BPS),
.CLK_FREQ (CLK_FREQ)
)uart_rx_inst
(
.sys_clk(sys_clk),
.rst_n (rst_n),
.rx (rx),
.Po_data(rx_data),
.Po_flag()
);
led_ctrl led_ctrl_inst(
.sys_clk (sys_clk),
.rst_n (rst_n),
.key_flag_w (w_flag),
.key_flag_b (b_flag),
.pi_data (rx_data),
.led_out_w (w_led),
.led_out_b (b_led),
.led (led),
.po_data (po_data),
.po_flag (po_flag)
);
endmodule
三、下板实验