Skip to content

Instantly share code, notes, and snippets.

@regymm
Created January 21, 2024 02:46
Show Gist options
  • Save regymm/93aa01486ad10a185976f2e665151e66 to your computer and use it in GitHub Desktop.
Save regymm/93aa01486ad10a185976f2e665151e66 to your computer and use it in GitHub Desktop.
IO_LOC "tmds_d_p" 71,70;
IO_PORT "tmds_d_p" PULL_MODE=NONE DRIVE=8;
#IO_LOC "tmds_d_p[0]" 71,70;
#IO_PORT "tmds_d_p[0]" PULL_MODE=NONE DRIVE=8;
#IO_LOC "tmds_d_p[1]" 73,72;
#IO_PORT "tmds_d_p[1]" PULL_MODE=NONE DRIVE=8;
#IO_LOC "tmds_d_p[2]" 75,74;
#IO_PORT "tmds_d_p[2]" PULL_MODE=NONE DRIVE=8;
#IO_LOC "tmds_clk_p" 69,68;
#IO_PORT "tmds_clk_p" PULL_MODE=NONE DRIVE=8;
IO_LOC "btn" 4;
IO_PORT "btn" PULL_MODE=UP;
IO_LOC "led[0]" 10;
IO_LOC "led[1]" 11;
IO_LOC "led[2]" 13;
IO_LOC "led[3]" 14;
IO_PORT "led[0]" IO_TYPE=LVCMOS33;
IO_PORT "led[1]" IO_TYPE=LVCMOS33;
IO_PORT "led[2]" IO_TYPE=LVCMOS33;
IO_PORT "led[3]" IO_TYPE=LVCMOS33;
IO_LOC "clk" 52;
IO_PORT "clk" IO_TYPE=LVCMOS33 PULL_MODE=UP;
module HDMI_test(
input clk,
output tmds_d_p, tmds_d_n
);
wire pixclk;
wire clk_TMDS;
wire lock;
wire clk_250;
// 250M and 25M
pll_25 pll_25_inst(
.clkin(clk),
.clkout(clk_250),
.clkoutd(pixclk),
.lock(lock)
);
// this is NOT good, but CLKDIV is not supported for now
reg clk_250_r = 0;
always @ (posedge clk_250) clk_250_r <= ~clk_250_r;
assign clk_TMDS = clk_250_r;
wire oscout;
OSC osc_inst(
.OSCOUT(oscout)
);
defparam osc_inst.FREQ_DIV = 2;
wire tmds_d;
OSER10 tmds_serdes (
.Q(tmds_d),
.D0(3'b011),
.D1(3'b110),
.D2(3'b011),
.D3(3'b011),
.D4(3'b110),
.D5(3'b101),
.D6(3'b101),
.D7(3'b011),
.D8(3'b101),
.D9(3'b111),
.PCLK(oscout),
.FCLK(oscout),
.RESET(1'b0)
);
ELVDS_OBUF tmds_bufds (
.I(tmds_d),
.O(tmds_d_p),
.OB(tmds_d_n)
);
endmodule
// https://github.com/sipeed/TangNano-9K-example/tree/main/hdmi
// https://github.com/YosysHQ/apicula/blob/master/examples/pll/rpll.v
module pll_25 (
output clkout,
output clkoutd,
input clkin,
output lock
);
rPLL pll (
.CLKOUT(clkout),
.CLKOUTD(clkoutd),
.CLKIN(clkin),
.CLKFB(0),
.RESET_P(0),
.RESET(0),
.FBDSEL(0),
.IDSEL(0),
.ODSEL(0),
.DUTYDA(0),
.PSDA(0),
.FDLY(0),
.LOCK(lock)
);
// f_clkout = f_clkin * FBDIV / IDIV
// f_clkoutd = f_clkout / SDIV
// f_vco = f_clkout * ODIV
defparam pll.DEVICE = "GW1NR-9";
defparam pll.FCLKIN = "27";
// 27 * 37 / 4 = 249.75, 249.75/10 = 24.975
defparam pll.FBDIV_SEL = 36; // FBDIV = FBDIV_SEL + 1
defparam pll.IDIV_SEL = 3; // IDIV = IDIV_SEL + 1
defparam pll.ODIV_SEL = 4; // PLL at 1000 MHz
defparam pll.CLKFB_SEL="internal";
defparam pll.CLKOUTD3_SRC="CLKOUT";
defparam pll.CLKOUTD_BYPASS="false";
defparam pll.CLKOUTD_SRC="CLKOUT";
defparam pll.CLKOUTP_BYPASS="false";
defparam pll.CLKOUTP_DLY_STEP=0;
defparam pll.CLKOUTP_FT_DIR=1'b1;
defparam pll.CLKOUT_BYPASS="false";
defparam pll.CLKOUT_DLY_STEP=0;
defparam pll.CLKOUT_FT_DIR=1'b1;
defparam pll.DUTYDA_SEL="1000";
defparam pll.DYN_DA_EN="false";
defparam pll.DYN_FBDIV_SEL="false";
defparam pll.DYN_IDIV_SEL="false";
defparam pll.DYN_ODIV_SEL="false";
defparam pll.DYN_SDIV_SEL=10;
defparam pll.PSDA_SEL="0000";
endmodule
BUILDDIR := ${CURDIR}/build
TOP := HDMI_test
LOGFILE := ${BUILDDIR}/top.log
all: ${BUILDDIR} ${BUILDDIR}/top.bit
${BUILDDIR}:
mkdir -m 777 -p ${BUILDDIR} && chown -R nobody ${BUILDDIR} | true
${BUILDDIR}/top.json: $(wildcard oser10elvds.v)
yosys -p "synth_gowin -top ${TOP} -json $@" $^ >> ${LOGFILE} 2>&1
${BUILDDIR}/top_pnr.json: ${BUILDDIR}/top.json $(wildcard *.xdc) $(wildcard *.pcf) $(wildcard *.lpf) $(wildcard *.cst)
nextpnr-gowin --json $< --write $@ --device GW1NR-LV9QN88PC6/I5 --cst $(filter-out $<,$^) >> ${LOGFILE} 2>&1
# It's .fs file, but we always use the name bit
${BUILDDIR}/top.bit: ${BUILDDIR}/top_pnr.json
gowin_pack -c -d GW1N-9C -o $@ $< >> ${LOGFILE} 2>&1
.PHONY: clean
clean:
@rm -f *.bit
@rm -f *.frames
@rm -f *.fasm
@rm -f *.json
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment