在这篇文以及下面几篇文里里使用HPS-FPGA-Slave实现HPS读取一张bmp图片,发送至SDRAM,然后由自定义的IP读取SDRAM输出至VGA显示。
不妥当的地方还需多多指教
IP逻辑设计
VGA时序控制模块,选择mod控制输出不同的分辨率
//vga timing ctrl module // systemverilog // //by Sorin module vga_timctrl( input clk,//200MHz input [1:0] mod, //input rst, output hsync,// output vsync,// output logic [10:0] addr_x,// output logic [10:0] addr_y,// output video_on,//, output logic clk_cycle//actule clock output ); //800*[email protected] //***************vga mode*************** ********************* // // 800 40 128 88 600 1 4 23 //"[email protected]" 50.0 800 856 976 1040 600 637 643 666 --mod0 //"[email protected]" 40.0 800 840 968 1056 600 601 605 628 --mod1 //"[email protected]" 25.2 640 656 752 800 480 490 492 525 --mod2 //"[email protected]" 102.1 1280 1360 1496 1712 960 961 964 994 --mod3 //"[email protected]" 108.0 1280 1328 1440 1688 1024 1025 1028 1066 --not surport logic[10:0] V_W=1280;// logic[10:0] V_H=1024;// logic[10:0] H_Sync_Start=1328;// logic[10:0] H_Sync_Stop=1440;// logic[10:0] H_Total=1688;// logic[10:0] V_Sync_Start=1025;// logic[10:0] V_Sync_Stop=1028; logic[10:0] V_Total=1066;// logic [3:0] CLK_DIV_CNT=0; logic inner_clk; logic [2:0] clk_cnt=0; logic inner_clk_reg; //assign inner_clk=inner_clk_reg; //clk divider always @(posedge clk) begin clk_cnt<=clk_cnt+1; end wire[10:0] V_Counter; wire[10:0] H_Counter; wire H_Video_On; wire V_Video_On; wire V_Clk; wire H_CLR; wire V_CLR; assign V_Clk=H_Video_On; assign video_on=H_Video_On&&V_Video_On; assign addr_x=video_on?H_Counter:V_W; assign addr_y=video_on?V_Counter:V_H; //assign inner_clk=clk; c_counter_binary Counter_H(.CLK(inner_clk),.SCLR(H_CLR),.Q(H_Counter),.CE(1)); c_counter_binary Counter_V(.CLK(inner_clk),.SCLR(V_CLR),.Q(V_Counter),.CE(H_CLR)); assign H_Video_On=(H_Counter<V_W)?1:0; assign V_Video_On=(V_Counter<V_H)?1:0; assign H_CLR=(H_Counter==H_Total-1)?1:0; assign V_CLR=((V_Counter==V_Total-1)&&H_CLR)?1:0; assign hsync=(H_Counter<H_Sync_Stop&&H_Counter>H_Sync_Start)?0:1; assign vsync=(V_Counter<V_Sync_Stop&&V_Counter>V_Sync_Start)?0:1; assign test=V_CLR; //modset always_comb begin case(mod) ‘b00: begin V_W=800; V_H=600; H_Sync_Start=856; H_Sync_Stop=976; H_Total=1040; V_Sync_Start=637; V_Sync_Stop=643; V_Total=666; //CLK_DIV_CNT=2;//200M/4=50M inner_clk=clk_cnt[1]; end ‘b01: begin V_W=800; V_H=600; H_Sync_Start=840; H_Sync_Stop=968; H_Total=1056; V_Sync_Start=601; V_Sync_Stop=605; V_Total=628; //CLK_DIV_CNT=2;//200M/4=50M inner_clk=clk_cnt[1]; end ‘b10: begin V_W=640; V_H=480; H_Sync_Start=656; H_Sync_Stop=752; H_Total=800; V_Sync_Start=490; V_Sync_Stop=492; V_Total=525; //CLK_DIV_CNT=4;//200M/8=25M inner_clk=clk_cnt[2]; end ‘b11: begin V_W=1280; V_H=960; H_Sync_Start=1360; H_Sync_Stop=1496; H_Total=1712; V_Sync_Start=961; V_Sync_Stop=964; V_Total=994; CLK_DIV_CNT=1;//200M/2=100M inner_clk=clk_cnt[0]; end default: begin V_W=800; V_H=600; H_Sync_Start=856; H_Sync_Stop=976; H_Total=1040; V_Sync_Start=637; V_Sync_Stop=643; V_Total=666; CLK_DIV_CNT=2; inner_clk=clk_cnt[0]; end endcase clk_cycle<=inner_clk; end endmodule //counter module module c_counter_binary #(parameter DATAWIDTH=11 )( input logic CLK, input logic SCLR, output logic [DATAWIDTH-1:0] Q, input logic CE ); logic [DATAWIDTH-1:0] cnt=0; always @(posedge CLK) begin if(SCLR) cnt=0; else begin if(CE==‘b1) begin cnt=cnt+1; end end Q<=cnt; end endmodule
顶层模块
面对sdram,使用pipeline方式读取,sdram controller支持的读取方式可以在它的datasheet中找到。
这里说明一下,avalon_slave控制有2个 words的地址空间,第一个words为sdram的基址寄存器,第二个words为控制寄存器。
控制寄存器由高至低:6位颜色模式控制 2位分辨率控制 12位height 12位width
颜色控制:
//vgacolormod 000000 stop, black
//vgacolormod 000001 8 bit gray-ram
//vgacolormod 000010 24 bit RGB888
//vgacolormod 000011 16 bit RGB565
//vgacolormod other black
//ram vgadisp //systemverilog //by Sorin module ramvgadisp( //avalone slave to hps input logic clk_s,reset_s,chipselect_s, input logic addr_s,//reg0 rambaseaddr input logic write_s, input logic [31:0] writedata_s, //avalone master to sdram controller input logic clk_m,reset_m,//clk_m 100MHz output logic read_m, input logic [63:0] readdata_m, output logic [31:0] readaddr_m, input waitrequest_m, input readdatavalid_m, //output logic[10:0] burstcount, //output to vgadisplay input logic vga_clk, output logic[23:0] vgaout_rgb, output logic vgaout_hsync,vgaout_vsync, output logic vgaout_sync_n,vgaout_clk, // output logic datareading ); wire logic [10:0]width,height,addr_x,addr_y; wire logic [1:0] vga_mod; logic video_on; logic [31:0] rambaseaddr,dispsetting; logic [5:0] vgacolormod; logic [22:0] ramoffsetaddr;//ram offset address counter logic [22:0] scalar_counter;//scalar counter logic vga_cycle;//vga pixel clk output assign vgaout_clk=vga_cycle; assign vgaout_sync_n=video_on; //always_comb//depart register data //begin assign width=dispsetting[10:0]; assign height=dispsetting[22:12]; assign vga_mod=dispsetting[25:24]; assign vgacolormod=dispsetting[31:26]; //end vga_timctrl timctrl( //vga time cotrol module .clk(vga_clk), .mod(vga_mod), .hsync(vgaout_hsync), .vsync(vgaout_vsync), .video_on(video_on), .addr_x(addr_x), .addr_y(addr_y), .clk_cycle(vga_cycle) ); //fifo definitions //logic [31:0]fifoRam_1[3]; logic [5:0][63:0] fifoRam_0,fifoRam_1; logic fifo_rpart,fifo_upart; //fifo_rpart reading from sdram;fifo_upart using by vga // rpart means this part should be full(fill it after turn to it ) // upart means this part is using logic [3:0] fifopore;// logic datarequest; logic datarequest1;//a clock later logic datarequestxor;//when datarequest give an effective signal logic [3:0] fifo_readed_cnt;//readed count logic fifo_rst; logic datarequestlock;//lock the request signal typedef enum logic{idle,busy} fifostatedef; typedef enum logic [1:0]{ridle,rwait,rreading}fiforstatedef; //scalar_counter //fatch data from sdram,and display //vgacolormod 000000 stop, black //vgacolormod 000001 8 bit gray-ram //vgacolormod 000010 24 bit RGB888 //vgacolormod 000011 16 bit RGB565 //vgacolormod other black //typedef union packed{ // logic [5:0][31:0] raw; // logic [23:0][7:0] gray; // logic [7:0][23:0] rgb888; //} fifoformat; logic [5:0][63:0]curdata_raw; logic [383:0] curdata_raw_c; logic [47:0][7:0]curdata_gray; logic [15:0][23:0]curdata_rgb888; logic [11:0][31:0]curdata_rgba; //wire[5:0] curdata;//current use fifo data //wire logic [23:0][7:0] curgray; //wire logic [8:0][23:0] currgb888; always_comb begin case(fifo_upart) ‘b0:curdata_raw=fifoRam_0; ‘b1:curdata_raw=fifoRam_1; default:curdata_raw=0; endcase end /* genvar i; generate for(i=0;i<6;i++) begin:gen1 curdata_raw_c[i*64] end endgenerate */ assign curdata_gray=({curdata_raw}); assign curdata_rgb888=({curdata_raw}); assign curdata_rgba=({curdata_raw}); logic [5:0]pix_cnt; logic offsetAddrStep;//1 add 6, 0 add 0 always_comb//for display begin if(video_on==‘b1) begin case(vgacolormod) ‘b000000: vgaout_rgb<=‘hffff00; ‘b000001: begin vgaout_rgb<={curdata_gray[pix_cnt],curdata_gray[pix_cnt],curdata_gray[pix_cnt]}; //vgaout.rgb.G<=curdata_gray[pix_cnt]; //vgaout.rgb.B<=curdata_gray[pix_cnt]; end ‘b000010: begin vgaout_rgb<=curdata_rgb888[pix_cnt]; end ‘b000011: begin vgaout_rgb<=curdata_rgba[pix_cnt][23:0]; end default: begin vgaout_rgb<=0; end endcase end else vgaout_rgb<=0; end //for corlor data logic [11:0] cntx,cnty; always@(posedge vga_cycle) begin if(~vgaout_vsync)//vsync is effective begin //read the first fifo part from ram and reset the output module pix_cnt<=0; cntx<=0; cnty<=0; datarequest<=0; fifo_upart<=0; fifo_rpart<=1; ramoffsetaddr=0; //offsetAddrStep=0; //vgaout_rgb<=0; end if(~vgaout_hsync) begin if(cntx>=width) begin cnty<=cnty+1; cntx<=0; end else begin cntx<=0; cnty<=cnty; end end if((video_on==‘b1)&(cntx<width)&(cnty<height))//video_on should be effective,addr_x and addr_y should begin cntx<=cntx+1; case(vgacolormod) ‘b000001: begin if(pix_cnt<47) begin pix_cnt<=pix_cnt+1; offsetAddrStep=0; datarequest<=0; ramoffsetaddr=ramoffsetaddr; end else begin//turn to the other fifo part to read pix_cnt<=0; fifo_upart<=~fifo_upart; fifo_rpart<=~fifo_rpart; datarequest<=1; ramoffsetaddr=ramoffsetaddr+6; offsetAddrStep=1; end end ‘b000010: if(pix_cnt<15) begin pix_cnt<=pix_cnt+1; offsetAddrStep=0; datarequest<=0; ramoffsetaddr=ramoffsetaddr; end else begin//turn to the other fifo part to read pix_cnt<=0; fifo_upart<=~fifo_upart; fifo_rpart<=~fifo_rpart; datarequest<=1; ramoffsetaddr=ramoffsetaddr+6; offsetAddrStep=1; end ‘b000011: if(pix_cnt<11) begin pix_cnt<=pix_cnt+1; offsetAddrStep=0; datarequest<=0; ramoffsetaddr=ramoffsetaddr; end else begin pix_cnt<=0; fifo_upart<=~fifo_upart; fifo_rpart<=~fifo_rpart; datarequest<=1; ramoffsetaddr=ramoffsetaddr+6; offsetAddrStep=1; end default: begin datarequest<=‘b0; end endcase //case(offsetAddrStep) //1:ramoffsetaddr<=ramoffsetaddr+6; //0:ramoffsetaddr<=ramoffsetaddr; //default:ramoffsetaddr<=ramoffsetaddr; //endcase //ramoffsetaddr<=ramoffsetaddr+offsetAddrStep; end else begin datarequest<=0; end end //as a slave, setting register always @(posedge clk_s) begin if(reset_s==‘b1) begin dispsetting<=0; end if(chipselect_s==‘b1) begin if(write_s==‘b1) begin case(addr_s) 0: begin rambaseaddr<=writedata_s; dispsetting<=dispsetting; end 1: begin dispsetting<=writedata_s; rambaseaddr<=rambaseaddr; end default: begin rambaseaddr<=rambaseaddr; dispsetting<=dispsetting; end endcase end end end //logic [31:0]fifoRam_0[3]; //store burst data received //fifo block fifostatedef fifostate; logic [3:0] fifo_addrsent_cnt; fiforstatedef fiforstate=ridle; logic [31:0] fiforeadaddr; assign fiforeadaddr=rambaseaddr+ramoffsetaddr+fifo_addrsent_cnt; assign datarequestxor=datarequest&(~datarequest1); always @(posedge clk_m) begin datarequest1<=datarequest; datareading<=0; if((fiforstate==ridle)&datarequestxor) begin fifo_readed_cnt<=0; fifo_addrsent_cnt<=0; fiforstate<=rreading; read_m<=‘b1; readaddr_m<=fiforeadaddr; //burstcount<=‘h0006; end else if(fiforstate==rreading) begin if(waitrequest_m) begin read_m<=‘b1; readaddr_m<=(rambaseaddr+ramoffsetaddr+fifo_addrsent_cnt)<<6; //burstcount<=‘h0006; end else begin if(fifo_addrsent_cnt<5)//address haven‘t sent all yet begin fifo_addrsent_cnt=fifo_addrsent_cnt+1; read_m<=‘b1; //burstcount<=‘h0006; readaddr_m<=(rambaseaddr+ramoffsetaddr+fifo_addrsent_cnt)<<6; end else begin read_m<=‘b0;//stop senting request end end if(readdatavalid_m)//data is valid begin case(fifo_rpart) 0: //fifoRam_0[fifo_readed_cnt]<=readdata_m; fifoRam_0[fifo_readed_cnt]<=readdata_m; 1: //fifoRam_1[fifo_readed_cnt]<=readdata_m; fifoRam_1[fifo_readed_cnt]<=readdata_m; endcase if(fifo_readed_cnt<5) begin fifo_readed_cnt<=fifo_readed_cnt+1; end else begin fifo_readed_cnt<=0; fiforstate<=ridle; end end end else begin fiforstate<=ridle; end end endmodule
时间: 2024-10-23 18:08:01