bsx.v 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. `timescale 1ns / 1ps
  2. //////////////////////////////////////////////////////////////////////////////////
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 02:43:54 02/06/2011
  7. // Design Name:
  8. // Module Name: bsx
  9. // Project Name:
  10. // Target Devices:
  11. // Tool versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. //
  20. //////////////////////////////////////////////////////////////////////////////////
  21. module bsx(
  22. input clkin,
  23. input reg_oe,
  24. input reg_we,
  25. input [23:0] snes_addr,
  26. input [7:0] reg_data_in,
  27. output [7:0] reg_data_out,
  28. input [7:0] reg_reset_bits,
  29. input [7:0] reg_set_bits,
  30. output [14:0] regs_out,
  31. input pgm_we,
  32. input use_bsx,
  33. output data_ovr,
  34. output flash_writable,
  35. input [59:0] rtc_data,
  36. output [9:0] bs_page_out, // support only page 0000-03ff
  37. output bs_page_enable,
  38. output [8:0] bs_page_offset
  39. );
  40. wire [3:0] reg_addr = snes_addr[19:16]; // 00-0f:5000-5fff
  41. wire [4:0] base_addr = snes_addr[4:0]; // 88-9f -> 08-1f
  42. wire [15:0] flash_addr = snes_addr[15:0];
  43. reg flash_ovr_r;
  44. reg flash_we_r;
  45. reg [7:0] flash_cmd0;
  46. reg [15:0] flash_cmd5555;
  47. wire cart_enable = (use_bsx) && ((snes_addr[23:12] & 12'hf0f) == 12'h005);
  48. wire base_enable = (use_bsx) && (!snes_addr[22] && (snes_addr[15:0] >= 16'h2188)
  49. && (snes_addr[15:0] <= 16'h219f));
  50. wire flash_enable = (snes_addr[23:16] == 8'hc0);
  51. wire is_flash_special_address = (flash_addr == 16'h0002
  52. || flash_addr == 16'h5555
  53. || flash_addr == 16'h2aaa
  54. || flash_addr == 16'h0000
  55. || (flash_addr >= 16'hff00
  56. && flash_addr <= 16'hff13));
  57. wire flash_ovr = (use_bsx)
  58. && (flash_enable & flash_ovr_r)
  59. && is_flash_special_address;
  60. assign flash_writable = (use_bsx)
  61. && flash_enable
  62. && flash_we_r
  63. && !is_flash_special_address;
  64. assign data_ovr = (cart_enable | base_enable | flash_ovr) & ~bs_page_enable;
  65. reg [9:0] bs_page0;
  66. reg [9:0] bs_page1;
  67. reg [8:0] bs_page0_offset;
  68. reg [8:0] bs_page1_offset;
  69. reg [4:0] bs_stb0_offset;
  70. reg [4:0] bs_stb1_offset;
  71. wire bs_sta0_en = base_addr == 5'h0a;
  72. wire bs_stb0_en = base_addr == 5'h0b;
  73. wire bs_page0_en = base_addr == 5'h0c;
  74. wire bs_sta1_en = base_addr == 5'h10;
  75. wire bs_stb1_en = base_addr == 5'h11;
  76. wire bs_page1_en = base_addr == 5'h12;
  77. assign bs_page_enable = base_enable & ((|bs_page0 & (bs_page0_en | bs_sta0_en | bs_stb0_en))
  78. |(|bs_page1 & (bs_page1_en | bs_sta1_en | bs_stb1_en)));
  79. assign bs_page_out = (bs_page0_en | bs_sta0_en | bs_stb0_en) ? bs_page0 : bs_page1;
  80. assign bs_page_offset = bs_sta0_en ? 9'h032
  81. : bs_stb0_en ? (9'h034 + bs_stb0_offset)
  82. : bs_sta1_en ? 9'h032
  83. : bs_stb1_en ? (9'h034 + bs_stb1_offset)
  84. : (9'h048 + (bs_page0_en ? bs_page0_offset : bs_page1_offset));
  85. reg [3:0] reg_oe_sreg;
  86. always @(posedge clkin) reg_oe_sreg <= {reg_oe_sreg[2:0], reg_oe};
  87. wire reg_oe_falling = (reg_oe_sreg[3:1] == 3'b100);
  88. wire reg_oe_rising = (reg_oe_sreg[3:1] == 3'b001);
  89. reg [2:0] reg_we_sreg;
  90. always @(posedge clkin) reg_we_sreg <= {reg_we_sreg[1:0], reg_we};
  91. wire reg_we_rising = (reg_we_sreg[2:1] == 2'b01);
  92. reg [1:0] pgm_we_sreg;
  93. always @(posedge clkin) pgm_we_sreg <= {pgm_we_sreg[0], pgm_we};
  94. wire pgm_we_rising = (pgm_we_sreg[1:0] == 2'b01);
  95. reg [14:0] regs_tmpr;
  96. reg [14:0] regs_outr;
  97. reg [7:0] reg_data_outr;
  98. reg [7:0] base_regs[31:8];
  99. reg [4:0] bsx_counter;
  100. reg [7:0] flash_vendor_data[7:0];
  101. assign regs_out = regs_outr;
  102. assign reg_data_out = reg_data_outr;
  103. wire [7:0] rtc_sec = rtc_data[3:0] + (rtc_data[7:4] << 3) + (rtc_data[7:4] << 1);
  104. wire [7:0] rtc_min = rtc_data[11:8] + (rtc_data[15:12] << 3) + (rtc_data[15:12] << 1);
  105. wire [7:0] rtc_hour = rtc_data[19:16] + (rtc_data[23:20] << 3) + (rtc_data[23:20] << 1);
  106. wire [7:0] rtc_day = rtc_data[27:24] + (rtc_data[31:28] << 3) + (rtc_data[31:28] << 1);
  107. wire [7:0] rtc_month = rtc_data[35:32] + (rtc_data[39:36] << 3) + (rtc_data[39:36] << 1);
  108. wire [7:0] rtc_dow = {4'b0,rtc_data[59:56]};
  109. wire [7:0] rtc_year1 = rtc_data[43:40] + (rtc_data[47:44] << 3) + (rtc_data[47:44] << 1);
  110. wire [7:0] rtc_year100 = rtc_data[51:48] + (rtc_data[55:52] << 3) + (rtc_data[55:52] << 1);
  111. wire [15:0] rtc_year = (rtc_year100 << 6) + (rtc_year100 << 5) + (rtc_year100 << 2) + rtc_year1;
  112. initial begin
  113. regs_tmpr <= 15'b000101111101100;
  114. regs_outr <= 15'b000101111101100;
  115. bsx_counter <= 0;
  116. base_regs[5'h08] <= 0;
  117. base_regs[5'h09] <= 0;
  118. base_regs[5'h0a] <= 8'h01;
  119. base_regs[5'h0b] <= 0;
  120. base_regs[5'h0c] <= 0;
  121. base_regs[5'h0d] <= 0;
  122. base_regs[5'h0e] <= 0;
  123. base_regs[5'h0f] <= 0;
  124. base_regs[5'h10] <= 8'h01;
  125. base_regs[5'h11] <= 0;
  126. base_regs[5'h12] <= 0;
  127. base_regs[5'h13] <= 0;
  128. base_regs[5'h14] <= 0;
  129. base_regs[5'h15] <= 0;
  130. base_regs[5'h16] <= 0;
  131. base_regs[5'h17] <= 0;
  132. base_regs[5'h18] <= 0;
  133. base_regs[5'h19] <= 0;
  134. base_regs[5'h1a] <= 0;
  135. base_regs[5'h1b] <= 0;
  136. base_regs[5'h1c] <= 0;
  137. base_regs[5'h1d] <= 0;
  138. base_regs[5'h1e] <= 0;
  139. base_regs[5'h1f] <= 0;
  140. flash_vendor_data[3'h0] <= 8'h4d;
  141. flash_vendor_data[3'h1] <= 8'h00;
  142. flash_vendor_data[3'h2] <= 8'h50;
  143. flash_vendor_data[3'h3] <= 8'h00;
  144. flash_vendor_data[3'h4] <= 8'h00;
  145. flash_vendor_data[3'h5] <= 8'h00;
  146. flash_vendor_data[3'h6] <= 8'h2a;
  147. flash_vendor_data[3'h7] <= 8'h00;
  148. flash_ovr_r <= 1'b0;
  149. flash_we_r <= 1'b0;
  150. bs_page0 <= 10'h0;
  151. bs_page1 <= 10'h0;
  152. bs_page0_offset <= 9'h0;
  153. bs_page1_offset <= 9'h0;
  154. bs_stb0_offset <= 5'h00;
  155. bs_stb1_offset <= 5'h00;
  156. end
  157. always @(posedge clkin) begin
  158. if(reg_oe_rising && base_enable) begin
  159. case(base_addr)
  160. 5'h0b: begin
  161. bs_stb0_offset <= bs_stb0_offset + 1;
  162. base_regs[5'h0d] <= base_regs[5'h0d] | reg_data_in;
  163. end
  164. 5'h0c: bs_page0_offset <= bs_page0_offset + 1;
  165. 5'h11: begin
  166. bs_stb1_offset <= bs_stb1_offset + 1;
  167. base_regs[5'h13] <= base_regs[5'h13] | reg_data_in;
  168. end
  169. 5'h12: bs_page1_offset <= bs_page1_offset + 1;
  170. endcase
  171. end else
  172. if(reg_oe_falling) begin
  173. if(cart_enable)
  174. reg_data_outr <= {regs_outr[reg_addr], 7'b0};
  175. else if(base_enable) begin
  176. case(base_addr)
  177. 5'h0c, 5'h12: begin
  178. case (bs_page1_offset)
  179. 4: reg_data_outr <= 8'h3;
  180. 5: reg_data_outr <= 8'h1;
  181. 6: reg_data_outr <= 8'h1;
  182. 10: reg_data_outr <= rtc_sec;
  183. 11: reg_data_outr <= rtc_min;
  184. 12: reg_data_outr <= rtc_hour;
  185. 13: reg_data_outr <= rtc_dow;
  186. 14: reg_data_outr <= rtc_day;
  187. 15: reg_data_outr <= rtc_month;
  188. 16: reg_data_outr <= rtc_year[7:0];
  189. 17: reg_data_outr <= rtc_hour;
  190. default: reg_data_outr <= 8'h0;
  191. endcase
  192. end
  193. 5'h0d, 5'h13: begin
  194. reg_data_outr <= base_regs[base_addr];
  195. base_regs[base_addr] <= 8'h00;
  196. end
  197. default:
  198. reg_data_outr <= base_regs[base_addr];
  199. endcase
  200. end else if (flash_enable) begin
  201. casex (flash_addr)
  202. 16'h0002:
  203. reg_data_outr <= 8'h80;
  204. 16'h5555:
  205. reg_data_outr <= 8'h80;
  206. 16'b1111111100000xxx:
  207. reg_data_outr <= flash_vendor_data[flash_addr&16'h0007];
  208. default:
  209. reg_data_outr <= 8'h00;
  210. endcase
  211. end
  212. end else if(pgm_we_rising) begin
  213. regs_tmpr[8:1] <= (regs_tmpr[8:1] | reg_set_bits[7:0]) & ~reg_reset_bits[7:0];
  214. regs_outr[8:1] <= (regs_outr[8:1] | reg_set_bits[7:0]) & ~reg_reset_bits[7:0];
  215. end else if(reg_we_rising && cart_enable) begin
  216. if(reg_addr == 4'he)
  217. regs_outr <= regs_tmpr;
  218. else
  219. regs_tmpr[reg_addr] <= reg_data_in[7];
  220. end else if(reg_we_rising && base_enable) begin
  221. case(base_addr)
  222. 5'h09: begin
  223. base_regs[8'h09] <= reg_data_in;
  224. bs_page0 <= {reg_data_in[1:0], base_regs[8'h08]};
  225. bs_page0_offset <= 9'h00;
  226. end
  227. 5'h0b: begin
  228. bs_stb0_offset <= 5'h00;
  229. end
  230. 5'h0c: begin
  231. bs_page0_offset <= 9'h00;
  232. end
  233. 5'h0f: begin
  234. base_regs[8'h0f] <= reg_data_in;
  235. bs_page1 <= {reg_data_in[1:0], base_regs[8'h0e]};
  236. bs_page1_offset <= 9'h00;
  237. end
  238. 5'h11: begin
  239. bs_stb1_offset <= 5'h00;
  240. end
  241. 5'h12: begin
  242. bs_page1_offset <= 9'h00;
  243. end
  244. default:
  245. base_regs[base_addr] <= reg_data_in;
  246. endcase
  247. end else if(reg_we_rising && flash_enable) begin
  248. case(flash_addr)
  249. 16'h0000: begin
  250. flash_cmd0 <= reg_data_in;
  251. if(flash_cmd0 == 8'h38 && reg_data_in == 8'hd0)
  252. flash_ovr_r <= 1;
  253. end
  254. 16'h5555: begin
  255. flash_cmd5555 <= {flash_cmd5555[7:0], reg_data_in};
  256. if(flash_cmd5555 == 16'haa55) begin
  257. case (reg_data_in)
  258. 8'hf0: begin
  259. flash_ovr_r <= 0;
  260. flash_we_r <= 0;
  261. end
  262. 8'ha0: begin
  263. flash_ovr_r <= 1;
  264. flash_we_r <= 1;
  265. end
  266. 8'h70: begin
  267. flash_we_r <= 0;
  268. end
  269. endcase
  270. end
  271. end
  272. 16'h2aaa: begin
  273. flash_cmd5555 <= {flash_cmd5555[7:0], reg_data_in};
  274. end
  275. endcase
  276. end
  277. end
  278. endmodule