newStep.v
This commit is contained in:
154
RTL/DEVICES/GFX_hdmi.v
Normal file
154
RTL/DEVICES/GFX_hdmi.v
Normal file
@@ -0,0 +1,154 @@
|
||||
|
||||
// Define one of:
|
||||
// MODE_640x480, MODE_800x600, MODE_1024x768, MODE_1280x1024.
|
||||
// ("physical mode" sent to the HDMI)
|
||||
|
||||
`include "TMDS_encoder.v"
|
||||
|
||||
// Generate HDMI signal from VGA signal
|
||||
module GFX_hdmi(
|
||||
input wire pixel_clk, // pixel clock
|
||||
input wire pixel_clk_x5, // 5 times pixel clock freq (used by TMDS serializer)
|
||||
// The TMDS serializers operate at (pixel_clock_freq * 10),
|
||||
// but we use DDR mode, hence (pixel_clock_freq * 5).
|
||||
input wire [7:0] R,
|
||||
input wire [7:0] G,
|
||||
input wire [7:0] B,
|
||||
input wire hsync,
|
||||
input wire vsync,
|
||||
input wire draw_area,
|
||||
|
||||
output wire [3:0] gpdi_dp // HDMI signals, blue, green, red, clock
|
||||
// dgpi_dn generated by pins (see, e.g., ulx3s.lpf)
|
||||
);
|
||||
|
||||
// RGB TMDS encoding
|
||||
// Generate 10-bits TMDS red,green,blue signals. Blue embeds HSync/VSync in its
|
||||
// control part.
|
||||
wire [9:0] TMDS_R, TMDS_G, TMDS_B;
|
||||
TMDS_encoder encode_R(.clk(pixel_clk), .VD(R), .CD(2'b00) , .VDE(draw_area), .TMDS(TMDS_R));
|
||||
TMDS_encoder encode_G(.clk(pixel_clk), .VD(G), .CD(2'b00) , .VDE(draw_area), .TMDS(TMDS_G));
|
||||
TMDS_encoder encode_B(.clk(pixel_clk), .VD(B), .CD({vsync,hsync}), .VDE(draw_area), .TMDS(TMDS_B));
|
||||
|
||||
// Modulo-5 clock divider.
|
||||
reg [4:0] TMDS_mod5=1;
|
||||
wire TMDS_shift_load = TMDS_mod5[4];
|
||||
always @(posedge pixel_clk_x5) TMDS_mod5 <= {TMDS_mod5[3:0],TMDS_mod5[4]};
|
||||
|
||||
// Shifters
|
||||
// Every 5 clocks, we get a fresh R,G,B triplet from the TMDS encoders,
|
||||
// else we shift.
|
||||
reg [9:0] TMDS_shift_R=0, TMDS_shift_G=0, TMDS_shift_B=0;
|
||||
always @(posedge pixel_clk_x5) begin
|
||||
TMDS_shift_R <= TMDS_shift_load ? TMDS_R : {2'b00,TMDS_shift_R[9:2]};
|
||||
TMDS_shift_G <= TMDS_shift_load ? TMDS_G : {2'b00,TMDS_shift_G[9:2]};
|
||||
TMDS_shift_B <= TMDS_shift_load ? TMDS_B : {2'b00,TMDS_shift_B[9:2]};
|
||||
end
|
||||
|
||||
// DDR serializers: they send D0 at the rising edge and D1 at the falling edge.
|
||||
`ifndef BENCH_OR_LINT
|
||||
`ifdef ULX3S
|
||||
ODDRX1F ddr_R (.D0(TMDS_shift_R[0]), .D1(TMDS_shift_R[1]), .Q(gpdi_dp[2]), .SCLK(pixel_clk_x5), .RST(1'b0));
|
||||
ODDRX1F ddr_G (.D0(TMDS_shift_G[0]), .D1(TMDS_shift_G[1]), .Q(gpdi_dp[1]), .SCLK(pixel_clk_x5), .RST(1'b0));
|
||||
ODDRX1F ddr_B (.D0(TMDS_shift_B[0]), .D1(TMDS_shift_B[1]), .Q(gpdi_dp[0]), .SCLK(pixel_clk_x5), .RST(1'b0));
|
||||
`endif
|
||||
`endif
|
||||
|
||||
// The pixel clock is sent through the fourth differential pair.
|
||||
assign gpdi_dp[3] = pixel_clk;
|
||||
|
||||
endmodule
|
||||
|
||||
/**************************************************************************************/
|
||||
|
||||
`ifdef BENCH_OR_LINT
|
||||
|
||||
module GFX_PLL(
|
||||
input wire pclk, // the board's clock
|
||||
output wire pixel_clk, // pixel clock
|
||||
output wire pixel_clk_x5 // 5 times pixel clock freq (used by TMDS serializer)
|
||||
);
|
||||
assign pixel_clk = pclk;
|
||||
assign pixel_clk_x5 = pclk;
|
||||
endmodule
|
||||
|
||||
`else
|
||||
|
||||
`ifdef ULX3S
|
||||
|
||||
module GFX_PLL(
|
||||
input wire pclk, // the board's clock
|
||||
output wire pixel_clk, // pixel clock
|
||||
output wire pixel_clk_x5 // 5 times pixel clock freq (used by TMDS serializer)
|
||||
// The TMDS serializers operate at (pixel_clock_freq * 10),
|
||||
// but we use DDR mode, hence (pixel_clock_freq * 5).
|
||||
);
|
||||
|
||||
// The parameters of the PLL,
|
||||
// They are found by using: ecppll -i 25 -o <5*pixel_clock> -f foobar.v
|
||||
|
||||
`ifdef MODE_640x480
|
||||
localparam CLKI_DIV = 1;
|
||||
localparam CLKOP_DIV = 5;
|
||||
localparam CLKOP_CPHASE = 2;
|
||||
localparam CLKOP_FPHASE = 0;
|
||||
localparam CLKFB_DIV = 5;
|
||||
`endif
|
||||
|
||||
`ifdef MODE_800x600
|
||||
localparam CLKI_DIV = 1;
|
||||
localparam CLKOP_DIV = 3;
|
||||
localparam CLKOP_CPHASE = 1;
|
||||
localparam CLKOP_FPHASE = 0;
|
||||
localparam CLKFB_DIV = 8;
|
||||
`endif
|
||||
|
||||
`ifdef MODE_1024x768
|
||||
localparam CLKI_DIV = 1;
|
||||
localparam CLKOP_DIV = 2;
|
||||
localparam CLKOP_CPHASE = 1;
|
||||
localparam CLKOP_FPHASE = 0;
|
||||
localparam CLKFB_DIV = 13;
|
||||
`endif
|
||||
|
||||
`ifdef MODE_1280x1024
|
||||
localparam CLKI_DIV = 3;
|
||||
localparam CLKOP_DIV = 1;
|
||||
localparam CLKOP_CPHASE = 0;
|
||||
localparam CLKOP_FPHASE = 0;
|
||||
localparam CLKFB_DIV = 65;
|
||||
`endif
|
||||
|
||||
// The PLL converts a 25 MHz clock into a (pixel_clock_freq * 5) clock
|
||||
// The (half) TMDS serializer clock is generated on pin CLKOP.
|
||||
// In addition, the pixel clock (at TMDS freq/5) is generated on
|
||||
// pin CLKOS (hence CLKOS_DIV = 5*CLKOP_DIV).
|
||||
(* ICP_CURRENT="12" *) (* LPF_RESISTOR="8" *) (* MFG_ENABLE_FILTEROPAMP="1" *) (* MFG_GMCREF_SEL="2" *)
|
||||
EHXPLLL #(
|
||||
.CLKI_DIV(CLKI_DIV),
|
||||
.CLKOP_DIV(CLKOP_DIV),
|
||||
.CLKOP_CPHASE(CLKOP_CPHASE),
|
||||
.CLKOP_FPHASE(CLKOP_FPHASE),
|
||||
.CLKOS_ENABLE("ENABLED"),
|
||||
.CLKOS_DIV(5*CLKOP_DIV),
|
||||
.CLKOS_CPHASE(CLKOP_CPHASE),
|
||||
.CLKOS_FPHASE(CLKOP_FPHASE),
|
||||
.CLKFB_DIV(CLKFB_DIV)
|
||||
) pll_i (
|
||||
.CLKI(pclk),
|
||||
.CLKOP(pixel_clk_x5),
|
||||
.CLKFB(pixel_clk_x5),
|
||||
.CLKOS(pixel_clk),
|
||||
.PHASESEL0(1'b0),
|
||||
.PHASESEL1(1'b0),
|
||||
.PHASEDIR(1'b1),
|
||||
.PHASESTEP(1'b1),
|
||||
.PHASELOADREG(1'b1),
|
||||
.PLLWAKESYNC(1'b0),
|
||||
.ENCLKOP(1'b0)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
`endif
|
||||
`endif
|
||||
Reference in New Issue
Block a user