Arlet, yeah, the clocking is a little weird. I updated the clocking code to more closely model how the 6502 generates its clock. From what I remember in the documentation it pushes the edges of the two clocks away from each other; far enough that it satisfies setup and hold times.
When I synthesize I'll try to setup a PLL or two to correctly generate the dual-clock.
Thank you for commenting on that!
After a bit more muscle work I've extracted the necessary bits for running the AB, ADL, and PCL. So the chip can now manage its own PC and set its AB correctly. The other tcstates are also simulated correctly now.
Code:
`timescale 1ns/1ns
module mos_6502(clk, ab, bi_data);
input clk;
inout [7:0] bi_data;
output reg [15:0] ab = 16'h0000;
reg [7:0] pd = 8'h00;
reg [7:0] ir = 8'h00;
reg [5:0] tcstate = 6'b111111;
reg [7:0] pcl = 8'h00, pch = 8'h00;
reg ADL_ABL = 1'b1; // Load ADL into Address Bus Register Low
reg I_PC = 1'b0; // Increment Program Counter
reg ADD_ADL = 1'b1, PCL_ADL = 1'b0, S_ADL = 1'b0, DL_ADL = 1'b0; // Flags that select the source for Address Data Low
reg [7:0] DL = 8'h00, S = 8'h00, ADD = 8'h00;
wire [7:0] ADL = S_ADL ? S : (PCL_ADL ? pcl : (DL_ADL ? DL : (ADD_ADL ? ADD : 8'h00)));
// Status Register
reg p0 = 1'b0, p1 = 1'b1, p2 = 1'b1, p3 = 1'b0, p4 = 1'b1, p6 = 1'b0, p7 = 1'b0;
wire clock1 = tcstate[0], clock2 = tcstate[1];
// cclk domain
reg pipeUNK11 = 1'b0, pipeUNK23 = 1'b0, pipeUNK35 = 1'b0, pipeUNK40 = 1'b0, pipeUNK41 = 1'b1, pipe_T0 = 1'b0, pipeBRtaken_v = 1'b0;
// cp1 domain
reg n_24_v = 1'b1, n_653_v = 1'b0, n_666_v = 1'b0;
reg cclk, cp1, shifted_clk;
always #100 shifted_clk = clk;
always @ (posedge shifted_clk) cclk <= 1'b1;
always @ (negedge clk) cclk <= 1'b0;
always @ (negedge shifted_clk) cp1 <= 1'b1;
always @ (posedge clk) cp1 <= 1'b0;
/////////////////////////////////////////////////////////////////
// Pre-Decoder
wire fetch_v = pipeUNK11;
wire clearIR = !fetch_v;
wire [7:0] pd_clearIR = clearIR ? 8'd0 : pd;
wire PD_xxxx10x0_v = !(pd_clearIR[0] | !pd_clearIR[3] | pd_clearIR[2]);
wire PD_1xx000x0_v = !(!pd_clearIR[7] | pd_clearIR[0] | pd_clearIR[3] | pd_clearIR[4] | pd_clearIR[2]);
wire PD_0xx0xx0x_v = !(pd_clearIR[7] | pd_clearIR[4] | pd_clearIR[1]);
wire PD_xxx010x1_v = !(!pd_clearIR[3] | pd_clearIR[4] | !pd_clearIR[0] | pd_clearIR[2]);
wire PD_n_0xx0xx0x_v = !PD_0xx0xx0x_v;
wire TWOCYCLE = (PD_n_0xx0xx0x_v & PD_xxxx10x0_v) | (PD_1xx000x0_v | PD_xxx010x1_v);
/////////////////////////////////////////////////////////////////
// PLA
// TODO: This should be a module that takes the appropriate inputs and
// gives a large 130 bit output. We can then write an include that
// assigns named wires to the bit array.
`include "pla_decode.v"
assign n_256_v = ~((op_T5_ind_x_v|op_T0_brk_rti_v|op_T0_jmp_v|op_T5_rts_v|op_T4_v|op_T5_rti_v|op_T3_v));
assign n_347_v = ~((op_T2_mem_zp_v|op_T3_mem_zp_idx_v|op_T3_mem_abs_v|op_T4_mem_abs_idx_v|op_T5_mem_ind_idx_v));
assign n_790_v = ~((op_asl_rol_v|op_lsr_ror_dec_inc_v));
assign n_368_v = ~((x_op_T3_plp_pla_v|op_T2_jmp_abs_v|op_T4_jmp_v|op_T5_rti_rts_v|xx_op_T5_jsr_v|op_T2_php_pha_v));
wire n_1716_v = ~(op_T3_branch_v | n_653_v | !n_368_v);
wire n_1286_v = ~(op_brk_rti_v | x_op_jmp_v | op_jsr_v | clock1);
wire n_1211_v = ~(op_T5_jsr_v | op_T2_branch_v | n_1286_v | !n_666_v | op_T2_abs_access_v);
wire n_182_v = clock1 & !op_T5_rts_v & n_1211_v;
wire n_1619_v = !(op_T2_branch_v | n_182_v);
wire n_620_v = (_op_branch_bit7_v | _op_branch_bit6_v | !p1) & (!p0 | !_op_branch_bit6_v | _op_branch_bit7_v);
wire BRtaken_v = (ir[5] | !(_op_branch_bit7_v | _op_branch_bit6_v | !p1) ) & (!ir[5] | n_620_v);
always @ (posedge cclk)
begin
pipeUNK11 <= !n_666_v;
pipeUNK23 <= clock1;
pipeUNK35 <= n_1716_v & clock1;
pipeUNK40 <= !(n_790_v | n_347_v);
pipeUNK41 <= n_24_v;
pipe_T0 <= clock1;
pipeBRtaken_v <= !(n_1619_v | (BRtaken_v & op_T2_branch_v));
pd <= bi_data;
// Bus Control Signals
ADL_ABL <= !n_653_v & n_24_v;
ADD_ADL <= !n_256_v;
PCL_ADL <= op_T5_jsr_v | op_T2_branch_v | op_T2_abs_access_v | ( !( op_brk_rti_v | x_op_jmp_v | op_jsr_v ) & !clock1 ) | !n_666_v;
S_ADL <= op_T2_stack_v | op_T0_jsr_v;
DL_ADL <= op_T2_ind_v | op_T2_zp_zp_idx_v;
end
always @ (posedge cp1)
begin
n_24_v <= !pipeUNK40;
n_653_v <= !pipeUNK41;
n_666_v <= pipeUNK23;
if(ADL_ABL)
ab[7:0] <= ADL;
// Increment PC?
I_PC <= pipeBRtaken_v | PD_xxxx10x0_v;
if(!I_PC)
{pch, pcl} <= {pch, pcl} + 16'd1;
if(fetch_v)
ir <= pd_clearIR;
// Timing Control
tcstate[0] <= (pipeUNK35 & !TWOCYCLE) | !pipe_T0;
tcstate[1] <= pipe_T0;
tcstate[2] <= tcstate[1];
if(!tcstate[0])
tcstate[5:3] <= 3'b111;
else
tcstate[5:3] <= tcstate[4:2];
end
endmodule
My short-term goal is to get the visual6502 example program working. To that end I'll start the arduous task of bashing my now swollen head into the keyboard until verilog code eventually falls out of it.
Or just get DL, AC, and the associated control signals working ...