- 实现目标:上位机通过串口发送图片到FPGA中,FPGA接收图片并保存在DDR2中,保存在 DDR2中的图片分为两路,一路经过VGA时序输出到RGB触摸屏上,另一路按照以太网帧格式进 行编码, 将以太网帧发送到PC端后,可用上位机软件实时显示视频图像。
- 主要工作:1.FPGA串口图像接收。2.DDR2读写。3.千兆以太网发送。4.VGA视频图像显示。
- 使用工具:Quartus ii、Modelsim、Wireshark、小梅哥UDP摄像头、串口传图工具。
一、串口接收模块(串口接收子模块用来接收上位机发送的图像数据)
module uart_byte_rx(
clk50M,
rst_n,
Rs232_rx,
baud_set,
Data_Byte,
Rx_Done
);
input clk50M;
input rst_n;
input Rs232_rx;
input [2:0]baud_set;
output reg [7:0]Data_Byte;
output reg Rx_Done;
reg s0_Rs232_rx, s1_Rs232_rx;
reg tmp0_Rs232_rx, tmp1_Rs232_rx;
reg [15:0]bps_DR;
reg [15:0]div_cnt;
reg bps_clk50M;
reg [7:0]bps_cnt;
reg uart_state;
wire ndge;
wire error_start;
always@(posedge clk50M or negedge rst_n)
if(!rst_n)begin
s0_Rs232_rx <= 1'b0;
s1_Rs232_rx <= 1'b0;
end
else begin
s0_Rs232_rx <= Rs232_rx;
s1_Rs232_rx <= s0_Rs232_rx;
end
always@(posedge clk50M or negedge rst_n)
if(!rst_n)begin
tmp0_Rs232_rx <= 1'b0;
tmp1_Rs232_rx <= 1'b0;
end
else begin
tmp0_Rs232_rx <= s1_Rs232_rx;
tmp1_Rs232_rx <= tmp0_Rs232_rx;
end
assign ndge = !tmp0_Rs232_rx & tmp1_Rs232_rx;
always@(posedge clk50M or negedge rst_n)
if(!rst_n)
bps_DR = 16'd324;
else begin
case(baud_set)
3'd0:bps_DR = 16'd324;
3'd1:bps_DR = 16'd162;
3'd2:bps_DR = 16'd80;
3'd3:bps_DR = 16'd53;
3'd4:bps_DR = 16'd26;
3'd5:bps_DR = 16'd1;
default:bps_DR = 16'd324;
endcase
end
always@(posedge clk50M or negedge rst_n)
if(!rst_n)
div_cnt <= 16'd0;
else if(!uart_state)
div_cnt <= 16'd0;
else if(div_cnt == bps_DR)
div_cnt <= 16'd0;
else
div_cnt <= div_cnt + 16'b1;
always@(posedge clk50M or negedge rst_n)
if(!rst_n)
bps_clk50M <= 1'b0;
else if(div_cnt == 16'b1)
bps_clk50M <= 1'b1;
else
bps_clk50M <= 1'b0;
always@(posedge clk50M or negedge rst_n)
if(!rst_n)
uart_state <= 1'b0;
else if(ndge)
uart_state <= 1'b1;
else if(Rx_Done || error_start)
uart_state <= 1'b0;
else
uart_state <= uart_state;
always@(posedge clk50M or negedge rst_n)
if(!rst_n)
bps_cnt <= 8'b0;
else if(bps_cnt == 8'd159 || error_start)
bps_cnt <= 8'b0;
else if(bps_clk50M)
bps_cnt <= bps_cnt + 8'b1;
else
bps_cnt <= bps_cnt;
always@(posedge clk50M or negedge rst_n)
if(!rst_n)
Rx_Done <= 1'b0;
else if(bps_cnt == 8'd159)
Rx_Done <= 1'b1;
else
Rx_Done <= 1'b0;
reg [2:0]r_Data_Byte[7:0];
reg [7:0]tmp_Data_Byte;
reg [2:0]START_BIT;
reg [2:0]STOP_BIT;
always@(posedge clk50M or negedge rst_n)
if(!rst_n)begin
START_BIT <= 3'd0;
r_Data_Byte[0] <= 3'd0;
r_Data_Byte[1] <= 3'd0;
r_Data_Byte[2] <= 3'd0;
r_Data_Byte[3] <= 3'd0;
r_Data_Byte[4] <= 3'd0;
r_Data_Byte[5] <= 3'd0;
r_Data_Byte[6] <= 3'd0;
r_Data_Byte[7] <= 3'd0;
STOP_BIT <= 3'd0;
end
else if(bps_clk50M)begin
case(bps_cnt)
0:begin
START_BIT <= 3'd0;
r_Data_Byte[0] <= 3'd0;
r_Data_Byte[1] <= 3'd0;
r_Data_Byte[2] <= 3'd0;
r_Data_Byte[3] <= 3'd0;
r_Data_Byte[4] <= 3'd0;
r_Data_Byte[5] <= 3'd0;
r_Data_Byte[6] <= 3'd0;
r_Data_Byte[7] <= 3'd0;
STOP_BIT <= 3'd0;
end
5, 6, 7, 8, 9, 10: START_BIT <= START_BIT + s1_Rs232_rx;
21, 22, 23, 24, 25, 26: r_Data_Byte[0] <= r_Data_Byte[0] + s1_Rs232_rx;
37, 38, 39, 40, 41, 42: r_Data_Byte[1] <= r_Data_Byte[1] + s1_Rs232_rx;
53, 54, 55, 56, 57, 58: r_Data_Byte[2] <= r_Data_Byte[2] + s1_Rs232_rx;
69, 70, 71, 72, 73, 74: r_Data_Byte[3] <= r_Data_Byte[3] + s1_Rs232_rx;
85, 86, 87, 88, 89, 90: r_Data_Byte[4] <= r_Data_Byte[4] + s1_Rs232_rx;
101,102,103,104,105,106:r_Data_Byte[5] <= r_Data_Byte[5] + s1_Rs232_rx;
117,118,119,120,121,122:r_Data_Byte[6] <= r_Data_Byte[6] + s1_Rs232_rx;
133,134,135,136,137,138:r_Data_Byte[7] <= r_Data_Byte[7] + s1_Rs232_rx;
149,150,151,152,153,154:STOP_BIT <= STOP_BIT + s1_Rs232_rx;
default:begin
START_BIT <= START_BIT;
r_Data_Byte[0] <= r_Data_Byte[0];
r_Data_Byte[1] <= r_Data_Byte[1];
r_Data_Byte[2] <= r_Data_Byte[2];
r_Data_Byte[3] <= r_Data_Byte[3];
r_Data_Byte[4] <= r_Data_Byte[4];
r_Data_Byte[5] <= r_Data_Byte[5];
r_Data_Byte[6] <= r_Data_Byte[6];
r_Data_Byte[7] <= r_Data_Byte[7];
STOP_BIT <= STOP_BIT;
end
endcase
end
assign error_start = ((bps_cnt == 8'd12) && (START_BIT > 2))?1'b1:1'b0;
always@(posedge clk50M or negedge rst_n)
if(!rst_n)
tmp_Data_Byte <= 8'b0000_0000;
else if(bps_cnt == 8'd159)begin
tmp_Data_Byte[0] <= (r_Data_Byte[0]>3);
tmp_Data_Byte[1] <= (r_Data_Byte[1]>3);
tmp_Data_Byte[2] <= (r_Data_Byte[2]>3);
tmp_Data_Byte[3] <= (r_Data_Byte[3]>3);
tmp_Data_Byte[4] <= (r_Data_Byte[4]>3);
tmp_Data_Byte[5] <= (r_Data_Byte[5]>3);
tmp_Data_Byte[6] <= (r_Data_Byte[6]>3);
tmp_Data_Byte[7] <= (r_Data_Byte[7]>3);
end
always@(posedge clk50M or negedge rst_n)
if(!rst_n)
Data_Byte <= 8'd0;
else if(Rx_Done)
Data_Byte <= tmp_Data_Byte;
else
Data_Byte <= Data_Byte;
endmodule ```
参考资料:【学习教材】FPGA系统设计与验证实战指南_V3.0(小梅哥)