Advertisement
Guest User

Untitled

a guest
May 14th, 2019
150
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.53 KB | None | 0 0
  1. // video.v - 1k byte video buffer & drive logic
  2. // 2nd generation w/ better timing, no chars in overscan region
  3. // 03-19-19 E. Brombaugh
  4.  
  5. `default_nettype none
  6.  
  7. module video(
  8. input clk, // 16MHz system clock
  9. input clk_2x, // 32MHz pixel clock
  10. input reset, // active high system reset
  11. input mode, // text/graphic mode control
  12. input [1:0] bank, // VRAM bank select
  13. input sel, // decoded video address
  14. input we, // write enable
  15. input [12:0] addr, // address (8k range)
  16. input [7:0] din, // write data
  17. output [7:0] dout, // read data
  18. inout [3:0] vdac // video DAC signal
  19. );
  20. // set up timing parameters for 32MHz clock rate
  21. localparam MAX_H = 2037; // 2038 clocks/line
  22. localparam MAX_V = 261; // 262 lines/frame
  23. localparam HS_WID = 149; // 150 clocks/4.7us H sync pulse
  24. localparam BK_TOP = 16; // Blanking top on line
  25. localparam BK_BOT = 240; // Blanking bottom on line
  26. localparam VS_LIN = 248; // Vsync on line
  27. localparam VS_WID = 1887; // 1888 clocks/59us V sync pulse
  28. localparam ASTART = 371; // start of active area @ 11.6us
  29.  
  30. // revised video timing - separate H and V counters
  31. reg [10:0] hcnt;
  32. reg [8:0] vcnt;
  33. reg hs, vs;
  34. always @(posedge clk_2x)
  35. begin
  36. if(reset)
  37. begin
  38. hcnt <= 11'd0;
  39. vcnt <= 9'd0;
  40. hs <= 1'b0;
  41. vs <= 1'b1;
  42. end
  43. else
  44. begin
  45. // counters
  46. if(hcnt == MAX_H)
  47. begin
  48. hcnt <= 10'd0;
  49. if(vcnt == MAX_V)
  50. vcnt <= 9'd0;
  51. else
  52. vcnt <= vcnt + 9'd1;
  53. end
  54. else
  55. hcnt <= hcnt + 1;
  56.  
  57. // sync pulses
  58. hs <= (hcnt < HS_WID) ? 1'b0 : 1'b1;
  59. vs <= ((hcnt < VS_WID)&&(vcnt == VS_LIN)) ? 1'b0 : 1'b1;
  60. end
  61. end
  62.  
  63. // extract video character data address & ROM line
  64. reg active; // active video
  65. reg [2:0] dcnt; // decimate counter (1/3)
  66. reg pixena; // pixel rate enable
  67. reg [2:0] pcnt; // pixel/char count
  68. reg vload; // load video shift reg
  69. reg [4:0] haddr; // horizontal component of vram addr
  70. reg [2:0] cline; // character line index
  71. reg [4:0] vaddr; // vertical component of vram addr
  72. always @(posedge clk_2x)
  73. begin
  74. if(reset)
  75. begin
  76. active <= 1'b0;
  77. dcnt <= 3'b000;
  78. pixena <= 1'b0;
  79. pcnt <= 3'b000;
  80. vload <= 1'b0;
  81. haddr <= 5'd0;
  82. cline <= 3'b000;
  83. vaddr <= 5'd0;
  84. end
  85. else
  86. begin
  87. // wait for start of active
  88. if(active == 1'b0)
  89. begin
  90. if((hcnt == ASTART) && (vcnt >= BK_TOP) && (vcnt < BK_BOT))
  91. begin
  92. // reset horizontal stuff at hcnt == ASTART
  93. active <= 1'b1; // active video
  94. dcnt <= 3'b000;
  95. pixena <= 1'b1; // start with enable
  96. pcnt <= 3'b000;
  97. vload <= 1'b1; // start with load
  98. haddr <= 5'd0;
  99.  
  100. // reset vertical stuff at vcnt == 0;
  101. if(vcnt == BK_TOP)
  102. begin
  103. cline <= 3'b000;
  104. vaddr <= 5'd0;
  105. end
  106. end
  107. end
  108. else
  109. begin
  110. // divide clock by 6 to get pixel
  111. if(dcnt == 3'b101)
  112. begin
  113. // generate pixel enable
  114. dcnt <= 3'b000;
  115. pixena <= 1'b1;
  116. if(pcnt == 3'b111)
  117. begin
  118. // generate vload
  119. vload <= 1'b1;
  120.  
  121. // end of line?
  122. if(haddr == 5'd31)
  123. begin
  124. // shut off counting & loading
  125. active <= 1'b0;
  126. vload <= 1'b0;
  127. pixena <= 1'b0;
  128.  
  129. // time to update vertical address?
  130. if(cline == 3'b111)
  131. vaddr <= vaddr + 5'd1;
  132.  
  133. // update character line index
  134. cline <= cline + 3'b001;
  135. end
  136.  
  137. // update horizontal address
  138. haddr <= haddr + 5'd1;
  139. end
  140. else
  141. vload <= 1'b0;
  142.  
  143. // always increment pixel count
  144. pcnt <= pcnt + 3'b001;
  145. end
  146. else
  147. begin
  148. dcnt <= dcnt + 2'b01;
  149. pixena <= 1'b0;
  150. end
  151. end
  152. end
  153. end
  154.  
  155. // pipeline control signals
  156. reg [1:0] pixena_pipe, vload_pipe;
  157. reg [2:0] active_pipe, hs_pipe, vs_pipe;
  158. reg [2:0] cline_dly;
  159. always @(posedge clk_2x)
  160. begin
  161. pixena_pipe <= {pixena_pipe[0],pixena};
  162. vload_pipe <= {vload_pipe[0],vload};
  163. active_pipe <= {active_pipe[1:0],active};
  164. hs_pipe <= {hs_pipe[1:0],hs};
  165. vs_pipe <= {vs_pipe[1:0],vs};
  166. cline_dly <= cline;
  167. end
  168. wire pixena_dly = pixena_pipe[1];
  169. wire vload_dly = vload_pipe[1];
  170. wire active_dly = active_pipe[2];
  171. wire hs_dly = hs_pipe[2];
  172. wire vs_dly = vs_pipe[2];
  173.  
  174. // concatenate horizontal and vertical addresses to make vram address
  175. wire [12:0] vid_addr = mode ? {vaddr,cline,haddr} : {3'b000,vaddr,haddr};
  176.  
  177. // invert msb of cpu addr due to decoding on D/E range
  178. wire [12:0] cpu_addr = addr ^ 13'h1000;
  179.  
  180. // address mux selects video or CPU - video in 1st half and CPU in 2nd half
  181. wire [12:0] mem_addr = clk ? vid_addr : cpu_addr;
  182.  
  183. // cpu writes to video memory only on 2nd half of CPU clock cycle
  184. wire mem_we = sel & we & ~clk;
  185.  
  186. // instantiated video memory
  187. wire [7:0] ram_dout;
  188. ram_32kb uram(
  189. .clk(clk_2x),
  190. .sel(1'b1),
  191. .we(mem_we),
  192. .wp(8'h00),
  193. .addr({bank,mem_addr}),
  194. .din(din),
  195. .dout(ram_dout)
  196. );
  197.  
  198. // hold data for full cycle for CPU
  199. reg [7:0] hld_dout;
  200. always @(posedge clk_2x)
  201. if(clk)
  202. hld_dout <= ram_dout;
  203.  
  204. // mux between live & held data for cpu
  205. always @(*)
  206. dout = clk ? ram_dout : hld_dout;
  207.  
  208. // one pipe delay
  209.  
  210. // Character Generator ROM
  211. wire [10:0] cg_addr = {ram_dout,cline_dly};
  212. wire [7:0] cg_dout;
  213. rom_cg_2kB ucgr(
  214. .clk(clk_2x),
  215. .addr(cg_addr),
  216. .dout(cg_dout)
  217. );
  218.  
  219. // graphics mode pass-thru
  220. reg [7:0] gfx_dout;
  221. always @(posedge clk_2x)
  222. gfx_dout <= ram_dout;
  223.  
  224. // mux CG or GFX
  225. wire [7:0] vdat = mode ? gfx_dout : cg_dout;
  226.  
  227. // two pipes delay
  228.  
  229. // Video Shift Register
  230. reg [7:0] vid_shf_reg;
  231. always @(posedge clk_2x)
  232. if(pixena_dly)
  233. begin
  234. if(vload_dly)
  235. vid_shf_reg <= vdat;
  236. else
  237. vid_shf_reg <= {vid_shf_reg[6:0],1'b0};
  238. end
  239.  
  240. // three pipes delay
  241.  
  242. // combine and reclock outputs
  243. reg luma, sync;
  244. always @(posedge clk_2x)
  245. begin
  246. luma <= active_dly & vid_shf_reg[7];
  247. sync <= hs_dly & vs_dly;
  248. end
  249.  
  250. // translate sync + luma to video DAC
  251. reg [3:0] pre_vdac;
  252. always @(*)
  253. if(!sync)
  254. pre_vdac = 4'h0;
  255. else
  256. begin
  257. if(luma)
  258. pre_vdac = 4'hf;
  259. else
  260. pre_vdac = 4'h3;
  261. end
  262.  
  263. // video DAC output register & drivers
  264. SB_IO #(
  265. .PIN_TYPE(6'b101001),
  266. .PULLUP(1'b1),
  267. .NEG_TRIGGER(1'b0),
  268. .IO_STANDARD("SB_LVCMOS")
  269. ) uvdac[3:0] (
  270. .PACKAGE_PIN(vdac),
  271. .LATCH_INPUT_VALUE(1'b0),
  272. .CLOCK_ENABLE(1'b1),
  273. .INPUT_CLK(1'b0),
  274. .OUTPUT_CLK(clk_2x),
  275. .OUTPUT_ENABLE(1'b1),
  276. .D_OUT_0(pre_vdac),
  277. .D_OUT_1(1'b0),
  278. .D_IN_0(),
  279. .D_IN_1()
  280. );
  281. endmodule
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement