【verilog】verilog实现串口传输UART
程序员文章站
2022-07-09 12:48:40
...
1.接收模块
代码:
//****************uart receive module******************//
//********************************************************//
`define SIM
module uart_rx#(
parameter DATAWIDTH = 8,
parameter BAUD_CNT_WIDTH = 12,
parameter BIT_CNT_WIDTH = 4
)
(
input CLK,
input RSTn,
input rs232_rx,//input data
output reg [ DATAWIDTH - 1 : 0 ] rx_data,//receive data
output reg po_flag //finish sig
);
`ifndef SIM
localparam BAUD_END = 5207;//simulate time too long,change to 56(560)
`else
localparam BAUD_END = 56;
`endif
localparam BAUD_M = BAUD_END / 2 - 1;
localparam BIT_END = 8;
reg rx_r1;
reg rx_r2;
reg rx_r3;
reg rx_flag;
reg [ BAUD_CNT_WIDTH - 1 : 0 ] baud_cnt;
reg bit_flag;
reg [ BIT_CNT_WIDTH - 1 : 0 ] bit_cnt;
wire rx_neg;//rx negedge
assign rx_neg = ~rx_r2 & rx_r3;
always @(posedge CLK or negedge RSTn) begin
rx_r1 <= 0;
rx_r2 <= 0;
rx_r3 <= 0;
end
always @(posedge CLK) begin
rx_r1 <= rs232_rx;
rx_r2 <= rx_r1;
rx_r3 <= rx_r2;
end
//rx_flag
always @(posedge CLK or negedge RSTn) begin
if (!RSTn) begin
// reset
rx_flag <= 0;
end
else if (rx_neg) begin
rx_flag <= 1;
end
else if (bit_cnt == 0 && baud_cnt == BAUD_END) begin
rx_flag <= 0;
end
end
//baud_cnt
always @(posedge CLK or negedge RSTn) begin
if (!RSTn) begin
// reset
baud_cnt <= 0;
end
else if (baud_cnt == BAUD_END) begin
baud_cnt <= 0;
end
else if (rx_flag) begin
baud_cnt <= baud_cnt + 1;
end
else begin
baud_cnt <= 0;
end
end
//bit_flag
always @(posedge CLK or negedge RSTn) begin
if (!RSTn) begin
// reset
bit_flag <= 0;
end
else if (baud_cnt == BAUD_M ) begin
bit_flag <= 1;
end
else begin
bit_flag <= 0;
end
end
//bit_cnt
always @(posedge CLK or negedge RSTn) begin
if (!RSTn) begin
// reset
bit_cnt <= 0;
end
else if (bit_flag == 1 && bit_cnt == BIT_END) begin
bit_cnt <= 0;
end
else if (bit_flag) begin
bit_cnt <= bit_cnt + 1;
end
end
//rx_data
always @(posedge CLK or negedge RSTn) begin
if (!RSTn) begin
// reset
rx_data <= 0;
end
else if (bit_flag == 1 && bit_cnt >= 1) begin
rx_data <= { rx_r2, rx_data [ DATAWIDTH - 1 : 1 ] };
end
end
//po_flag
always @(posedge CLK or negedge RSTn) begin
if (!RSTn) begin
// reset
po_flag <= 0;
end
else if (bit_cnt == BIT_END && bit_flag == 1) begin
po_flag <= 1;
end
else begin
po_flag <= 0;
end
end
endmodule
testbench:
module uart_rx_tb;
reg CLK;
reg RSTn;
reg rs232_tx;
wire po_flag;
wire [7:0] rx_data;
reg [7:0] mem [4:0];
initial $readmemh ("D:/Project/verilog_pro/project_module/sdram_controller/src/tx_data.txt",mem);
initial
begin
CLK = 1;
forever #5 CLK = ~CLK;
end
initial
begin
RSTn = 0;
rs232_tx <= 1;
#100
RSTn = 1;
#100
tx_byte();
end
task tx_byte();
integer i;
for (i = 0; i < 5;i=i+1 )
begin
tx_bit(mem[i]);
end
endtask
task tx_bit(
input [7:0] data
);
integer i;
for (i = 0; i < 10;i=i+1 )
begin
case(i)
0: rs232_tx <= 1'b0;
1: rs232_tx <= data [0];
2: rs232_tx <= data [1];
3: rs232_tx <= data [2];
4: rs232_tx <= data [3];
5: rs232_tx <= data [4];
6: rs232_tx <= data [5];
7: rs232_tx <= data [6];
8: rs232_tx <= data [7];
9: rs232_tx <= 1'b1;
endcase
#560;
end
endtask
uart_rx uart_rx_inst(.CLK (CLK ),
.RSTn (RSTn ),
.rs232_rx (rs232_tx ),
.rx_data (rx_data ),
.po_flag (po_flag ));
endmodule
txt文件:
2.发送模块
代码:
//******************uart transfer module******************//
//***********************************************************//
`define SIM
module uart_tx#(
parameter DATAWIDTH = 8,
parameter BAUD_CNT_WIDTH = 32,
parameter BIT_CNT_WIDTH = 4
)
(
input CLK,
input RSTn,
input [ DATAWIDTH - 1 : 0 ] tx_data,//data
input tx_trig,//transfer sig
output reg rs232_tx//transfer data
);
`ifndef SIM
localparam BAUD_END = 5207;//simulate time too long,change to 56(560)
`else
localparam BAUD_END = 56;
`endif
localparam BAUD_M = BAUD_END / 2 - 1;
localparam BIT_END = 8;
reg [ DATAWIDTH - 1 : 0 ] tx_data_r;
reg tx_flag;
reg [ BAUD_CNT_WIDTH - 1 : 0 ] baud_cnt;
reg bit_flag;
reg [ BIT_CNT_WIDTH - 1 : 0 ] bit_cnt;
//reg rs232_tx_t;
//tx_data_r
always @(posedge CLK or negedge RSTn) begin
if (!RSTn) begin
// reset
tx_data_r <= 0;
end
else if (tx_trig == 1 && tx_flag == 0) begin
tx_data_r <= tx_data;
end
end
//tx_flag
always @(posedge CLK or negedge RSTn) begin
if (!RSTn) begin
// reset
tx_flag <= 0;
end
else if (tx_trig == 1 && tx_flag == 0) begin
tx_flag <= 1;
end
else if (bit_cnt == BIT_END && bit_flag == 1) begin
tx_flag <= 0;
end
end
//baud_cnt
always @(posedge CLK or negedge RSTn) begin
if (!RSTn) begin
// reset
baud_cnt <= 0;
end
else if (baud_cnt == BAUD_END) begin
baud_cnt <= 0;
end
else if (tx_flag) begin
baud_cnt <= baud_cnt + 1;
end
else begin
baud_cnt <= 0;
end
end
//bit_flag
always @(posedge CLK or negedge RSTn) begin
if (!RSTn) begin
// reset
bit_flag <= 0;
end
else if (baud_cnt == BAUD_END) begin
bit_flag <= 1;
end
else begin
bit_flag <= 0;
end
end
//bit_cnt
always @(posedge CLK or negedge RSTn) begin
if (!RSTn) begin
// reset
bit_cnt <= 0;
end
else if (bit_flag == 1 && bit_cnt == BIT_END) begin
bit_cnt <= 0;
end
else if (bit_flag) begin
bit_cnt <= bit_cnt + 1;
end
end
//rs232_tx
always @(posedge CLK or negedge RSTn) begin
if (!RSTn) begin
// reset
rs232_tx <= 1;
end
else if (tx_flag) begin
case(bit_cnt)
0: rs232_tx <= 0;
1: rs232_tx <= tx_data_r[0];
2: rs232_tx <= tx_data_r[1];
3: rs232_tx <= tx_data_r[2];
4: rs232_tx <= tx_data_r[3];
5: rs232_tx <= tx_data_r[4];
6: rs232_tx <= tx_data_r[5];
7: rs232_tx <= tx_data_r[6];
8: rs232_tx <= tx_data_r[7];
default:rs232_tx <= 1;
endcase
end
else begin
rs232_tx <= 1;
end
end
//assign rs232_tx = rs232_tx_t;
endmodule
testbench:
module uart_tx_tb;
reg CLK;
reg RSTn;
reg tx_trig;
reg [7:0] tx_data;
wire rs232_tx;
initial
begin
CLK = 1;
forever #5 CLK = ~CLK;
end
initial
begin
RSTn = 0;
#100
RSTn = 1;
end
initial
begin
tx_data <= 0;
tx_trig <= 0;
#200
tx_trig <= 1;
tx_data <= 8'h55;
#10
tx_trig <= 0;
end
uart_tx uart_tx_inst(.CLK(CLK),
.RSTn(RSTn),
.tx_data(tx_data),
.tx_trig(tx_trig),
.rs232_tx(rs232_tx)
);
endmodule
3.顶层
module uart_top(
input CLK,
input RSTn,
input rs232_rx,
output rs232_tx
);
//***************Main Code*************//
wire [7:0] rx_data;
wire tx_trig;
//reg rs232_tx_t;
uart_rx uart_rx_inst(.CLK (CLK ),
.RSTn (RSTn ),
.rs232_rx (rs232_rx ),
.rx_data (rx_data ),
.po_flag (tx_trig ));
uart_tx uart_tx_inst(.CLK (CLK ),
.RSTn (RSTn ),
.tx_data (rx_data ),
.tx_trig (tx_trig ),
.rs232_tx (rs232_tx ));
endmodule
testbench:
module uart_tb;
reg CLK;
reg RSTn;
reg rs232_rx;
wire rs232_tx;
reg [7:0] mem [4:0];
initial $readmemh ("D:/Project/verilog_pro/project_module/sdram_controller/src/tx_data.txt",mem);
initial
begin
RSTn = 0;
//rs232_tx = 1;
#100
RSTn = 1;
#100
tx_byte();
end
initial
begin
CLK = 0;
forever #5 CLK = ~CLK;
end
task tx_byte();
integer i;
for (i = 0; i < 5;i=i+1 )
begin
tx_bit(mem[i]);
end
endtask
task tx_bit(
input [7:0] data
);
integer i;
for (i = 0; i < 10;i=i+1 )
begin
case(i)
0: rs232_rx <= 1'b0;
1: rs232_rx <= data [0];
2: rs232_rx <= data [1];
3: rs232_rx <= data [2];
4: rs232_rx <= data [3];
5: rs232_rx <= data [4];
6: rs232_rx <= data [5];
7: rs232_rx <= data [6];
8: rs232_rx <= data [7];
9: rs232_rx <= 1'b1;
endcase
#560;
end
endtask
uart_top uart_inst(.CLK (CLK),
.RSTn (RSTn),
.rs232_rx (rs232_rx),
.rs232_tx (rs232_tx));
endmodule
下一篇: 你看的真是超高清?揭开原生4K的神秘面纱