OpenCores
URL https://opencores.org/ocsvn/jt51/jt51/trunk

Subversion Repositories jt51

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 2 to Rev 3
    Reverse comparison

Rev 2 → Rev 3

/jt51/trunk/contra/bus_manager.v
0,0 → 1,80
`timescale 1ns / 1ps
 
module bus_manager #(parameter RAM_MSB=10)(
input rst50,
input clk50,
input clk_per,
input [7:0] cpu_data_out,
input [7:0] ROM_data_out,
input [7:0] RAM_data,
input [7:0] jt_data_out,
// Other system elements
input [1:0] sw_sel,
input [7:0] sound_latch,
output clear_irq,
// CPU control
output reg [7:0] cpu_data_in,
input [15:0]addr,
input cpu_vma,
input cpu_rw,
// select signals
output reg RAM_cs,
output reg opm_cs_n
);
 
wire ROM_cs = addr[15];
 
parameter RAM_START = 16'h6000;
parameter RAM_END = RAM_START+(2**(RAM_MSB+1));
parameter ROM_START=16'h8000;
 
wire [15:0] ram_start_contra = 16'h6000;
wire [15:0] ram_end_contra = 16'h7FFF;
wire [15:0] ram_start_ddragon = 16'h0000;
wire [15:0] ram_end_ddragon = 16'h0FFF;
 
// wire [15:0] rom_start_addr = ROM_START;
// wire [15:0] ym_start_addr = 16'h2000;
// wire [15:0] ym_end_addr = 16'h2002;
reg [15:0] irq_clear_addr;
 
reg LATCH_rd;
 
reg [7:0] ym_final_d;
 
always @(*) begin
if( cpu_rw && cpu_vma)
casex( {~opm_cs_n, RAM_cs, ROM_cs, LATCH_rd } )
4'b1XXX: cpu_data_in <= jt_data_out;
4'b01XX: cpu_data_in <= RAM_data;
4'b001X: cpu_data_in <= ROM_data_out;
4'b0001: cpu_data_in <= sound_latch;
default: cpu_data_in <= {8{sw_sel[1]}};
endcase
else
cpu_data_in <= 8'h0;
end
 
// RAM
wire opm_cs_contra = !addr[15] && !addr[14] && addr[13];
wire opm_cs_ddragon= addr>=16'h2800 && addr<=16'h2801;
 
always @(*)
if( sw_sel[0] ) begin
RAM_cs <= cpu_vma && (addr>=ram_start_ddragon && addr<=ram_end_ddragon);
opm_cs_n<= !(cpu_vma && opm_cs_ddragon);
LATCH_rd<= cpu_vma && addr==16'h1000; // Sound latch at $1000
irq_clear_addr <= 16'h1000;
end
else begin
RAM_cs <= cpu_vma && (addr>=ram_start_contra && addr<=ram_end_contra);
opm_cs_n<= !(cpu_vma && opm_cs_contra);
LATCH_rd<= cpu_vma && addr==16'h0; // Sound latch at $0000
irq_clear_addr <= 16'h4000;
end
// Clear IRQ
assign clear_irq = (addr==irq_clear_addr) && cpu_vma ? 1'b1 : 1'b0;
endmodule
/jt51/trunk/contra/clocks.v
0,0 → 1,128
`timescale 1ns / 1ps
 
module clocks(
input rst,
input clk50,
input divide_more,
output clk_cpu,
output clk_dac,
output reg locked
);
wire GND_BIT = 1'b0;
wire clk_base; // 4*3.58MHz
wire CLKDV_BUF;
wire locked0, locked1;
always @(posedge clk_cpu) locked <= locked0 & locked1;
reg [1:0] clk_cpu_cnt;
always @( posedge CLKDV_BUF or posedge rst)
if( rst )
clk_cpu_cnt <= 2'b0;
else
clk_cpu_cnt <= clk_cpu_cnt + 1'b1;
reg clk_sel;
always @( negedge CLKDV_BUF )
clk_sel <= divide_more;
 
BUFG CLKDV_BUFG_INST(
.I( clk_sel ? clk_cpu_cnt[0] : CLKDV_BUF ),
.O(clk_cpu)
);
 
BUFG CLK2X_BUFG_INST (.I(clkbase_2x),
.O( clkbase_fbin ));
DCM_SP #( .CLK_FEEDBACK("2X"), .CLKDV_DIVIDE(2.0), .CLKFX_DIVIDE(7),
.CLKFX_MULTIPLY(2), .CLKIN_DIVIDE_BY_2("FALSE"),
.CLKIN_PERIOD(20.000), .CLKOUT_PHASE_SHIFT("NONE"),
.DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), .DFS_FREQUENCY_MODE("LOW"),
.DLL_FREQUENCY_MODE("LOW"), .DUTY_CYCLE_CORRECTION("TRUE"),
.FACTORY_JF(16'hC080), .PHASE_SHIFT(0), .STARTUP_WAIT("FALSE") )
u_clkbase ( .CLKFB(clkbase_fbin),
.CLKIN(clk50), // *
.DSSEN(GND_BIT),
.PSCLK(GND_BIT),
.PSEN(GND_BIT),
.PSINCDEC(GND_BIT),
.RST(GND_BIT),
.CLKDV(),
.CLKFX(clk_base), // *
.CLKFX180(),
.CLK0(),
.CLK2X(clkbase_2x),
.CLK2X180(),
.CLK90(),
.CLK180(),
.CLK270(),
.LOCKED(locked0),
.PSDONE(),
.STATUS());
 
wire clkdiv0, clkdiv0_buf;
BUFG u_clkdiv_buf(
.I(clkdiv0),
.O(clkdiv0_buf)
);
DCM_SP #( .CLK_FEEDBACK("1X"), .CLKDV_DIVIDE(4.0), .CLKFX_DIVIDE(1),
.CLKFX_MULTIPLY(4), .CLKIN_DIVIDE_BY_2("FALSE"),
.CLKIN_PERIOD(69.832), .CLKOUT_PHASE_SHIFT("NONE"),
.DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), .DFS_FREQUENCY_MODE("LOW"),
.DLL_FREQUENCY_MODE("LOW"), .DUTY_CYCLE_CORRECTION("TRUE"),
.FACTORY_JF(16'hC080), .PHASE_SHIFT(0), .STARTUP_WAIT("FALSE") )
u_clkdiv ( .CLKFB(clkdiv0_buf), //*
.CLKIN(clk_base), //*
.DSSEN(GND_BIT),
.PSCLK(GND_BIT),
.PSEN(GND_BIT),
.PSINCDEC(GND_BIT),
.RST(GND_BIT),
.CLKDV(CLKDV_BUF), //*
.CLKFX(),
.CLKFX180(),
.CLK0(clkdiv0),
.CLK2X(),
.CLK2X180(),
.CLK90(),
.CLK180(),
.CLK270(),
.LOCKED(locked1),
.PSDONE(),
.STATUS());
 
wire clk_dac_pre;
BUFG CLKFX_BUFG_INST (.I(clk_dac_pre),
.O(clk_dac));
 
DCM_SP #( .CLK_FEEDBACK("NONE"), .CLKDV_DIVIDE(2.0), .CLKFX_DIVIDE(1),
.CLKFX_MULTIPLY(2), .CLKIN_DIVIDE_BY_2("FALSE"),
.CLKIN_PERIOD(20.000), .CLKOUT_PHASE_SHIFT("NONE"),
.DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), .DFS_FREQUENCY_MODE("LOW"),
.DLL_FREQUENCY_MODE("LOW"), .DUTY_CYCLE_CORRECTION("TRUE"),
.FACTORY_JF(16'hC080), .PHASE_SHIFT(0), .STARTUP_WAIT("FALSE") )
u_clkdac ( .CLKFB(GND_BIT),
.CLKIN(clk50),
.DSSEN(GND_BIT),
.PSCLK(GND_BIT),
.PSEN(GND_BIT),
.PSINCDEC(GND_BIT),
.RST(GND_BIT),
.CLKDV(),
.CLKFX(clk_dac_pre),
.CLKFX180(),
.CLK0(),
.CLK2X(),
.CLK2X180(),
.CLK90(),
.CLK180(),
.CLK270(),
.LOCKED(),
.PSDONE(),
.STATUS());
endmodule
/jt51/trunk/contra/fake_tone.v
0,0 → 1,72
`timescale 1ns / 1ps
 
module fake_tone(
input rst,
input clk,
input ym_p1,
output onebit
);
wire [15:0] tone, linear;
wire sh, so;
ramp_a_tone tonegen( .rst(rst), .clk(clk), .tone(tone) );
sh_encode encoder( .rst(rst), .ym_p1(ym_p1), .data(tone), .sh(sh), .so(so) );
ym_linearize linearizer( .rst(rst), .sh(sh), .ym_so(so), .ym_p1(ym_p1), .linear(linear) );
sigma_delta1 sd1( .rst(rst), .clk(clk), .data(linear), .sound(onebit) );
endmodule
 
module sh_encode(
input rst,
input ym_p1,
input [15:0] data,
output reg sh,
output so
);
reg [12:0] serial_data;
reg [3:0] cnt;
assign so = serial_data[0];
always @(posedge rst or posedge ym_p1) begin
if( rst ) begin
sh <= 1'b0;
cnt <= 0;
end
else begin
cnt <= cnt + 1'b1;
if( cnt==4'd2 ) begin
casex( data[15:10] )
6'b1XXXXX: serial_data <= { 3'd7, data[15:6]};
6'b01XXXX: serial_data <= { 3'd6, data[14:5]};
6'b001XXX: serial_data <= { 3'd5, data[13:4]};
6'b0001XX: serial_data <= { 3'd4, data[12:3]};
6'b00001X: serial_data <= { 3'd3, data[11:2]};
6'b000001: serial_data <= { 3'd2, data[10:1]};
default: serial_data <= { 3'd1, data[ 9:0]};
endcase
end
else serial_data <= serial_data>>1;
if( cnt==4'd10 ) sh<=1'b1;
if( cnt==4'd15 ) sh<=1'b0;
end
end
endmodule
 
// it produces a ~440Hz triangular signal at full scale for a 50MHz clock
module ramp_a_tone ( input rst, input clk, output reg [15:0] tone );
reg up;
always @(posedge rst or posedge clk) begin
if( rst ) begin
up <= 0;
tone <= 0;
end
else begin
if( tone == 16'hFFFE ) begin
up <= 1'b0;
end
else if( tone == 16'h1 ) begin
up <= 1'b1;
end
tone <= up ? (tone+1'b1) : (tone-1'b1);
end
end
endmodule
/jt51/trunk/contra/fsm_control.v
0,0 → 1,176
`timescale 1ns / 1ps
 
module fsm_control(
input clk,
input clk_cpu,
input rst,
input jt_sample,
// Sound
output reg [ 7:0] sound_latch,
input [15:0] jt_left,
input [15:0] jt_right,
output reg irq,
input clear_irq,
// Program
output reg cpu_rst,
output rom_prog,
output reg rom_wr,
output reg [14:0] rom_addr,
output reg [7:0] rom_data,
// UART wires
input uart_rx,
output uart_tx
);
 
 
// UART control
wire [7:0] uart_rx_data;
reg [7:0] uart_tx_data;
wire uart_received, uart_error;
reg uart_tx_wr;
wire uart_tx_done;
reg [1:0] send_st;
 
parameter TX_IDLE=0, TX_WAIT_LSB=1, TX_WAIT_MSB=2;
 
reg [15:0] left, right, mono;
reg sample;
 
always @(*) { left, right, sample } <= { jt_left, jt_right, jt_sample };
always @(*) mono <= (left+right)>>1;
 
// Send music to computer
reg last_sample;
 
always @(posedge clk or posedge rst) begin
if( rst ) begin
uart_tx_wr <= 1'b0;
send_st <= TX_IDLE;
end
else begin
last_sample <= sample;
case( send_st )
TX_IDLE:
if( sample && !last_sample ) begin
send_st <= TX_WAIT_LSB;
uart_tx_data<= mono[7:0];
uart_tx_wr <= 1'b1;
end
TX_WAIT_LSB: begin
uart_tx_wr <= 1'b0;
if( uart_tx_done ) begin
send_st <= TX_WAIT_MSB;
uart_tx_data<= mono[15:8];
uart_tx_wr <= 1'b1;
end
end
TX_WAIT_MSB: begin
uart_tx_wr <= 1'b0;
if( uart_tx_done )
send_st <= TX_IDLE;
end
endcase
end
end
 
reg set_irq;
 
always @(posedge clk_cpu or posedge rst ) begin
if( rst )
irq <= 1'b0;
else begin
if(set_irq) irq<=1'b1;
else if(clear_irq ) irq<=1'b0;
end
end
 
reg [1:0] irq_s;
reg rom_wr_s, prog_done_s, adv_s;
reg advance, prog_done;
 
assign rom_prog = !prog_done;
 
always @(posedge clk or posedge rst ) begin
if( rst ) begin
// Sound
sound_latch <= 8'h0;
set_irq <= 1'b0;
cpu_rst <= 1'b1;
end
else begin
irq_s <= { irq_s[0], irq };
rom_wr_s <= rom_wr;
prog_done_s <= prog_done;
if( uart_received && !uart_error ) begin
if( prog_done ) begin
sound_latch <= uart_rx_data;
set_irq <= 1'b1;
end
else begin
advance <= 1'b1;
end
end
else begin
cpu_rst <= !prog_done;
if(irq_s[1]) set_irq <= 1'b0;
if(rom_wr_s ) advance <= 1'b0;
end
end
end
 
reg prog_st;
 
parameter WAIT=1, NEXT=0;
 
always @(posedge clk_cpu or posedge rst )
if( rst ) begin
prog_st <= WAIT;
rom_wr <= 1'b0;
prog_done<= 1'b0;
`ifdef FASTSIM
rom_addr<= 15'h7FF0;
`else
rom_addr<= 15'h0;
`endif
end
else begin
adv_s <= advance;
case( prog_st )
NEXT: begin
{ prog_done,rom_addr } <= rom_addr + 1'b1;
rom_wr <= 1'b0;
prog_st <= WAIT;
end
WAIT: if( adv_s ) begin
rom_wr <= 1'b1;
rom_data <= uart_rx_data;
prog_st <= NEXT;
end
endcase
end
 
 
uart_transceiver u_uart(
.sys_rst( rst ),
.sys_clk( clk ),
 
.uart_rx(uart_rx),
.uart_tx(uart_tx),
 
// 461 kbps @ 50MHz
// .clk_divider( 5'd6 ),
// 921.6 kbps @ 50MHz
.clk_divider( 5'd3 ),
.uart_divider( 5'd17 ),
 
.rx_data( uart_rx_data ),
.rx_done( uart_received ),
.rx_error( uart_error ),
.tx_data ( uart_tx_data ),
.tx_wr ( uart_tx_wr ),
.tx_done ( uart_tx_done )
);
 
 
endmodule
/jt51/trunk/contra/readme
0,0 → 1,19
Contra / Double Dragon Sound Boards
-----------------------------------
 
 
This set of files show how to connect the JT51 to a m6809 processor, RAM
memory and ROM memory in order to get sound from two different arcade
video games: Contra and Double Dragon.
 
The files are incomplete as the original video game ROM memories are not
included. The m6809 core is not included but it can be obtained from
opencores.org. Other minor files, like UART and DAC modules are not included
either. The only purpose is to show connectivity in a real scenario and for
that visual inspection of these files should be sufficient.
 
----
29th October, 2016
Jose Tejada
@topapate
jotego at fora: http://www.atari-forum.com/ or http://www.zxuno.com/forum/
/jt51/trunk/contra/ymplayer.v
0,0 → 1,216
`timescale 1ns / 1ps
`timescale 1ns / 1ps
 
module ymplayer(
input clk50,
input rst,
// sound
output speaker_left,
output speaker_right,
// switches
input [1:0] sw_sel, //
input send_data, // 1=Send music over UART, 0=stop
// UART wires
input uart_rx,
output uart_tx,
output [7:0] led
);
 
wire clk_dac, clk, locked, rst_clk, rst_clk50;
 
// Send data
reg [9:0] send_data_shr;
wire send_data_s = &send_data_shr;
 
always @(posedge clk50)
send_data_shr <= { send_data_shr[8:0], send_data };
 
clocks u_clocks(
.rst ( rst ),
.clk50 ( clk50 ),
.locked ( locked ),
.divide_more( send_data_s ),
.clk_cpu( clk ),
.clk_dac( clk_dac )
);
 
// wire clk_per = clk; // cpu09l.vhd
wire clk_per = ~clk; // cpu09new.vhd
wire cpu_rst_req;
 
rst_sync u_rst1(
.rst_in ( rst|(~locked)|cpu_rst_req ),
.clk ( clk ),
.rst_out( rst_clk )
);
/*
rst_sync u_rst2(
.rst_in ( rst_clk ),
.clk ( clk_dac ),
.rst_out( rst_fast )
);
*/
rst_sync u_rst50(
.rst_in ( rst|(~locked) ),
.clk ( clk50 ),
.rst_out( rst_clk50 )
);
 
wire [7:0] cpu_data_in, cpu_data_out;
wire [15:0] cpu_addr;
wire [7:0]jt_data_out;
 
wire cpu_rw;
 
wire signed [15:0] jt_left, jt_right;
 
wire jt_sample;
 
// JT51
`ifndef NOJT
jt51 u_jt51(
.clk ( clk_per ),
.rst ( rst_clk ),
.cs_n ( jt_cs_n ), // chip select
.wr_n ( cpu_rw ), // write
.a0 ( cpu_addr[0] ),
.d_in ( cpu_data_out ), // data in
.d_out ( jt_data_out ), // data out
.irq_n ( jt_irq_n ),
// uso salidas exactas para el DAC
.sample ( jt_sample ),
.xleft ( jt_left ),
.xright ( jt_right )
);
`endif
 
speaker u_speaker(
.clk100 ( clk50 ), // the faster the clock the better !
.left_in ( jt_left ),
.right_in ( jt_right ),
.left_out ( speaker_left ),
.right_out ( speaker_right )
);
 
parameter RAM_MSB = 10; // 10 for Contra;
 
wire [7:0] ROM_data_out, RAM_data;
 
wire fsm_wr;
wire [ 7:0] fsm_data;
wire [14:0] fsm_addr;
wire rom_prog;
 
//synthesis attribute box_type ram32 "black_box"
ram32 ROM( // 32kb
.clka ( clk_per ),
.dina ( fsm_data ),
.ena ( 1'b1 ),
.wea ( fsm_wr ),
.douta ( ROM_data_out ),
.addra ( rom_prog ? fsm_addr : cpu_addr[14:0])
);
 
//synthesis attribute box_type ram2 "black_box"
ram2 RAM( // 2kb
.clka ( clk_per ),
.dina ( cpu_data_out ),
.douta ( RAM_data ),
.addra ( cpu_addr[RAM_MSB:0] ),
.ena ( RAM_cs ),
.wea ( ~cpu_rw )
);
wire [7:0] sound_latch;
wire clear_irq;
 
assign led = rom_prog ? fsm_addr[14:7] : sound_latch;
 
 
fsm_control fsm_ctrl(
.clk ( clk50 ),
.clk_cpu ( clk ),
.rst ( rst_clk50 ),
// Sound
.sound_latch(sound_latch),
.jt_left ( jt_left ),
.jt_right ( jt_right ),
.jt_sample ( jt_sample ),
.irq ( irq ),
.clear_irq ( clear_irq ),
// Programming
.cpu_rst ( cpu_rst_req),
.rom_prog ( rom_prog ),
.rom_wr ( fsm_wr ),
.rom_addr ( fsm_addr ),
.rom_data ( fsm_data ),
// UART wires
.uart_rx ( uart_rx ),
.uart_tx ( uart_tx )
);
 
 
bus_manager #(RAM_MSB) bus_mng(
.rst50 ( rst_clk50 ),
.clk50 ( clk50 ),
.clk_per ( clk_per ),
.sw_sel ( sw_sel ),
.ROM_data_out ( ROM_data_out ),
.RAM_data ( RAM_data ),
.sound_latch ( sound_latch ),
.clear_irq ( clear_irq ),
.cpu_data_out ( cpu_data_out ),
.jt_data_out ( jt_data_out ),
//
.cpu_data_in ( cpu_data_in ),
.cpu_rw ( cpu_rw ),
.addr ( cpu_addr ),
.cpu_vma ( cpu_vma ),
.RAM_cs ( RAM_cs ),
.opm_cs_n ( jt_cs_n )
);
 
wire [15:0] dummy_pcout; // cpu09 debug
 
wire cpu_firq = sw_sel[0] ? ~jt_irq_n : 1'b0;
 
cpu09 cpu(
.clk ( clk ),
.rst ( rst_clk ),
.rw ( cpu_rw ),
.vma ( cpu_vma ),
.address ( cpu_addr ),
.data_in ( cpu_data_in ),
.data_out ( cpu_data_out ),
.halt ( 1'b0 ),
.hold ( 1'b0 ),
.irq ( irq ),
.firq ( cpu_firq ), // for Contra
.nmi ( 1'b0 ),
.pc_out ( dummy_pcout )
);
 
/*
// cpu09l.vhd
cpu09 cpu(
.clk ( clk ),
.rst ( rst_clk ),
.rw ( cpu_rw ),
.vma ( cpu_vma ),
.addr ( cpu_addr ),
.data_in ( cpu_data_in ),
.data_out ( cpu_data_out ),
.halt ( 1'b0 ),
.hold ( 1'b0 ),
.irq ( irq ),
.firq ( 1'b0 ), // for Contra
.nmi ( 1'b0 ),
.lic (),
.ifetch (),
.ba (),
.bs ()
//.pc_out ( pc_out )
);
*/
endmodule
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.