mirror of
https://github.com/MiSTer-devel/PCXT_MiSTer.git
synced 2026-05-24 03:04:19 +00:00
Pause and Credits based on jtframe by @jotego
I have modified jtframe to adapt it to the characteristics of the core, with 64 characters instead of 32.
This commit is contained in:
57
PCXT.sv
57
PCXT.sv
@@ -319,6 +319,7 @@ module emu
|
||||
|
||||
wire VGA_VBlank_border;
|
||||
wire std_hsyncwidth;
|
||||
wire pause_core;
|
||||
|
||||
always @(posedge CLK_VIDEO)
|
||||
begin
|
||||
@@ -1122,7 +1123,8 @@ module emu
|
||||
.enable_a000h (a000h),
|
||||
.wait_count_clk_en (~clk_cpu & clk_cpu_ff_2),
|
||||
.ram_read_wait_cycle (ram_read_wait_cycle),
|
||||
.ram_write_wait_cycle (ram_write_wait_cycle)
|
||||
.ram_write_wait_cycle (ram_write_wait_cycle),
|
||||
.pause_core (pause_core)
|
||||
);
|
||||
|
||||
wire [15:0] SDRAM_DQ_IN;
|
||||
@@ -1142,7 +1144,7 @@ module emu
|
||||
.CLK(clk_cpu),
|
||||
|
||||
.RESET(reset_cpu),
|
||||
.READY(processor_ready),
|
||||
.READY(processor_ready && ~pause_core),
|
||||
.NMI(1'b0),
|
||||
.INTR(interrupt_to_cpu),
|
||||
|
||||
@@ -1263,8 +1265,8 @@ module emu
|
||||
cmp_r <= compr(out_r);
|
||||
end
|
||||
|
||||
assign AUDIO_L = status[37:36] ? cmp_l : out_l;
|
||||
assign AUDIO_R = status[37:36] ? cmp_r : out_r;
|
||||
assign AUDIO_L = pause_core ? 1'b0 : status[37:36] ? cmp_l : out_l;
|
||||
assign AUDIO_R = pause_core ? 1'b0 : status[37:36] ? cmp_r : out_r;
|
||||
assign AUDIO_S = 1;
|
||||
assign AUDIO_MIX = status[39:38];
|
||||
|
||||
@@ -1489,6 +1491,12 @@ module emu
|
||||
assign CE_PIXEL = ce_pixel;
|
||||
*/
|
||||
|
||||
wire LHBL = border_video_ff ? HBlank_fixed : HBlank_VGA;
|
||||
wire LVBL = border_video_ff ? std_hsyncwidth ? VGA_VBlank_border : ~VSync : VBlank;
|
||||
|
||||
wire pre2x_LHBL, pre2x_LVBL;
|
||||
wire [7:0] pre2x_r, pre2x_g, pre2x_b;
|
||||
|
||||
|
||||
video_mixer #(.GAMMA(1)) video_mixer_cga
|
||||
(
|
||||
@@ -1500,12 +1508,12 @@ module emu
|
||||
|
||||
.freeze_sync(),
|
||||
|
||||
.R(raux_cga),
|
||||
.G(gaux_cga),
|
||||
.B(baux_cga),
|
||||
.R(pre2x_r),
|
||||
.G(pre2x_g),
|
||||
.B(pre2x_b),
|
||||
|
||||
.HBlank(border_video_ff ? HBlank_fixed : HBlank_VGA),
|
||||
.VBlank(border_video_ff ? std_hsyncwidth ? VGA_VBlank_border : ~VSync : VBlank),
|
||||
.HBlank(pre2x_LHBL),
|
||||
.VBlank(pre2x_LVBL),
|
||||
.HSync(HSync),
|
||||
.VSync(VSync),
|
||||
|
||||
@@ -1641,6 +1649,37 @@ module emu
|
||||
// .mosi (vsdMosi ),
|
||||
// .miso (vsdMiso )
|
||||
// );
|
||||
|
||||
jtframe_credits #(
|
||||
.PAGES (4),
|
||||
.COLW (8),
|
||||
.BLKPOL (1)
|
||||
) u_credits(
|
||||
.rst ( reset ),
|
||||
.clk ( clk_chipset ), // alt: CLK_VIDEO_CGA
|
||||
.pxl_cen ( CE_PIXEL_cga ), // alt: ce_pixel_cga
|
||||
|
||||
// input image
|
||||
.HB ( LHBL ),
|
||||
.VB ( LVBL ),
|
||||
.rgb_in ( { raux_cga, gaux_cga, baux_cga } ),
|
||||
.rotate ( 2'd0 ),
|
||||
.toggle ( 1'b0 ),
|
||||
.fast_scroll( 1'b0 ),
|
||||
.border ( border_video_ff ),
|
||||
|
||||
.vram_din ( 8'h0 ),
|
||||
.vram_dout ( ),
|
||||
.vram_addr ( 8'h0 ),
|
||||
.vram_we ( 1'b0 ),
|
||||
.vram_ctrl ( 3'b0 ),
|
||||
.enable ( pause_core ),
|
||||
|
||||
// output image
|
||||
.HB_out ( pre2x_LHBL ),
|
||||
.VB_out ( pre2x_LVBL ),
|
||||
.rgb_out ( {pre2x_r, pre2x_g, pre2x_b } )
|
||||
);
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
4
credits/Makefile
Normal file
4
credits/Makefile
Normal file
@@ -0,0 +1,4 @@
|
||||
programs = msg2hex
|
||||
|
||||
all: $(programs)
|
||||
|
||||
111
credits/msg
Normal file
111
credits/msg
Normal file
@@ -0,0 +1,111 @@
|
||||
\R * ( ( )
|
||||
\R ( ` )\\ ) * ) )\\ ) ( ( /( * )
|
||||
\R )\\))( ( (()/(` ) /( ( ( (()/( )\\ )\\())` ) /(
|
||||
\R ((_)()\\ )\\ /(_))( )(_))))\\ )( /(_)|((_)((_)\\ ( )(_))
|
||||
\W (_()((_|(_|_)) (_(_())/((_|()\\ (_)) )\\_____((_)(_(_())
|
||||
\W | \\/ |(_) __||_ _(_)) ((_) | _ ((/ __\\ \\/ /|_ _|
|
||||
\W | |\\/| || \\__ \\ | | / -_)| '_| | _/| (__ > < | |
|
||||
\W |_| |_||_|___/ |_| \\___||_| |_| \\___/_/\\_\\ |_|
|
||||
|
||||
\W & Tandy 1000 by \Gspark2k06
|
||||
|
||||
Aitor Gomez Garcia
|
||||
https://ko-fi.com/spark2k06
|
||||
|
||||
\BPOWERED BY
|
||||
|
||||
KFPC-XT * kitune-san
|
||||
https://github.com/kitune-san
|
||||
|
||||
MCL86 * Ted Fried
|
||||
http://www.microcorelabs.com/
|
||||
|
||||
GraphicsGremlin * TubeTime
|
||||
https://tubetime.us/
|
||||
|
||||
\BALSO
|
||||
|
||||
JTOPL * JT89 * JTCREDITS
|
||||
Jose Tejada (jotego)
|
||||
https://www.patreon.com/jotego
|
||||
|
||||
MS Mouse PS2 to Serial
|
||||
Antonio Sanchez (TheSonders)
|
||||
https://github.com/TheSonders
|
||||
|
||||
SAA1099 (Tandy Sound)
|
||||
Dave Hooper (stripwax)
|
||||
https://github.com/stripwax
|
||||
|
||||
SAA1099 (Tandy Sound)
|
||||
Miguel Angel Rodriguez Jodar (mcleod-ideafix)
|
||||
https://github.com/mcleod-ideafix
|
||||
|
||||
2 Button Analog Joysticks
|
||||
Flandango
|
||||
https://github.com/Flandango
|
||||
|
||||
UART 16750
|
||||
Sebastian Witt
|
||||
https://opencores.org/users/hasw/profile
|
||||
|
||||
Other ao486-based modules
|
||||
Alexey Melnikov (sorgelig)
|
||||
https://www.patreon.com/FPGAMiSTer
|
||||
|
||||
______________________________________________________________
|
||||
|
||||
\BDEVELOPERS \W& \GCO-WORKERS
|
||||
|
||||
Aitor Gomez Garcia (spark2k06)
|
||||
kitune-san
|
||||
Ted Fried (MicroCoreLabs)
|
||||
somhi
|
||||
David Gila Blazquez (Mills)
|
||||
flynnsbit
|
||||
Jason Alexander (JasonA)
|
||||
Newsdee
|
||||
birdybro
|
||||
Pedro Gimeno (pgimeno)
|
||||
Jordi Segura (Jordi)
|
||||
|
||||
______________________________________________________________
|
||||
|
||||
\BSpecial Thanks
|
||||
|
||||
https://www.xtideuniversalbios.org/
|
||||
https://www.lo-tech.co.uk
|
||||
https://github.com/640-KB/GLaBIOS
|
||||
https://github.com/virtualxt/pcxtbios
|
||||
https://github.com/skiselev/8088_bios
|
||||
Alejandro Valero Sebastian (Wilco2009)
|
||||
naeloob
|
||||
gyurco
|
||||
|
||||
______________________________________________________________
|
||||
|
||||
\BThanks for supporting this project!!!
|
||||
|
||||
Adr1048
|
||||
TonyEscobar
|
||||
Kathleen
|
||||
Jordi Segura (Jordi)
|
||||
thorr
|
||||
Caldor
|
||||
|
||||
______________________________________________________________
|
||||
|
||||
\RReport issues to
|
||||
https://github.com/MiSTer-devel/PCXT_MiSTer/issues
|
||||
|
||||
|
||||
\BSome Known Issues
|
||||
|
||||
* The AREA5150 demo has graphical glitches.
|
||||
|
||||
* More than the standard 16 colours of simulated
|
||||
composite video are not displayed reliably.
|
||||
|
||||
* Timing issues mean that the image may not display well on
|
||||
CRTs and some vertical line shifts to the right of the
|
||||
image, such as 640x400x4 and sometimes 320x200x16.
|
||||
105
credits/msg2hex.cc
Normal file
105
credits/msg2hex.cc
Normal file
@@ -0,0 +1,105 @@
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <ctype.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void parse_line( int *buf, ifstream& fin );
|
||||
|
||||
int main( int argc, char *argv[] ) {
|
||||
if( argc != 2 ) {
|
||||
cout << "ERROR: expecting .msg filename\n";
|
||||
return 1;
|
||||
}
|
||||
string fname( argv[1] );
|
||||
ifstream fin( fname );
|
||||
if( !fin.good() ) {
|
||||
cout << "ERROR: cannot open file " << fname << '\n';
|
||||
return 2;
|
||||
}
|
||||
// Parse file
|
||||
int *buf = new int[16*1024]; // Max 16 kB
|
||||
for(int k=0; k<16*1024; k++ ) buf[k]=0;
|
||||
int *pline = buf;
|
||||
int line=0;
|
||||
|
||||
try {
|
||||
while( !fin.eof() ) {
|
||||
parse_line( pline, fin );
|
||||
pline += 0x40;
|
||||
if( pline-buf >= 16*1024 ) {
|
||||
throw "ERROR: file is too long for 16kB ";
|
||||
}
|
||||
line++;
|
||||
}
|
||||
// Dump the contents
|
||||
ofstream fout( "msg.hex" );
|
||||
for( int k=0; k<16*1024; k++ ) {
|
||||
fout << hex << buf[k] << '\n';
|
||||
}
|
||||
fout.close();
|
||||
fout.open( "msg.bin" );
|
||||
for( int k=0; k<16*1024; k++ ) {
|
||||
int v = buf[k];
|
||||
for( int bit=0; bit<9; bit++ ) {
|
||||
if( v&0x100 ) fout << '1'; else fout << '0';
|
||||
v<<=1;
|
||||
}
|
||||
fout << '\n';
|
||||
}
|
||||
} catch( const char* error ) {
|
||||
cout << "ERROR: " << error << "at line " << dec << (line+1) << '\n';
|
||||
delete []buf;
|
||||
return 3;
|
||||
}
|
||||
|
||||
delete []buf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void parse_line( int *buf, ifstream& fin ) {
|
||||
string line;
|
||||
getline( fin, line );
|
||||
int pal=3;
|
||||
bool brk=false;
|
||||
int cnt=0;
|
||||
for( int i : line ) {
|
||||
if( brk ) {
|
||||
if( i=='\\' ) {
|
||||
brk = false;
|
||||
}
|
||||
else {
|
||||
switch( toupper(i) ) {
|
||||
case 'R': pal=0; break;
|
||||
case 'G': pal=1; break;
|
||||
case 'B': pal=2; break;
|
||||
case 'W': pal=3; break;
|
||||
default: {
|
||||
throw "ERROR: invalid palette code ";
|
||||
}
|
||||
}
|
||||
brk = false;
|
||||
// cout << pal << '\n';
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if( i=='\\' ) {
|
||||
// cout << "BRK";
|
||||
brk=true;
|
||||
continue;
|
||||
}
|
||||
// actual chars
|
||||
if( cnt++ == 64 ) {
|
||||
throw "line is longer than 64 characters, ";
|
||||
}
|
||||
if( i<0x20 || i>0x7f ) {
|
||||
throw "character code out of range ";
|
||||
}
|
||||
int v = i-0x20;
|
||||
v&=0x7f;
|
||||
v |= pal<<7;
|
||||
*buf++ = v;
|
||||
}
|
||||
}
|
||||
@@ -153,7 +153,8 @@ module CHIPSET (
|
||||
// RAM wait mode
|
||||
input logic wait_count_clk_en,
|
||||
input logic [1:0] ram_read_wait_cycle,
|
||||
input logic [1:0] ram_write_wait_cycle
|
||||
input logic [1:0] ram_write_wait_cycle,
|
||||
output logic pause_core
|
||||
);
|
||||
|
||||
logic [19:0] latch_address;
|
||||
@@ -367,7 +368,8 @@ module CHIPSET (
|
||||
.fdd_dma_req (fdd_dma_req),
|
||||
.fdd_dma_ack (~dma_acknowledge_n[2]),
|
||||
.terminal_count (terminal_count_n),
|
||||
.xtctl (xtctl)
|
||||
.xtctl (xtctl),
|
||||
.pause_core (pause_core)
|
||||
);
|
||||
|
||||
RAM u_RAM
|
||||
|
||||
@@ -16,7 +16,8 @@ module KFPS2KB #(
|
||||
|
||||
output logic irq,
|
||||
output logic [7:0] keycode,
|
||||
input logic clear_keycode
|
||||
input logic clear_keycode,
|
||||
output reg pause_core = 1'b0
|
||||
);
|
||||
//
|
||||
// Internal Signals
|
||||
@@ -246,6 +247,19 @@ module KFPS2KB #(
|
||||
keycode <= 8'h00;
|
||||
break_flag <= 1'b1;
|
||||
end
|
||||
else if (register == 8'h07) begin
|
||||
// F12 -> Pause core and credits
|
||||
irq <= 1'b0;
|
||||
keycode <= 8'h00;
|
||||
break_flag <= 1'b0;
|
||||
pause_core <= break_flag ? ~pause_core : pause_core;
|
||||
end
|
||||
else if (pause_core) begin
|
||||
// The core is paused and the credits are visible
|
||||
irq <= 1'b0;
|
||||
keycode <= 8'h00;
|
||||
break_flag <= 1'b0;
|
||||
end
|
||||
else begin
|
||||
// Make code
|
||||
irq <= 1'b1;
|
||||
|
||||
@@ -121,7 +121,8 @@ module PERIPHERALS #(
|
||||
input logic fdd_dma_ack,
|
||||
input logic terminal_count,
|
||||
// XTCTL DATA
|
||||
output logic [7:0] xtctl = 8'h00
|
||||
output logic [7:0] xtctl = 8'h00,
|
||||
output logic pause_core
|
||||
);
|
||||
|
||||
wire [4:0] clkdiv;
|
||||
@@ -442,7 +443,8 @@ module PERIPHERALS #(
|
||||
// I/O
|
||||
.irq (keybord_irq),
|
||||
.keycode (keycode),
|
||||
.clear_keycode (clear_keycode)
|
||||
.clear_keycode (clear_keycode),
|
||||
.pause_core (pause_core)
|
||||
);
|
||||
|
||||
// Keybord reset
|
||||
|
||||
@@ -8,3 +8,6 @@ set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) MSMouse
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) ide.v ]
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) bram.vhd ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) tandy_pcjr_joy.sv ]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtframe_credits.v ]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtframe_ram.v ]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtframe_dual_ram.v ]
|
||||
1024
rtl/common/font0.hex
Normal file
1024
rtl/common/font0.hex
Normal file
File diff suppressed because it is too large
Load Diff
446
rtl/common/jtframe_credits.v
Normal file
446
rtl/common/jtframe_credits.v
Normal file
@@ -0,0 +1,446 @@
|
||||
/* This file is part of JTFRAME.
|
||||
JTFRAME program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
JTFRAME program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with JTFRAME. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 14-3-2020 */
|
||||
|
||||
// 8x8 tiles
|
||||
|
||||
module jtframe_credits #(
|
||||
parameter PAGES = 1,
|
||||
COLW = 4, // bits per pixel colour component
|
||||
parameter [11:0] PAL0 = { 4'hf, 4'h0, 4'h0 }, // Red
|
||||
parameter [11:0] PAL1 = { 4'h0, 4'hf, 4'h0 }, // Green
|
||||
parameter [11:0] PAL2 = { 4'h3, 4'h3, 4'hf }, // Blue
|
||||
parameter [11:0] PAL3 = { 4'hf, 4'hf, 4'hf }, // White
|
||||
parameter BLKPOL = 1'b1, // Blanking polarity
|
||||
parameter SPEED = 2 // scroll speed
|
||||
) (
|
||||
input rst,
|
||||
input clk,
|
||||
|
||||
// input image
|
||||
input pxl_cen,
|
||||
input HB,
|
||||
input VB,
|
||||
input [COLW*3-1:0] rgb_in,
|
||||
|
||||
// Optional VRAM control
|
||||
input [8:0] vram_din,
|
||||
input [9:0] vram_addr,
|
||||
input vram_we,
|
||||
output [8:0] vram_dout,
|
||||
|
||||
// control
|
||||
input enable, // shows the screen and resets the scroll counter
|
||||
input toggle, // disables the screen. Only has an effect if enable is high
|
||||
input [2:0] vram_ctrl,
|
||||
input fast_scroll,
|
||||
input [1:0] rotate,
|
||||
input border,
|
||||
|
||||
// output image
|
||||
output reg HB_out,
|
||||
output reg VB_out,
|
||||
output reg [COLW*3-1:0] rgb_out
|
||||
);
|
||||
|
||||
localparam MSGW = PAGES == 1 ? 11 :
|
||||
(PAGES == 2 ? 12 :
|
||||
(PAGES > 2 && PAGES <=4 ? 13 :
|
||||
(PAGES > 5 && PAGES <=8 ? 14 : 15 ))); // Support for upto 16 pages
|
||||
localparam VPOSW = MSGW-2;
|
||||
localparam HPOSW = 10;
|
||||
localparam _MAXVISIBLE = PAGES*24*8-1; // workaround to avoid a warning
|
||||
localparam [VPOSW-1:0] MAXVISIBLE = _MAXVISIBLE[VPOSW-1:0];
|
||||
|
||||
localparam [HPOSW-1:0] HSTART = 0, HEND = 514;
|
||||
|
||||
wire [HPOSW-1:0] hoffset = 64 + (border ? 73 : 0);
|
||||
|
||||
reg [HPOSW-1:0] hn;
|
||||
wire [HPOSW-1:0] hscan;
|
||||
reg [VPOSW-1:0] scrpos, vdump, vdump1;
|
||||
reg [8:0] vrender;
|
||||
wire [8:0] scan_data;
|
||||
wire [7:0] font_data;
|
||||
reg [MSGW-1:0] scan_addr;
|
||||
wire [9:0] font_addr = {scan_data[6:0],
|
||||
rotate==2'b11 ? (~vdump[2:0]+3'd1) : vdump[2:0] };
|
||||
wire visible = vrender < MAXVISIBLE;
|
||||
reg last_toggle, last_enable;
|
||||
reg show, hide;
|
||||
wire vram_mode = vram_ctrl[0];
|
||||
wire vram_nc;
|
||||
|
||||
assign hscan = hn - hoffset;
|
||||
|
||||
jtframe_dual_ram #(.dw(10), .aw(MSGW),.synfile("msg.bin"),.ascii_bin(1)) u_msg(
|
||||
.clk0 ( clk ),
|
||||
.clk1 ( clk ),
|
||||
// Port 0: optional write access
|
||||
.data0 ( {1'b1, vram_din } ),
|
||||
.addr0 ( { {MSGW-10{1'b0}}, vram_addr } ),
|
||||
.we0 ( vram_we ),
|
||||
.q0 ( { vram_nc, vram_dout } ),
|
||||
// Port 1: video dump
|
||||
.data1 ( 10'd0 ),
|
||||
.addr1 ( scan_addr ),
|
||||
.we1 ( 1'b0 ),
|
||||
.q1 ( scan_data )
|
||||
);
|
||||
|
||||
jtframe_ram #(.aw(10),.synfile("font0.hex")) u_font(
|
||||
.clk ( clk ),
|
||||
.cen ( 1'b1 ),
|
||||
.data ( 8'd0 ),
|
||||
.addr ( font_addr ),
|
||||
.we ( 1'b0 ),
|
||||
.q ( font_data )
|
||||
);
|
||||
|
||||
reg [1:0] pal;
|
||||
reg [2:0] pxl;
|
||||
|
||||
localparam MULTIPAGE = MSGW > 11;
|
||||
|
||||
// hb and vb are always active high
|
||||
wire hb = BLKPOL ? HB : ~HB;
|
||||
wire vb = BLKPOL ? VB : ~VB;
|
||||
reg [7:0] pxl_data;
|
||||
wire tate = rotate[0],
|
||||
tate_flip = rotate==2'b11;
|
||||
|
||||
reg last_hb, last_vb;
|
||||
reg [3:0] scr_base;
|
||||
|
||||
wire hb_edge = hb && !last_hb;
|
||||
|
||||
always @(posedge clk) if(pxl_cen) begin
|
||||
if( tate || hb_edge ) begin
|
||||
vdump1 <= scrpos + (tate ? hscan : vrender);
|
||||
vdump <= vdump1;
|
||||
end
|
||||
end
|
||||
|
||||
wire [VPOSW-1:3] vidx_flip = (~vdump[VPOSW-1:3])+1'd1;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if( rst ) begin
|
||||
hn <= HSTART;
|
||||
scrpos <= {VPOSW{1'b0}};
|
||||
vrender <= 8'd0;
|
||||
scr_base <= 4'd0;
|
||||
end else if(pxl_cen) begin
|
||||
last_hb <= hb;
|
||||
last_vb <= vb;
|
||||
if( hb_edge ) begin
|
||||
vrender <= vrender + 8'd1;
|
||||
end
|
||||
hn <= hb ? HSTART : hn+9'd1;
|
||||
// scrpos: scroll counter
|
||||
// gets reset each time the pause button is pressed
|
||||
if( enable && !last_enable ) begin
|
||||
scrpos <= tate_flip ? MAXVISIBLE : {VPOSW{1'b0}};
|
||||
end else begin
|
||||
if ( vb ) begin
|
||||
vrender <= 0;
|
||||
if( !last_vb && MULTIPAGE ) begin
|
||||
// Scroll runs at max speed when the visible pages are over
|
||||
// otherwise it runs at SPEED
|
||||
if( scr_base == SPEED || (scrpos > MAXVISIBLE && scrpos < (MAXVISIBLE << 2)) || fast_scroll ) begin
|
||||
scrpos <= tate_flip ? (scrpos-1'b1) : (scrpos + 1'b1);
|
||||
scr_base <= 4'd0;
|
||||
end else scr_base <= scr_base + 4'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
if( vram_mode ) scrpos <= 0;
|
||||
//if( /*tate || hn[2:0]==3'd0 || hb || vb ) begin
|
||||
scan_addr <= tate ?
|
||||
{ rotate[1] ? vidx_flip : vdump[VPOSW-1:3], vrender[7:3]^{5{~rotate[1]}} } :
|
||||
{ vdump[VPOSW-1:3], hscan[8:3] };
|
||||
//end
|
||||
// Draw
|
||||
if( tate ) begin
|
||||
pxl <= { scan_data[8:7], font_data[ vrender[2:0] ^{3{rotate[1]}} ] };
|
||||
end else begin
|
||||
pxl <= { pal, pxl_data[7] };
|
||||
if( hscan[2:0]==3'd1 ) begin
|
||||
pal <= scan_data[8:7];
|
||||
pxl_data <= font_data;
|
||||
end else begin
|
||||
pxl_data <= pxl_data << 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Object Generator
|
||||
|
||||
|
||||
`ifdef JTFRAME_AVATARS
|
||||
reg [ 7:0] buf_din;
|
||||
reg buf_we0, buf_we1;
|
||||
reg [ 7:0] buf_addr0;
|
||||
|
||||
reg [11:0] lut_addr;
|
||||
wire [ 7:0] lut_data;
|
||||
|
||||
reg [12:0] obj_addr;
|
||||
wire [15:0] obj_data;
|
||||
|
||||
wire [ 7:0] pal_addr;
|
||||
wire [11:0] pal_data;
|
||||
reg [11:0] obj_pxl;
|
||||
reg [ 7:0] obj_id, obj_x, obj_y;
|
||||
|
||||
reg line = 1'b0;
|
||||
|
||||
jtframe_dual_ram #(.dw(8), .aw(9)) u_linebuffer(
|
||||
.clk0 ( clk ),
|
||||
.clk1 ( clk ),
|
||||
// Port 0: new data writes
|
||||
.data0 ( buf_din ),
|
||||
.addr0 ( { line, buf_addr0 } ),
|
||||
.we0 ( buf_we0 ),
|
||||
.q0 ( ),
|
||||
// Port 1
|
||||
.data1 ( ~8'd0 ),
|
||||
.addr1 ( { ~line, hscan[7:0] } ),
|
||||
.we1 ( buf_we1 ),
|
||||
.q1 ( pal_addr )
|
||||
);
|
||||
|
||||
jtframe_ram #(.dw(8), .aw(12),.synfile("lut.hex")) u_lut(
|
||||
.clk ( clk ),
|
||||
.cen ( 1'b1 ),
|
||||
.data ( 8'd0 ),
|
||||
.addr ( lut_addr ),
|
||||
.we ( 1'b0 ),
|
||||
.q ( lut_data )
|
||||
);
|
||||
|
||||
jtframe_ram #(.dw(16), .aw(13),.synfile("avatar.hex")) u_obj(
|
||||
.clk ( clk ),
|
||||
.cen ( 1'b1 ),
|
||||
.data ( 16'd0 ),
|
||||
.addr ( obj_addr ),
|
||||
.we ( 1'b0 ),
|
||||
.q ( obj_data )
|
||||
);
|
||||
|
||||
jtframe_ram #(.dw(12), .aw(4+4),.synfile("avatar_pal.hex")) u_pal(
|
||||
.clk ( clk ),
|
||||
.cen ( 1'b1 ),
|
||||
.data ( 12'd0 ),
|
||||
.addr ( pal_addr ),
|
||||
.we ( 1'b0 ),
|
||||
.q ( pal_data )
|
||||
);
|
||||
|
||||
wire [VPOSW-1:0] vsub = vdump1 - { lut_data, 3'b0 };
|
||||
reg [3:0] obj_pal;
|
||||
reg [3:0] x,y,z,w;
|
||||
|
||||
reg [4:0] st;
|
||||
reg first;
|
||||
|
||||
reg last_hb2; // this is one is not gated by pxl_cen
|
||||
|
||||
always @(posedge clk) begin
|
||||
last_hb2 <= hb;
|
||||
if( hb && !last_hb2 ) begin
|
||||
lut_addr <= 12'd0;
|
||||
first <= 1'b1;
|
||||
st <= 0;
|
||||
line <= ~line;
|
||||
buf_we0 <= 1'b0;
|
||||
buf_addr0<= 8'd0;
|
||||
end else begin
|
||||
st <= st+1;
|
||||
case( st )
|
||||
0: begin
|
||||
if( lut_addr==12'd0 && !first ) st <= 0;
|
||||
end
|
||||
1: begin
|
||||
lut_addr <= lut_addr + 12'd1;
|
||||
first <= 1'b0;
|
||||
end
|
||||
2: begin
|
||||
lut_addr <= lut_addr + 12'd1;
|
||||
obj_id <= lut_data;
|
||||
end
|
||||
3: begin
|
||||
lut_addr <= lut_addr + 12'd1;
|
||||
obj_x <= lut_data;
|
||||
end
|
||||
4: begin
|
||||
lut_addr <= lut_addr + 12'd1;
|
||||
obj_y <= lut_data;
|
||||
obj_addr <= { obj_id[6:0], vsub[3:0], 2'b0 }; // 7+4+2 = 13
|
||||
if( !({lut_data,3'b0} <= vdump1 && {lut_data,3'b0}+16 > vdump1) ) st <= 0;
|
||||
if( obj_id==8'hff ) begin // end of LUT
|
||||
lut_addr <= 12'd0;
|
||||
st <= 0;
|
||||
end
|
||||
end
|
||||
5: obj_pal <= lut_data;
|
||||
6: begin
|
||||
buf_addr0 <= { obj_x-8'd1, 3'b111 };
|
||||
{z,y,x,w} <= obj_data;
|
||||
obj_addr[1:0] <= 2'b01;
|
||||
end
|
||||
7,8,9,10, 12,13,14,15,
|
||||
17,18,19,20, 22,23,24,25: begin
|
||||
buf_addr0 <= buf_addr0 + 1;
|
||||
// xywz
|
||||
// wxyz
|
||||
// zyxw
|
||||
// zywx
|
||||
// zwyx
|
||||
// zwxy
|
||||
buf_din <= { obj_pal, z[3],y[3],x[3],w[3] };
|
||||
buf_we0 <= 1'b1;
|
||||
obj_x <= obj_x + 1;
|
||||
x <= x << 1;
|
||||
y <= y << 1;
|
||||
z <= z << 1;
|
||||
w <= w << 1;
|
||||
end
|
||||
11: begin
|
||||
{z,y,x,w} <= obj_data;
|
||||
obj_addr[1:0] <= 2'b10;
|
||||
end
|
||||
16: begin
|
||||
{z,y,x,w} <= obj_data;
|
||||
obj_addr[1:0] <= 2'b11;
|
||||
end
|
||||
21: {z,y,x,w} <= obj_data;
|
||||
26: begin
|
||||
buf_we0<= 1'b0;
|
||||
st <= 0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
reg rd=1'b0;
|
||||
reg [ 2:0] st2=3'd0;
|
||||
reg obj_ok;
|
||||
|
||||
always @(posedge clk ) begin
|
||||
st2 <= st2+1;
|
||||
case( st2 )
|
||||
3: begin
|
||||
obj_pxl <= pal_data;
|
||||
obj_ok <= pal_addr[3:0] != 4'hf; // visible pixel
|
||||
buf_we1 <= !hscan[9]; // do not empty the line buffer when
|
||||
// scanning the left side of the screen
|
||||
// This applies when JTFRAME_CREDITS_HSTART!=0
|
||||
end
|
||||
4: begin
|
||||
buf_we1 <= 1'b0;
|
||||
if( pxl_cen ) st2 <= 0; else st2 <= 4;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
`else
|
||||
wire [11:0] obj_pxl = ~12'h0;
|
||||
wire obj_ok = 1'b0;
|
||||
`endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Colour Mixer
|
||||
// Merge the new image with the old
|
||||
localparam R1 = COLW*3-1;
|
||||
localparam R0 = COLW*2;
|
||||
localparam G1 = COLW*2-1;
|
||||
localparam G0 = COLW;
|
||||
localparam B1 = COLW-1;
|
||||
localparam B0 = 0;
|
||||
|
||||
wire [COLW*3-1:0] dim = { 1'b0, rgb_in[R1:R0+1], 1'b0, rgb_in[G1:G0+1], 1'b0, rgb_in[B1:B0+1] };
|
||||
|
||||
function [COLW*3-1:0] extend;
|
||||
input [11:0] rgb4;
|
||||
extend =
|
||||
COLW==5 ? {
|
||||
rgb4[11:8], rgb4[11],
|
||||
rgb4[7:4], rgb4[7],
|
||||
rgb4[3:0], rgb4[3]
|
||||
} : (
|
||||
COLW==4 ? rgb4 :
|
||||
{
|
||||
rgb4[11:8], rgb4[11:8],
|
||||
rgb4[7:4], rgb4[7:4],
|
||||
rgb4[3:0], rgb4[3:0]
|
||||
});
|
||||
endfunction
|
||||
|
||||
always @(posedge clk, posedge rst) begin
|
||||
if( rst ) begin
|
||||
show <= 0;
|
||||
hide <= 0;
|
||||
last_toggle <= 0;
|
||||
last_enable <= 0;
|
||||
end else begin
|
||||
last_enable <= enable;
|
||||
last_toggle <= toggle;
|
||||
if( enable ) begin
|
||||
if( vram_mode ) begin
|
||||
show <= 1;
|
||||
hide <= 0;
|
||||
end else begin
|
||||
show <= ~hide;
|
||||
if( toggle && !last_toggle ) begin
|
||||
hide <= ~hide;
|
||||
end
|
||||
end
|
||||
end else show <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) if(pxl_cen) begin
|
||||
{ HB_out, VB_out } <= { HB, VB };
|
||||
// if hoffset != 0 and the game is vertical, the full horizontal length
|
||||
// of the screen is used. Otherwise, the credits will start at hoffset
|
||||
// and last for 512 pixels
|
||||
if( !show || ( hoffset!=0 && !tate && (hn<hoffset || hn>=(HEND+hoffset))) )
|
||||
rgb_out <= rgb_in;
|
||||
else begin
|
||||
if( (!pxl[0] && (!obj_ok || vram_mode)) || !visible ) begin
|
||||
if( vram_ctrl[0] ) begin
|
||||
rgb_out <= (vdump[7] ? vram_ctrl[2] : vram_ctrl[1]) ? dim : rgb_in;
|
||||
end else begin
|
||||
rgb_out <= dim;
|
||||
end
|
||||
end else begin
|
||||
if( pxl[0] || tate ) begin // CHAR, OBJ disabled for TATE
|
||||
case( pxl[2:1] )
|
||||
2'd0: rgb_out <= extend(PAL0);
|
||||
2'd1: rgb_out <= extend(PAL1);
|
||||
2'd2: rgb_out <= extend(PAL2);
|
||||
2'd3: rgb_out <= extend(PAL3);
|
||||
endcase
|
||||
end else rgb_out <= extend(obj_pxl); // OBJ
|
||||
end
|
||||
if( vb || hb ) rgb_out <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
217
rtl/common/jtframe_dual_ram.v
Normal file
217
rtl/common/jtframe_dual_ram.v
Normal file
@@ -0,0 +1,217 @@
|
||||
/* This file is part of JTFRAME.
|
||||
JTFRAME program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
JTFRAME program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with JTFRAME. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 27-10-2017 */
|
||||
|
||||
// Generic dual port RAM with clock enable
|
||||
// parameters:
|
||||
// dw => Data bit width, 8 for byte-based memories
|
||||
// aw => Address bit width, 10 for 1kB
|
||||
// simfile => binary file to load during simulation
|
||||
// simhexfile => hexadecimal file to load during simulation
|
||||
// synfile => hexadecimal file to load for synthesis
|
||||
|
||||
/* verilator lint_off MULTIDRIVEN */
|
||||
|
||||
module jtframe_dual_ram #(parameter dw=8, aw=10,
|
||||
simfile="", simhexfile="",
|
||||
synfile="",
|
||||
ascii_bin=0, // set to 1 to read the ASCII file as binary
|
||||
dumpfile="dump.hex"
|
||||
)(
|
||||
// Port 0
|
||||
input clk0,
|
||||
input [dw-1:0] data0,
|
||||
input [aw-1:0] addr0,
|
||||
input we0,
|
||||
output [dw-1:0] q0,
|
||||
// Port 1
|
||||
input clk1,
|
||||
input [dw-1:0] data1,
|
||||
input [aw-1:0] addr1,
|
||||
input we1,
|
||||
output [dw-1:0] q1
|
||||
`ifdef JTFRAME_DUAL_RAM_DUMP
|
||||
,input dump
|
||||
`endif
|
||||
);
|
||||
|
||||
jtframe_dual_ram_cen #(
|
||||
.dw ( dw ),
|
||||
.aw ( aw ),
|
||||
.simfile ( simfile ),
|
||||
.simhexfile ( simhexfile),
|
||||
.synfile ( synfile ),
|
||||
.ascii_bin ( ascii_bin ),
|
||||
.dumpfile ( dumpfile )
|
||||
) u_ram (
|
||||
.clk0 ( clk0 ),
|
||||
.cen0 ( 1'b1 ),
|
||||
.clk1 ( clk1 ),
|
||||
.cen1 ( 1'b1 ),
|
||||
// Port 0
|
||||
.data0 ( data0 ),
|
||||
.addr0 ( addr0 ),
|
||||
.we0 ( we0 ),
|
||||
.q0 ( q0 ),
|
||||
// Port 1
|
||||
.data1 ( data1 ),
|
||||
.addr1 ( addr1 ),
|
||||
.we1 ( we1 ),
|
||||
.q1 ( q1 )
|
||||
`ifdef JTFRAME_DUAL_RAM_DUMP
|
||||
,.dump ( dump )
|
||||
`endif
|
||||
);
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
module jtframe_dual_ram_cen #(parameter dw=8, aw=10,
|
||||
simfile="", simhexfile="",
|
||||
synfile="",
|
||||
ascii_bin=0, // set to 1 to read the ASCII file as binary
|
||||
dumpfile="dump.hex"
|
||||
)(
|
||||
input clk0,
|
||||
input cen0,
|
||||
input clk1,
|
||||
input cen1,
|
||||
// Port 0
|
||||
input [dw-1:0] data0,
|
||||
input [aw-1:0] addr0,
|
||||
input we0,
|
||||
output [dw-1:0] q0,
|
||||
// Port 1
|
||||
input [dw-1:0] data1,
|
||||
input [aw-1:0] addr1,
|
||||
input we1,
|
||||
output [dw-1:0] q1
|
||||
`ifdef JTFRAME_DUAL_RAM_DUMP
|
||||
,input dump
|
||||
`endif
|
||||
);
|
||||
|
||||
`ifdef SIMULATION
|
||||
localparam SIMULATION=1;
|
||||
`else
|
||||
localparam SIMULATION=0;
|
||||
`endif
|
||||
|
||||
`ifdef POCKET
|
||||
localparam POCKET=1;
|
||||
`else
|
||||
localparam POCKET=0;
|
||||
`endif
|
||||
|
||||
generate
|
||||
if( !SIMULATION && POCKET && aw<13 && dw<=8 ) begin
|
||||
jtframe_pocket_dualram u_pocket_ram(
|
||||
.address_a( addr0 ),
|
||||
.address_b( addr1 ),
|
||||
.clock_a ( clk0 ),
|
||||
.clock_b ( clk1 ),
|
||||
.data_a ( data0 ),
|
||||
.data_b ( data1 ),
|
||||
.enable_a ( cen0 ),
|
||||
.enable_b ( cen1 ),
|
||||
.wren_a ( we0 ),
|
||||
.wren_b ( we1 ),
|
||||
.q_a ( q0 ),
|
||||
.q_b ( q1 )
|
||||
);
|
||||
end else begin
|
||||
reg [dw-1:0] qq0, qq1;
|
||||
(* ramstyle = "no_rw_check" *) reg [dw-1:0] mem[0:(2**aw)-1];
|
||||
|
||||
assign { q0, q1 } = { qq0, qq1 };
|
||||
|
||||
always @(posedge clk0) if(cen0) begin
|
||||
qq0 <= mem[addr0];
|
||||
if(we0) mem[addr0] <= data0;
|
||||
end
|
||||
|
||||
always @(posedge clk1) if(cen1) begin
|
||||
qq1 <= mem[addr1];
|
||||
if(we1) mem[addr1] <= data1;
|
||||
end
|
||||
|
||||
/* verilator lint_off WIDTH */
|
||||
`ifdef SIMULATION
|
||||
// Content dump for simulation debugging
|
||||
`ifdef JTFRAME_DUAL_RAM_DUMP
|
||||
integer fdump=0, dumpcnt;
|
||||
|
||||
always @(posedge dump) begin
|
||||
$display("INFO: contents dumped to %s", dumpfile );
|
||||
if( fdump==0 )begin
|
||||
fdump=$fopen(dumpfile,"w");
|
||||
end
|
||||
for( dumpcnt=0; dumpcnt<2**aw; dumpcnt=dumpcnt+1 )
|
||||
$fdisplay(fdump,"%X", mem[dumpcnt]);
|
||||
end
|
||||
`endif
|
||||
|
||||
integer f, readcnt;
|
||||
initial begin
|
||||
for( f=0; f<(2**aw)-1;f=f+1) begin
|
||||
mem[f] = 0;
|
||||
end
|
||||
if( simfile != "" ) begin
|
||||
f=$fopen(simfile,"rb");
|
||||
if( f != 0 ) begin
|
||||
readcnt=$fread( mem, f );
|
||||
$display("INFO: Read %14s (%4d bytes/%2d%%) for %m",
|
||||
simfile, readcnt, readcnt*100/(2**aw));
|
||||
if( readcnt != 2**aw )
|
||||
$display(" the memory was not filled by the file data");
|
||||
$fclose(f);
|
||||
end else begin
|
||||
$display("WARNING: %m cannot open file: %s", simfile);
|
||||
end
|
||||
end
|
||||
else begin
|
||||
if( simhexfile != "" ) begin
|
||||
$readmemh(simhexfile,mem);
|
||||
$display("INFO: Read %14s (hex) for %m", simhexfile);
|
||||
end else begin
|
||||
if( synfile!= "" ) begin
|
||||
if( ascii_bin==1 )
|
||||
$readmemb(synfile,mem);
|
||||
else
|
||||
$readmemh(synfile,mem);
|
||||
$display("INFO: Read %14s (hex) for %m", synfile);
|
||||
end else
|
||||
for( readcnt=0; readcnt<2**aw; readcnt=readcnt+1 )
|
||||
mem[readcnt] = {dw{1'b0}};
|
||||
end
|
||||
end
|
||||
end
|
||||
`else
|
||||
// file for synthesis:
|
||||
initial if(synfile!="" ) begin
|
||||
if( ascii_bin==1 )
|
||||
$readmemb(synfile,mem);
|
||||
else
|
||||
$readmemh(synfile,mem);
|
||||
end
|
||||
`endif
|
||||
end
|
||||
endgenerate
|
||||
|
||||
/* verilator lint_on WIDTH */
|
||||
endmodule
|
||||
/* verilator lint_on MULTIDRIVEN */
|
||||
81
rtl/common/jtframe_ram.v
Normal file
81
rtl/common/jtframe_ram.v
Normal file
@@ -0,0 +1,81 @@
|
||||
/* This file is part of JTFRAME.
|
||||
JTFRAME program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
JTFRAME program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with JTFRAME. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 27-10-2017 */
|
||||
|
||||
// Generic RAM with clock enable
|
||||
// parameters:
|
||||
// dw => Data bit width, 8 for byte-based memories
|
||||
// aw => Address bit width, 10 for 1kB
|
||||
// simfile => binary file to load during simulation
|
||||
// simhexfile => hexadecimal file to load during simulation
|
||||
// synfile => hexadecimal file to load for synthesis
|
||||
// cen_rd => Use clock enable for reading too, by default it is used
|
||||
// only for writting.
|
||||
|
||||
|
||||
module jtframe_ram #(parameter dw=8, aw=10,
|
||||
simfile="", simhexfile="",
|
||||
synfile="", synbinfile="",
|
||||
cen_rd=0)(
|
||||
input clk,
|
||||
input cen /* direct_enable */,
|
||||
input [dw-1:0] data,
|
||||
input [aw-1:0] addr,
|
||||
input we,
|
||||
output reg [dw-1:0] q
|
||||
);
|
||||
|
||||
(* ramstyle = "no_rw_check" *) reg [dw-1:0] mem[0:(2**aw)-1];
|
||||
|
||||
`ifdef SIMULATION
|
||||
integer f, readcnt;
|
||||
initial
|
||||
if( simfile != 0 ) begin
|
||||
f=$fopen(simfile,"rb");
|
||||
if( f != 0 ) begin
|
||||
readcnt=$fread( mem, f );
|
||||
$display("INFO: Read %14s (%4d bytes) for %m",simfile, readcnt);
|
||||
$fclose(f);
|
||||
end else begin
|
||||
$display("WARNING: %m cannot open file: %s", simfile);
|
||||
end
|
||||
end
|
||||
else begin
|
||||
if( simhexfile != 0 ) begin
|
||||
$readmemh(simhexfile,mem);
|
||||
$display("INFO: Read %14s (hex) for %m", simhexfile);
|
||||
end else begin
|
||||
if( synfile != 0 ) begin
|
||||
$readmemh(synfile,mem);
|
||||
$display("INFO: Read %14s for %m", synfile);
|
||||
end else
|
||||
for( readcnt=0; readcnt<(2**aw)-1; readcnt=readcnt+1 )
|
||||
mem[readcnt] = {dw{1'b0}};
|
||||
end
|
||||
end
|
||||
`else
|
||||
// file for synthesis:
|
||||
initial if(synfile!=0 )$readmemh(synfile,mem);
|
||||
initial if(synbinfile!=0 )$readmemb(synbinfile,mem);
|
||||
`endif
|
||||
|
||||
always @(posedge clk) begin
|
||||
if( !cen_rd || cen ) q <= mem[addr];
|
||||
if( cen && we) mem[addr] <= data;
|
||||
end
|
||||
|
||||
endmodule
|
||||
16384
rtl/common/msg.bin
Normal file
16384
rtl/common/msg.bin
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user