1
0
mirror of https://github.com/mist-devel/mist-board.git synced 2026-02-04 07:13:01 +00:00

[BBC] Planetoid, Snapper fixed, and other m6522 improvements. Clocks improvements.

This commit is contained in:
Squid
2017-02-26 11:17:27 +00:00
parent 5cd8f9ceb0
commit d8ed5ec585
3 changed files with 124 additions and 87 deletions

View File

@@ -88,6 +88,7 @@ wire io_fred;
wire io_jim;
wire io_sheila;
// SHEILA
wire crtc_enable;
wire acia_enable;
wire serproc_enable;
@@ -645,6 +646,11 @@ assign sound_di = sys_via_pa_out;
// Others (idle until missing bits implemented)
assign sys_via_pb_in[7:4] = { 2'b11, !joy_but[1], !joy_but[0] };
assign sys_via_pb_in[3:0] = sys_via_pb_out[3:0];
// Fixes Planetoid, Snapper etc
assign user_via_pa_in = user_via_pa_out;
assign user_via_pb_in = user_via_pb_out;
assign MEM_ADR = cpu_a[15:0];

103
cores/bbc/rtl/clocks.v Normal file → Executable file
View File

@@ -1,5 +1,5 @@
`timescale 1ns / 1ps
/*
`timescale 1ns / 1ps
/*
Copyright (c) 2012, Stephen J Leary
All rights reserved.
@@ -24,35 +24,35 @@ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
*/
module clocks(
input clk_32m,
input clk_32m,
input clk_24m,
input reset_n,
input reset_n,
input mhz1_enable,
output wire mhz4_clken,
output wire mhz2_clken,
output wire mhz4_clken,
output wire mhz2_clken,
output wire mhz1_clken,
output wire cpu_cycle,
output wire cpu_cycle,
output wire cpu_clken,
output wire vid_clken,
output wire ttxt_clken,
output wire vid_clken,
output wire ttxt_clken,
output wire ttxt_clkenx2,
output wire tube_clken
);
output wire tube_clken
);
reg [4:0] clken_counter;
reg cpu_cycle_mask;
// SAA5050 needs a 6 MHz clock enable relative to a 24 MHz clock
reg [1:0] ttxt_clken_counter;
reg [1:0] cpu_cycle_mask;
// SAA5050 needs a 6 MHz clock enable relative to a 24 MHz clock
reg [1:0] ttxt_clken_counter;
// Clock enable generation - 32 MHz clock split into 32 cycles^M
// CPU is on 0 and 16 (but can be masked by 1 MHz bus accesses)^M
// Video is on all odd cycles (16 MHz)^M
@@ -61,16 +61,16 @@ assign vid_clken = clken_counter[0]; // & ~vsync_latch & ~hsync_latch;
// 1,3,5...^M
assign mhz4_clken = clken_counter[0] & clken_counter[1] & clken_counter[2];
// 7/15/23/31^M
assign mhz2_clken = mhz4_clken & clken_counter[3];
// 1/17
assign mhz2_clken = mhz4_clken & clken_counter[3];
// 1/17
assign tube_clken = clken_counter[0] & !clken_counter[1] & !clken_counter[2];
// 15/31^M
assign mhz1_clken = mhz2_clken & clken_counter[4];
// 31^M
assign cpu_cycle = ~(clken_counter[0] | clken_counter[1] | clken_counter[2] | clken_counter[3]);
// 0/16^M
assign cpu_clken = /* reset_n && */ cpu_cycle & ~cpu_cycle_mask;
assign cpu_clken = cpu_cycle & ~cpu_cycle_mask[1] & ~cpu_cycle_mask[0];
always @(posedge clk_32m)
begin : clk_gen
// if (reset_n === 1'b 0)
@@ -81,43 +81,40 @@ always @(posedge clk_32m)
// begin
clken_counter <= clken_counter + 5'd1;
// end
end
end
always @(posedge clk_32m)
begin : cycle_stretch
if (reset_n === 1'b 0)
begin
cpu_cycle_mask <= 1'b 0;
end
else if (mhz2_clken === 1'b 1 )
begin
if ((mhz1_enable === 1'b 1) && (cpu_cycle_mask === 1'b 0))
begin
// Block CPU cycles until 1 MHz cycle has completed
cpu_cycle_mask <= 1'b 1;
end
if (mhz1_clken === 1'b 1)
begin
// CPU can run again
// FIXME: This may not be correct in terms of CPU cycles, but it
// should work
cpu_cycle_mask <= 1'b 0;
end
if (reset_n === 1'b 0) begin
cpu_cycle_mask <= 2'b 00;
end
else if (mhz2_clken === 1'b 1 ) begin
if ((mhz1_enable === 1'b 1) && (cpu_cycle_mask === 2'b 00)) begin
// Block CPU cycles until 1 MHz cycle has completed
if (mhz1_clken === 1'b 0) begin
cpu_cycle_mask <= 2'b 01;
end else begin
cpu_cycle_mask <= 2'b 10;
end
end
if (cpu_cycle_mask !== 2'b 00) begin
cpu_cycle_mask <= cpu_cycle_mask - 2'b 01;
end
end
end
always @(posedge clk_24m)
begin : ttxt_clk_gen
if (reset_n === 1'b 0) begin
ttxt_clken_counter <= {2{1'b 0}};
end else begin
end else begin
ttxt_clken_counter <= ttxt_clken_counter + 1;
end
end
end
// 6 MHz clock enable for SAA5050
assign ttxt_clken = ttxt_clken_counter === 0 ? 1'b 1 : 1'b 0;
assign ttxt_clkenx2 = !ttxt_clken_counter[0];
endmodule
assign ttxt_clken = ttxt_clken_counter === 0 ? 1'b 1 : 1'b 0;
assign ttxt_clkenx2 = !ttxt_clken_counter[0];
endmodule

View File

@@ -40,6 +40,9 @@
//
// Revision list
//
// version 004 fixes to PB7 T1 control and Mode 0 Shift Register operation
// version 003 fix reset of T1/T2 IFR flags if T1/T2 is reload via reg5/reg9 from wolfgang (WoS)
// Ported to numeric_std and simulation fix for signal initializations from arnim laeuger
// version 002 fix from Mark McDougall, untested
// version 001 initial release
// not very sure about the shift register, documentation is a bit light.
@@ -114,7 +117,7 @@ wire O_CB1;
wire O_CB1_OE_L;
reg O_CB2;
reg O_CB2_OE_L;
reg [1:0] phase;
reg [1:0] phase = 2'b00;
reg p2_h_t1;
wire cs;
@@ -145,24 +148,24 @@ reg [7:0] load_data;
// timer 1
reg [15:0] t1c;
reg t1c_active;
wire t1c_done;
reg t1c_done;
reg t1_w_reset_int;
reg t1_r_reset_int;
reg t1_load_counter;
wire t1_reload_counter;
reg t1_reload_counter;
reg t1_toggle;
reg t1_irq;
// timer 2
reg [15:0] t2c;
reg t2c_active;
wire t2c_done;
reg t2c_done;
reg t2_pb6;
reg t2_pb6_t1;
reg t2_w_reset_int;
reg t2_r_reset_int;
reg t2_load_counter;
wire t2_reload_counter;
reg t2_reload_counter;
reg t2_irq;
reg t2_sr_ena;
@@ -202,8 +205,6 @@ wire cb2_int;
reg ca2_irq;
reg cb2_irq;
reg final_irq;
wire p_timer1_done_done;
wire p_timer2_done_done;
reg p_timer2_ena;
reg p_sr_dir_out;
reg p_sr_ena;
@@ -328,6 +329,7 @@ always @(posedge CLK) begin
end
if (r_acr[7] === 1'b1) begin
// DMB: Forgetting to clear B7 broke Acornsoft Planetoid
if(t1_load_counter)
r_orb[7] <= 1'b0; // writing T1C-H resets bit 7
else if (t1_toggle === 1'b1)
@@ -340,8 +342,12 @@ end
always @(posedge CLK) begin
//Fix incorrect power up values in timer latches
if (RESET_L === 1'b 0) begin
// The spec says, this is not reset.
// Fact is that the 1541 VIA1 timer won't work,
// as the firmware ONLY sets the r_t1l_h latch!!!!
// DMB: These are observed power on values from the Beeb
// DMB: Note, it's a little overzeleaous setting these on reset; that doesn't happen in reality
r_t1l_l <= 8'h FE;
r_t1l_h <= 8'h FF;
r_t2l_l <= 8'h FE;
@@ -419,20 +425,21 @@ assign O_DATA_OE_L = (cs === 1'b 1 & I_RW_L === 1'b 1) ? 1'b0 : 1'b1;
always @(posedge CLK) begin
if (ENA_4 === 1'b 1) begin
if (ENA_4 === 1'b 1) begin
t1_r_reset_int <= 1'b0;
t2_r_reset_int <= 1'b0;
sr_read_ena <= 1'b0;
r_irb_hs <= 1'b 0;
r_ira_hs <= 1'b 0;
O_DATA <= 8'h 00; // default
if (cs === 1'b 1 & I_RW_L === 1'b 1) begin
case (I_RS)
4'h 0: begin
O_DATA <= r_irb & ~r_ddrb | r_orb & r_ddrb;
// when x"0" => O_DATA <= r_irb; r_irb_hs <= '1';
// fix from Mark McDougall, untested
4'h 0: begin
O_DATA <= r_irb & ~r_ddrb | r_orb & r_ddrb;
r_irb_hs <= 1'b 1;
end
@@ -505,7 +512,7 @@ always @(posedge CLK) begin
endcase
end
end
end
end
//
@@ -781,10 +788,11 @@ always @(posedge CLK) begin
end
end
// data direction reg (ddr) 0 = input, 1 = output
assign O_PA = r_ora;
assign O_PA_OE_L = ~r_ddra;
assign O_PB_OE_L[6:0] = ~r_ddrb[6:0];
// not clear if r_ddrb(7) must be 1 as well, an output if under t1 control
assign O_PB_OE_L[7] = (r_acr[7] === 1'b 1) ? 1'b 0 : ~r_ddrb[7];
@@ -795,11 +803,21 @@ assign O_PB[7:0] = r_orb[7:0];
// Timer 1
//
// data direction reg (ddr) 0 = input, 1 = output
reg p_timer1_done_done;
always @(posedge CLK) begin
if (ENA_4 === 1'b1) begin
p_timer1_done_done = t1c == 16'h 0000;
t1c_done <= p_timer1_done_done & phase == 2'b 11;
if (phase === 2'b 11) begin
t1_reload_counter <= p_timer1_done_done & r_acr[6] == 1'b1;
end
if (t1_load_counter ) begin
t1c_done <= 1'b0;
end
end
end
assign p_timer1_done_done = t1c == 16'h 0000;
assign t1c_done = p_timer1_done_done & phase == 2'b 11;
assign t1_reload_counter = p_timer1_done_done & r_acr[6] == 1'b 1;
always @(posedge CLK) begin
@@ -819,18 +837,17 @@ always @(posedge CLK) begin
t1c_active <= 1'b0;
end
if (RESET_L === 1'b 0) begin
t1c_active <= 1'b0;
end
t1_toggle <= 1'b 0;
if (t1c_active & t1c_done) begin
t1_toggle <= 1'b 1;
t1_irq <= 1'b 1;
end
else if (RESET_L === 1'b 0 | t1_w_reset_int | t1_r_reset_int |
clear_irq[6] === 1'b 1 ) begin
else if (t1_w_reset_int | t1_r_reset_int | clear_irq[6] === 1'b 1 ) begin
t1_irq <= 1'b 0;
end
if (t1_load_counter) begin // irq reset on load!
t1_irq <= 1'b 0;
end
end
@@ -852,9 +869,20 @@ always @(posedge CLK) begin
end
end
assign p_timer2_done_done = t2c == 16'h 0000;
assign t2c_done = p_timer2_done_done & phase == 2'b 11;
assign t2_reload_counter = p_timer2_done_done;
reg p_timer2_done_done;
always @(posedge CLK) begin
if (ENA_4 === 1'b1) begin
p_timer2_done_done = t2c == 16'h 0000;
t2c_done <= p_timer2_done_done & phase == 2'b 11;
if (phase === 2'b 11) begin
t2_reload_counter <= p_timer2_done_done;
end
if (t2_load_counter ) begin // done reset on load!
t2c_done <= 1'b0;
end
end
end
always @(posedge CLK) begin
@@ -893,17 +921,17 @@ always @(posedge CLK) begin
t2c_active <= 1'b0;
end
if (RESET_L === 1'b 0) begin
t2c_active <= 1'b0;
end
if (t2c_active & t2c_done) begin
t2_irq <= 1'b 1;
end
else if (RESET_L === 1'b 0 | t2_w_reset_int | t2_r_reset_int |
clear_irq[5] === 1'b 1 ) begin
else if (t2_w_reset_int | t2_r_reset_int | clear_irq[5] === 1'b 1 ) begin
t2_irq <= 1'b 0;
end
if (t2_load_counter) begin // irq reset on load!
t2_irq <= 1'b 0;
end
end
end
@@ -1011,7 +1039,10 @@ always @(posedge CLK) begin
// input
if (sr_cnt[3] === 1'b 1 | p_sr_cb1_ip === 1'b 1) begin
if (sr_strobe_rising) begin
r_sr <= {r_sr[6:0], I_CB2};
r_sr[0] <= I_CB2;
end
else if (sr_strobe_falling) begin
r_sr[7:1] <= r_sr[6:0];
end
end
@@ -1036,7 +1067,10 @@ always @(posedge CLK) begin
p_sr_sr_count_ena = sr_strobe_rising;
if (sr_write_ena | sr_read_ena) begin
// DMB: reseting sr_count when not enabled cause the sr to
// start running immediately it was enabled, which is incorrect
// and broke the latest SmartSPI ROM on the BBC Micro
if (p_sr_ena & (sr_write_ena | sr_read_ena)) begin
// some documentation says sr bit in IFR must be set as well ?
sr_cnt <= 4'b 1000;