没有设计rs485的顶层,因为我的另一块板子没有TTL信号转差分信号的芯片:MAX3485CSA
module ctrl(
input wire sys_clk ,
input wire sys_rst_n ,
input wire key_w ,
input wire key_b ,
output wire [7:0] po_data , // 由于w_en 与b_en 使能信号是reg型,虽然po_data是时序逻辑,但是相对于按键按下信号,仍然要延后一个时钟周期。
output reg po_flag // 所以po_data 应该用reg
);
reg w_en ;
reg b_en ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
w_en <= 1'b0 ;
end else begin
if(key_w == 1'b1) begin
w_en <= ~w_en ;
end else begin
if(key_b == 1'b1) begin
w_en <= 1'b0 ;
end else begin
w_en <= w_en ;
end
end
end
end
// b_en
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
b_en <= 1'b0 ;
end else begin
if(key_b == 1'b1) begin
b_en <= ~b_en ;
end else begin
if(key_w == 1'b1) begin
b_en <= 1'b0 ;
end else begin
b_en <= b_en ;
end
end
end
end
// [7:0] po_data ,
assign po_data = {6'd0,w_en,b_en} ;
// po_flag
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
po_flag <= 1'b0 ;
end else begin
po_flag <= key_b || key_w ;
end
end
endmodule
`timescale 1ns/1ns
module test_ctrl();
reg sys_clk ;
reg sys_rst_n ;
reg key_w ;
reg key_b ;
wire [7:0] po_data ;
wire po_flag ;
ctrl ctrl_insert(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.key_w ( key_w ) ,
.key_b ( key_b ) ,
.po_data ( po_data ) ,
.po_flag ( po_flag )
);
parameter CYCLE = 20 ;
initial begin
sys_clk = 1'b1 ;
sys_rst_n <= 1'b0 ;
key_w <= 1'b0 ;
key_b <= 1'b0 ;
#( CYCLE * 10 ) ;
sys_rst_n <= 1'b1 ;
#( 210 ) ;
sys_rst_n <= 1'b0 ;
#( 10 ) ;
#( CYCLE * 10 ) ;
sys_rst_n <= 1'b1 ;
#( CYCLE * 100 ) ;
key_w <= 1'b1 ;
#( CYCLE ) ;
key_w <= 1'b0 ;
#( CYCLE * 500) ;
key_b <= 1'b1 ;
#( CYCLE ) ;
key_b <= 1'b0 ;
#( CYCLE * 500) ;
key_w <= 1'b1 ;
#( CYCLE ) ;
key_w <= 1'b0 ;
#( CYCLE * 500) ;
key_b <= 1'b1 ;
#( CYCLE ) ;
key_b <= 1'b0 ;
#( CYCLE * 500) ;
key_w <= 1'b1 ;
#( CYCLE ) ;
key_w <= 1'b0 ;
#( CYCLE * 500) ;
key_w <= 1'b1 ;
#( CYCLE ) ;
key_w <= 1'b0 ;
#( CYCLE * 500) ;
$stop ;
end
always #( CYCLE / 2 ) sys_clk = ~sys_clk ;
endmodule
module be_ctrl(
input wire sys_clk ,
input wire sys_rst_n ,
// input wire key_w , // 作为被控制板模块的ctrl 一些端口信号用不到的。
// input wire key_b ,
input wire [7:0] pi_data ,
input wire pi_flag ,
input wire [3:0] led_w ,
input wire [3:0] led_b ,
// output wire [7:0] po_data ,
// output wire po_flag
output reg [3:0] led_out // 也可以用组合逻辑
);
reg w_en ;
reg b_en ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
w_en <= 1'b0 ;
end else begin
if(pi_data[1]) begin
w_en <= ~w_en ;
end else begin
if(pi_data[0]) begin
w_en <= 1'b0 ;
end else begin
w_en <= w_en ;
end
end
end
end
// b_en
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
b_en <= 1'b0 ;
end else begin
if(pi_data[0]) begin
b_en <= ~b_en ;
end else begin
if(pi_data[1]) begin
b_en <= 1'b0 ;
end else begin
b_en <= b_en ;
end
end
end
end
// [3:0] led_out
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
led_out <= 3'd0 ;
end else begin
if(w_en == 1'b1) begin
led_out <= led_w;
end else begin
if(b_en == 1'b1) begin
led_out <= led_b;
end else begin
led_out <= led_out ;
end
end
end
end
endmodule
`timescale 1ns/1ns
module test_be_ctrl();
reg sys_clk ;
reg sys_rst_n ;
reg [7:0] pi_data_w ;
reg pi_flag_w ;
wire [3:0] led_out ;
// 由例化的模块产生
wire [3:0] led_w_w ;
wire [3:0] led_b_w ;
water_led
#(
.MAX_CNT ( 25'd25_0) // 00_000
)water_led_insert
(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.led ( led_w_w )
);
breath_led
#(
.CNT_1US ( 5 ) ,
.CNT_1K ( 10 )
)breath_led_insert
(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.led_out_1 ( led_b_w[0] ) ,
.led_out_2 ( led_b_w[1] ) ,
.led_out_3 ( led_b_w[2] ) ,
.led_out_4 ( led_b_w[3] )
);
be_ctrl be_ctrl_insert(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.pi_data ( pi_data_w ) ,
.pi_flag ( pi_flag_w ) ,
.led_w ( led_w_w ) ,
.led_b ( led_b_w ) ,
.led_out ( led_out )
);
parameter CYCLE = 20 ;
initial begin
sys_clk = 1'b1 ;
sys_rst_n <= 1'b0 ;
pi_data_w <= 8'd0 ;
pi_flag_w <= 1'b0 ;
#( CYCLE * 10 ) ;
sys_rst_n <= 1'b1 ;
#( 210 ) ;
sys_rst_n <= 1'b0 ;
#( 10 ) ;
#( CYCLE * 10 ) ;
sys_rst_n <= 1'b1 ; // 复位释放。
#( 50 * CYCLE) ;
pi_data_w <= 8'd1 ; // 呼吸灯控制按键按下
pi_flag_w <= 1'b1 ;
#( CYCLE ) ;
pi_data_w <= 8'd0 ;
pi_flag_w <= 1'b0 ;
#( CYCLE * 500 ) ;
pi_data_w <= 8'd1 ; // 呼吸灯控制按键按下
pi_flag_w <= 1'b1 ;
#( CYCLE ) ;
pi_data_w <= 8'd0 ;
pi_flag_w <= 1'b0 ;
#( CYCLE * 500 ) ;
pi_data_w <= 8'd2 ; // 流水灯控制按键按下
pi_flag_w <= 1'b1 ;
#( CYCLE ) ;
pi_data_w <= 8'd0 ;
pi_flag_w <= 1'b0 ;
#( CYCLE * 500 ) ;
pi_data_w <= 8'd1 ; // 呼吸灯控制按键按下
pi_flag_w <= 1'b1 ;
#( CYCLE ) ;
pi_data_w <= 8'd0 ;
pi_flag_w <= 1'b0 ;
#( CYCLE * 500 ) ;
$stop ;
end
always #( CYCLE / 2 ) sys_clk = ~sys_clk ;
endmodule
流水灯模块与呼吸灯模块是之前工程里的。
module rs_485_tx (
input wire sys_clk ,
input wire sys_rst_n ,
input wire [7:0] pi_data ,
input wire pi_flag ,
output reg tx ,
output reg re
);
// reg signal define
reg pi_flag_r ;
reg [7:0] pi_data_r ;
reg work_en ;
reg [12:00] baud_cnt ;
reg bit_flag ;
reg [ 3: 0] bit_cnt ;
// pi_flag_r ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
pi_flag_r <= 1'b0 ;
end else begin
if(pi_flag == 1'b1) begin
pi_flag_r <= 1'b1 ;
end else begin
pi_flag_r <= 1'b0 ;
end
end
end
// [7:0] pi_data_r ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
pi_data_r <= 1'b0 ;
end else begin
if(pi_flag == 1'b1) begin
pi_data_r <= pi_data ;
end else begin
pi_data_r <= pi_data_r ;
end
end
end
// work_en ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
work_en <= 1'b0 ;
end else begin
if(baud_cnt == 13'd5027 && bit_cnt == 4'd9) begin
work_en <= 1'b0 ;
end else begin
if(pi_flag_r == 1'b1) begin
work_en <= 1'b1 ;
end else begin
work_en <= work_en ;
end
end
end
end
// [12:00] baud_cnt ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
baud_cnt <= 13'd0 ;
end else begin
if(work_en == 1'b1 && baud_cnt == 13'd5027 || work_en == 1'b0) begin
baud_cnt <= 13'd0 ;
end else begin
if(work_en == 1'b1) begin
baud_cnt <= baud_cnt + 1'b1 ;
end else begin
baud_cnt <= 13'd0 ;
end
end
end
end
// bit_flag ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
bit_flag <= 1'b0 ;
end else begin
if(baud_cnt == 13'd5026) begin // 野火上是等于 1 .
bit_flag <= 1'b1 ;
end else begin
bit_flag <= 1'b0 ;
end
end
end
// [ 3: 0] bit_cnt ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
bit_cnt <= 4'd0 ;
end else begin
if(bit_flag == 1'b1 && bit_cnt == 4'd9 || work_en == 1'b0) begin
bit_cnt <= 4'd0 ;
end else begin
if(bit_flag == 1'b1) begin
bit_cnt <= bit_cnt + 1'b1 ;
end else begin
bit_cnt <= bit_cnt ;
end
end
end
end
// output signal
// tx
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
tx <= 1'b1 ;
end else begin
if(work_en == 1'b1 && bit_cnt == 4'd0) begin
tx <= 1'b0 ;
end else begin
if(work_en == 1'b1 && bit_cnt == 4'd9 || work_en == 1'b0) begin
tx <= 1'b1 ;
end else begin
tx <= pi_data_r[bit_cnt - 1'b1] ;
end
end
end
end
// re
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
re <= 1'b0 ;
end else begin
re <= work_en ;
end
end
endmodule
`timescale 1ns/1ns
module test_rs_485_tx();
reg sys_clk ;
reg sys_rst_n ;
reg [7:0] pi_data ;
reg pi_flag ;
wire tx ;
wire re ;
rs_485_tx rs_485_tx_insert(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.pi_data ( pi_data ) ,
.pi_flag ( pi_flag ) ,
.tx ( tx ) ,
.re ( re )
);
parameter CYCLE = 20 ;
initial begin
sys_clk = 1'b1 ;
sys_rst_n <= 1'b0 ;
pi_data <= 8'd0 ;
pi_flag <= 1'b0 ;
#( CYCLE * 10 ) ;
sys_rst_n <= 1'b1 ;
#( 210 ) ;
sys_rst_n <= 1'b0 ;
#( 10 ) ;
#( CYCLE * 10 ) ;
sys_rst_n <= 1'b1 ; // 复位释放。
#( 50 * CYCLE) ;
pi_data <= 8'd1 ; // 呼吸灯控制按键按下
pi_flag <= 1'b1 ;
#( CYCLE ) ;
pi_data <= 8'd0 ;
pi_flag <= 1'b0 ;
#( CYCLE * 96100 ) ;
pi_data <= 8'd1 ; // 呼吸灯控制按键按下
pi_flag <= 1'b1 ;
#( CYCLE ) ;
pi_data <= 8'd0 ;
pi_flag <= 1'b0 ;
#( CYCLE * 96100 ) ;
pi_data <= 8'd2 ; // 流水灯控制按键按下
pi_flag <= 1'b1 ;
#( CYCLE ) ;
pi_data <= 8'd0 ;
pi_flag <= 1'b0 ;
#( CYCLE * 96100 ) ;
pi_data <= 8'd1 ; // 呼吸灯控制按键按下
pi_flag <= 1'b1 ;
#( CYCLE ) ;
pi_data <= 8'd0 ;
pi_flag <= 1'b0 ;
#( CYCLE * 96100 ) ;
$stop ;
end
always #( CYCLE / 2 ) sys_clk = ~sys_clk ;
endmodule