module zx2_sram(clk28,reset,R,G,B,bright,HSync, VSync, ioreq,memreq,refr,wr_n,rd_n,M1, ram_addr,ram_data,cpu_data, cpu_addr,A14_rom, clk_div, video_access, interrupt, turbo, DL, speaker, v0, text_mode ); input clk28,reset,turbo; input ioreq, memreq, refr, wr_n, rd_n, M1; input [7:0] ram_data; inout [7:0] cpu_data; input [15:0] cpu_addr; input [3:0]clk_div; input text_mode; output reg R; output reg G; output reg B; output reg bright; output HSync, VSync; output [12:0] ram_addr; output A14_rom; output video_access; output interrupt, speaker, v0; output reg [5:0] DL; wire [12:0] addr; reg mux_high; reg [5:0] Hor_Cnt; reg [5:0] Ver_Cnt; reg extra_vert_cnt = 0; assign v0 = extra_vert_cnt; //reg [2:0] ChrC_Cnt; wire [2:0] ChrC_Cnt; reg [2:0] ChrR_Cnt; reg [3:0] Invert; reg [7:0] Shift; reg [7:0] Attr_r; reg [7:0] Attr_hold; reg [7:0] Vdata; reg real_blank; reg Blank_r; wire Blank_n; reg [4:0] Border; reg HSync, VSync; wire get_vdata, get_attr; // wire [7:0] cpu_addr_muxed; wire video; wire A16, A17; wire a7FFD_C; reg [1:0] state; reg [1:0] next_state; wire vid_a15, sync; wire video_clk; // assign video_clk = (clk_div[1:0] == 0); assign video_clk = (clk_div[0] == 0); reg cpu_wants_RAM; // assign video = (state == 2); //assign video = (ChrC_Cnt == 0); assign video = (clk_div[2:0] == 3); assign A14_rom = DL[4]; assign A16 = video ? 1 : DL[2]; assign vid_a15 = DL[3]; assign sync = ~(HSync ^ VSync); assign addr = clk_div[3] ? { Ver_Cnt[4:3], ChrR_Cnt, Ver_Cnt[2:0], Hor_Cnt[4:0]} : { 3'b110, Ver_Cnt[4:0], Hor_Cnt[4:0]}; assign get_vdata = video & clk_div[3]; assign get_attr = video & ~clk_div[3]; assign ram_addr = addr; assign video_access = video; assign interrupt = (Ver_Cnt == 6'b11111) && (Hor_Cnt[5:4] == 0) && (ChrR_Cnt == 0) & ~extra_vert_cnt; assign ChrC_Cnt = clk_div[3:1]; assign speaker = Border[4]; always @(posedge clk28 ) begin // if(video_clk) begin if(get_vdata) Vdata <= ram_data; if(get_attr) Attr_hold <= ram_data; // end end always @(posedge clk28 or posedge reset ) begin // transition on cpu clock going up if(reset) state <= 0; else if((clk_div[0] == 0) | turbo) state <= next_state; end // always @(posedge clk28 or posedge reset ) begin always @(*) begin if(reset) cpu_wants_RAM <= 0; else cpu_wants_RAM <= ~memreq && refr; end always @* begin case (state) 2'b00: if(~Blank_n && ~ChrC_Cnt[2] && ~ChrC_Cnt[1] && ~ChrC_Cnt[0]) begin if((memreq || ~refr) && ioreq) next_state <= 2; else next_state <= 1; end else next_state <= 0; 2'b01: // can wait up 2 two cycles if((memreq || ~refr) && ioreq ) next_state <= 2; else next_state <= 1; 2'b10: next_state <= 0; 2'b11: next_state <= 0; endcase end always @(posedge clk28 or posedge reset) begin // if( ~ioreq && ~wr_n && (ram_addr_m == 8'hFE)) begin if(reset) begin DL <= 0; end else if( ~ioreq && ~wr_n ) begin if(~cpu_addr[0]) Border <= cpu_data[4:0]; else if(~cpu_addr[1] & cpu_addr[14] & ~cpu_addr[15]) /*& M1 */ DL <= cpu_data[5:0]; end end wire [9:0] fontrom_addr; wire [7:0] fontrom_data; wire [6:0] char_code; fontrom fontrom ( .address(fontrom_addr), .clock(clk28), .q(fontrom_data)); assign char_code = Attr_hold;//{ Ver_Cnt[2:0], Hor_Cnt[4:0]}; assign fontrom_addr = {char_code, ChrR_Cnt}; always @(posedge clk28 or posedge reset) begin if(reset) begin Hor_Cnt <= 0; Ver_Cnt <= 0; // ChrC_Cnt <= 0; ChrR_Cnt <= 0; Invert <= 0; real_blank <= 0; extra_vert_cnt <= 0; // Border <= 0; end else if(video_clk) begin if(ChrC_Cnt == 7) begin // ChrC_Cnt <= 0; if(Hor_Cnt == 55) begin Hor_Cnt <= 0; extra_vert_cnt <= ~extra_vert_cnt; if(extra_vert_cnt) begin ChrR_Cnt <= ChrR_Cnt + 1; if(ChrR_Cnt == 7) begin if (Ver_Cnt == 38) begin ChrR_Cnt <= 0; Ver_Cnt <= 0; Invert <= Invert + 1; end else begin Ver_Cnt <= Ver_Cnt + 1; end end end //extra_vert_cnt end else begin Hor_Cnt <= Hor_Cnt + 1; if (Hor_Cnt == 37) real_blank <= 1; else if (Hor_Cnt == 48) real_blank <= 0; end end /* else begin ChrC_Cnt <= ChrC_Cnt + 1; end */ end end //always assign Blank_n = Hor_Cnt[5] | Ver_Cnt[5] | (Ver_Cnt[4] & Ver_Cnt[3]); always @(posedge clk28 ) begin if(reset) begin Shift <= 0; // Attr_r <= 0; end else if(video_clk) begin if (ChrC_Cnt == 7) begin if(text_mode) Shift <= fontrom_data; else Shift <= Vdata; Attr_r <= Attr_hold; end else begin Shift <= {Shift[6:0], 1'b0}; end if((real_blank == 1) || VSync) begin R <= 0; G <= 0; B <= 0; end else begin // real blank if (Blank_r == 0) begin if(text_mode) begin bright <= 1'b1; R <= Shift[7]; G <= Shift[7]; B <= Shift[7]; end else begin // not text mode bright <= Attr_r[6]; if (Shift[7] ^ (Attr_r[7] & Invert[3])) begin G <= Attr_r[2]; R <= Attr_r[1]; B <= Attr_r[0]; end else begin G <= Attr_r[5]; R <= Attr_r[4]; B <= Attr_r[3]; end end // text mode end else begin bright <= 0; G <= Border[2]; R <= Border[1]; B <= Border[0]; end end // real blank if (ChrC_Cnt == 7) Blank_r <= Blank_n; end //reset end //always always @(posedge clk28 ) begin if(reset) begin HSync <= 0; VSync <= 0; end else begin if (Hor_Cnt[5] & Hor_Cnt[3] & (Hor_Cnt[4] | ~Hor_Cnt[2])) HSync <= 1; else HSync <= 0; if (Ver_Cnt[4 : 0] == 5'b11111) VSync <= 1; else VSync <= 0; end end //always endmodule