赞
踩
本篇内容:
上位机由串口助手通过 rx 线往 FPGA 发 8 比特数据,当 FPGA接收到 8 比特数据后,再通过 tx 线把接收到的 8 比特数据给上位机发回去,要求上位机接收到的数据和上位机发送的数据一样,并且保证连续发送也没问题。
代码:
module uart_rx( input wire clk, input wire rst, input wire rx, output reg [7:0]po_data, output reg po_flag ); parameter CNT_END=100; //9600bps cnt=5207 sim时,cnt=100; parameter CNT_END_HALF=CNT_END/2; reg rx_t; reg rx_tt; reg rx_tt_reg; reg [12:0] cnt; reg cnt_flag; reg bit_flag; reg [3:0]bit_cnt; // rx_t always @(posedge clk) begin if(rst==1'b1) begin rx_t <= 'd1; end else begin rx_t<=rx ; end end // rx_tt always @(posedge clk) begin if(rst==1'b1) begin rx_tt <= 'd1; end else begin rx_tt<=rx_t ; end end // rx_tt_reg always @(posedge clk) begin if(rst==1'b1) begin rx_tt_reg <= 'd1; end else begin rx_tt_reg<=rx_tt ; end end //cnt always @(posedge clk) begin if(rst==1'b1) begin cnt<= 'd0; end else if (cnt_flag==1'b1 && cnt==CNT_END) begin cnt<='d0; end else if (cnt_flag==1'b1) begin cnt<=cnt+1'b1; end else if (bit_cnt=='d8 && bit_flag==1'b1) begin cnt<='d0; end end //bit_flag always @(posedge clk) begin if(rst==1'b1) begin bit_flag <= 'd0; end else if (cnt_flag==1'b1 && cnt==CNT_END_HALF) begin bit_flag<='d1; end else bit_flag<='d0; end // cnt_flag always @(posedge clk) begin if(rst==1'b1) begin cnt_flag <= 'd0; end else if (rx_tt==1'b0 && rx_tt_reg==1'b1) begin cnt_flag<='d1; end else if (bit_cnt=='d8 && cnt==CNT_END_HALF) begin cnt_flag<='d0; end end // bit_cnt always @(posedge clk) begin if(rst==1'b1) begin bit_cnt <= 'd0; end else if (bit_cnt=='d8 && bit_flag==1'b1) begin bit_cnt<='d0; end else if (bit_flag==1'b1) begin bit_cnt<=bit_cnt+1'b1; end end // po_data always @(posedge clk) begin if(rst==1'b1) begin po_data <= 'd0; end else if (bit_cnt>0 && bit_flag==1'b1) begin po_data<={rx,po_data[7:1]}; end end // po_flag always @(posedge clk) begin if(rst==1'b1) begin po_flag<= 'd0; end else if (bit_cnt=='d8 && bit_flag==1'b1) begin po_flag<='d1; end else po_flag<='d0; end endmodule
tb:
`timescale 1ns / 1ps module tb_rx(); reg clk; reg rst; reg rx; wire [7:0] po_data; wire po_flag; initial begin clk=0; rst=1; #100 rst=0; end initial begin rx=1;//空闲状态 #100 gen_rx(); end //这里模拟发送20帧数据,每次发送8个0~1的任意数,发送前rx拉低,表示起始位 //由于9600波特率需要计数5207次,为了仿真方便,假设只需要计数100次。 task gen_rx; integer i; integer j; begin for (j = 0; j < 20; j=j+1) begin rx=0; for ( i = 0; i < 8; i=i+1) begin repeat(100) begin //每隔100周期发送1bit数据; @(posedge clk); end rx={$random}; end rx=1; //每发送完一帧数据后,rx恢复空闲状态,维持10个周期后继续发送数据,直到发够20帧数据。 repeat(10) begin @(posedge clk); end end end endtask always #5 clk=~clk; uart_rx inst_uart_rx ( .clk (clk), .rst (rst), .rx (rx), .po_data (po_data), .po_flag (po_flag) ); endmodule
module uart_tx( input wire clk, input wire rst, input wire[7:0] po_data, input wire po_flag, output reg tx ); parameter CNT_END=100; // bps为9600时,这里为:5207, 为仿真方便设为100。 reg [7:0] po_data_reg; reg [12:0]cnt; reg cnt_flag; reg bit_flag; reg [3:0] bit_cnt; // po_data_reg always @(posedge clk) begin if(rst==1'b1) begin po_data_reg<= 'd0; end else po_data_reg<=po_data; end // cnt always @(posedge clk) begin if(rst==1'b1) begin cnt <= 'd0; end else if (cnt_flag==1'b1 && cnt==CNT_END) begin cnt <= 'd0; end else if (cnt_flag==1'b1) begin cnt<=cnt+1'b1; end end //cnt_flag always @(posedge clk) begin if(rst==1'b1) begin cnt_flag <= 'd0; end else if (po_flag==1'b1) begin cnt_flag<='d1; end else if (bit_cnt=='d8 && bit_flag==1'b1) begin cnt_flag<='d0; end end // bit_flag always @(posedge clk) begin if(rst==1'b1) begin bit_flag <= 'd0; end else if (cnt==CNT_END-1 && cnt_flag==1'b1) begin bit_flag<='d1; end else bit_flag<='d0; end // bit_cnt always @(posedge clk) begin if(rst==1'b1) begin bit_cnt <= 'd0; end else if (bit_flag==1'b1 && bit_cnt=='d8) begin bit_cnt<='d0; end else if (bit_flag==1'b1) begin bit_cnt<=bit_cnt+1'b1; end end // tx always @(posedge clk) begin if(rst==1'b1) begin tx <= 'd1; end else if (po_flag==1'b1) begin tx<='d0; end else if (bit_flag==1'b1 && bit_cnt=='d8) begin tx<='d1; end else if (bit_flag==1'b1) begin tx<=po_data_reg[bit_cnt]; end end endmodule
tb:
`timescale 1ns / 1ps module tb_rx(); reg clk; reg rst; reg rx; wire tx; initial begin clk=0; rst=1; #100 rst=0; end initial begin rx=1;//空闲状态 #100 gen_rx(); end //这里模拟发送20次数据,每次发送8个0~1的任意数,发送前rx拉低,表示起始位 //由于9600波特率需要计数5207次,为了仿真方便,假设只需要计数100次。 task gen_rx; integer i; integer j; begin for (j = 0; j < 20; j=j+1) begin rx=0; for ( i = 0; i < 8; i=i+1) begin repeat(100) begin //每隔100周期发送1bit数据; @(posedge clk); end rx={$random}; end rx=1; //每发送完一帧数据后,rx恢复空闲状态,维持100个周期(方便tx端完整传输完一帧数据)后继续发送数据,直到发够20帧数据。 repeat(1000) begin @(posedge clk); end end end endtask always #5 clk=~clk; top_uart inst_top_uart (.clk(clk), .rst(rst), .rx(rx), .tx(tx)); endmodule
module top_uart( input wire clk, input wire rst, input wire rx, output wire tx ); wire [7:0] po_data; wire po_flag; uart_rx inst_uart_rx ( .clk (clk), .rst (rst), .rx (rx), .po_data (po_data), .po_flag (po_flag) ); uart_tx inst_uart_tx ( .clk (clk), .rst (rst), .po_data (po_data), .po_flag (po_flag), .tx (tx) ); endmodule
可以看到,rx和tx波形一致,则能实现传输要求。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。