1.原理图,需要用到5个模块。分别是时钟分频模块,ram随机存储模块,uart发送、接收检测模块,vga图像显示模块。
2.这次属于模块的顶层例化,比较难想明白的是,如果终端图片发送,写地址清零。而且很多细节问题需要多次调试,第一次实现图片回传与上位机检测,发现上位机可以接收到回传信息。。第一次调试发现图片不能中断传输,原因是我触发条件写错了,只能计数器记到1。第二次图片一直上传不到显示器上,经过观测发现写地址一直处于清零状态,原因是我没给清理标志位清零。
module ram_ctrl(
input wire rst_n,
input wire sclk,
input wire rd_en,
input wire flag_o,
input wire [7:0]data_o,
output wire [7:0]ram_data
);
reg [15:0] addra_space;
reg [15:0] addrb_space;
reg [15:0] cnt_clean;
parameter CNT_CLEAN=28888;
blk_mem_39999 blk_mem_39999_inst (
.clka(sclk), // 输入25M的全局时钟
.wea(flag_o), // input [0 : 0] wea
.addra(addra_space), // input [15 : 0] addra
.dina(data_o), // input [7 : 0] dina
.clkb(sclk), // 输入25M的全局时钟
.addrb(addrb_space), // input [15 : 0] addrb
.doutb(ram_data) // output [7 : 0] doutb
);
always@(posedge sclk or negedge rst_n) //ram输入信号清零计数器
if(!rst_n)
cnt_clean<=16'd0;
else if(flag_o==1'b1) // 少写了清零条件,导致写地址一直处于清零状态
cnt_clean<=16'd0;
else if(cnt_clean==CNT_CLEAN)
cnt_clean<=16'd0; // 优先级
else if(flag_o==1'b0) //flag_o==1'b1,当时想的就是拉高开始计数,结果发现根本不计数
cnt_clean<=cnt_clean+1'b1; //因为标志位拉高只有一个时钟周期,应该记拉低的时钟周期。
always@(posedge sclk or negedge rst_n) //为ram输入地址分配空间
if(!rst_n)
addra_space<=16'd0;
else if(cnt_clean==CNT_CLEAN)
addra_space<=16'd0;
else if(addra_space==39999&&flag_o==1'b1)
addra_space<=16'd0;
else if(flag_o==1'b1)
addra_space<=addra_space+1'b1;
always@(posedge sclk or negedge rst_n) //为ram输出地址分配地址空间
if(!rst_n)
addrb_space<=16'd0;
else if(addrb_space==39999)
addrb_space<=16'd0;
else if(rd_en==1'b1)
addrb_space<=addrb_space+1'b1;
endmodule
清零控制位需要多次调试,最重要的是要想清楚清零计数器记的是那个位置的始终周期。只要ram IP核控制好,就可以实现这次实践的功能。
3.顶层模块例化主要是uart模块的发送端与接收端与fpga的链接。对于fpga uart的接受端链接的是fpga的发送模块,uart的发送端链接的是fpga的接受端。整个模块fpga为主控芯片。
module top(
input wire sclk_in,
input wire rst_n,
input wire rx_in,
output wire h_sync,v_sync,
output wire [7:0] rgb_data,
output wire data
);
wire sclk;
wire rd_en;
wire [7:0]ram_data;
wire flag_o;
wire [7:0]data_o;
vga_ctrl vga_ctrl_inst(
. sclk (sclk),
. rst_n (rst_n),
.rd_en (rd_en),
.ram_data (ram_data),
.h_sync (h_sync),
.v_sync (v_sync),
.rgb_data (rgb_data)
);
clk_50_25 clk_50_25_inst
(// Clock in ports
.CLK_50(sclk_in), // IN
// Clock out ports
.CLK_25(sclk));
ram_ctrl ram_ctrl_inst(
.rst_n (rst_n),
.sclk (sclk),
.rd_en (rd_en),
.flag_o (flag_o),
.data_o (data_o),
.ram_data (ram_data)
);
tx_crtl tx_crtl_inst(
.sclk (sclk),
.rst_n (rst_n),
.rx_in (rx_in),
.flag_o (flag_o),
.data_o (data_o)
);
uart_crtl uart_crtl_inst(
.sclk (sclk),
.rst_n (rst_n),
.data_in (data_o),
.flag_in (flag_o),
.data_o (data)
);
endmodule