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 |
|