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

Subversion Repositories t6507lp

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 70 to Rev 71
    Reverse comparison

Rev 70 → Rev 71

/t6507lp/trunk/rtl/verilog/t6507lp_fsm_tb.v
46,8 → 46,8
`timescale 1ns / 1ps
 
module t6507lp_fsm_tb();
reg clk_in;
reg rst_in_n;
reg clk;
reg reset_n;
reg [7:0] alu_result;
reg [7:0] alu_status;
reg [7:0] data_in;
61,31 → 61,53
 
`include "../T6507LP_Package.v"
 
t6507lp_fsm #(8,13) my_dut(clk_in, rst_in_n, alu_result, alu_status, data_in, address, control, data_out, alu_opcode, alu_a, alu_enable);
t6507lp_fsm #(8,13) my_dut(clk, reset_n, alu_result, alu_status, data_in, address, control, data_out, alu_opcode, alu_a, alu_enable);
 
always #10 clk_in = ~clk_in;
always #10 clk = ~clk;
 
reg[7:0] fake_mem[20:0];
 
initial begin
clk_in = 0;
data_in = ASL_ACC;
rst_in_n = 1'b0;
alu_result = 0;
clk = 0;
reset_n = 1'b0;
alu_result = 8'h01;
alu_status = 0;
@(negedge clk_in) //will wait for next negative edge of the clock (t=20)
rst_in_n=1'b1;
 
@(negedge clk_in) //will wait for next negative edge of the clock (t=40)
data_in = ROL_ACC;
fake_mem[0] = ASL_ACC; // testing ACC mode
fake_mem[1] = ADC_IMM; // testing IMM mode
fake_mem[2] = 8'h27;
fake_mem[3] = JMP_ABS; // testing ABS mode, JMP type
fake_mem[4] = 8'h09;
fake_mem[5] = 8'h00;
fake_mem[6] = ASL_ACC; // wont be executed
fake_mem[7] = ASL_ACC; // wont be executed
fake_mem[8] = ASL_ACC; // wont be executed
fake_mem[9] = ASL_ACC; // wont be executed
fake_mem[10] = LDA_ABS; // testing ABS mode, READ type. A = MEM[0002]. (a=27)
fake_mem[11] = 8'h02;
fake_mem[12] = 8'h00;
fake_mem[13] = ASL_ABS; // testing ABS mode, READ_MODIFY_WRITE type. should overwrite the first ASL_ACC
fake_mem[14] = 8'h04;
fake_mem[15] = 8'h00;
fake_mem[16] = 8'h00;
 
@(negedge clk_in) //will wait for next negative edge of the clock (t=60)
data_in = ROR_ACC;
@(negedge clk) // will wait for next negative edge of the clock (t=20)
reset_n=1'b1;
 
@(negedge clk_in) //will wait for next negative edge of the clock (t=80)
@(negedge clk_in) //will wait for next negative edge of the clock (t=100)
@(negedge clk_in) //will wait for next negative edge of the clock (t=120)
#500;
$finish; // to shut down the simulation
end //initial
 
always @(clk) begin
if (control == 0) begin // MEM_READ
data_in <= fake_mem[address];
$write("\nreading from mem position %h: %h", address, fake_mem[address]);
end
else if (control == 1'b1) begin // MEM_WRITE
fake_mem[address] <= data_out;
$write("\nreading from mem position %h: %h", address, fake_mem[address]);
end
end
 
endmodule
/t6507lp/trunk/rtl/verilog/t6507lp_fsm.v
48,13 → 48,12
 
`timescale 1ns / 1ps
 
module t6507lp_fsm(clk_in, rst_in_n, alu_result, alu_status, data_in, address, control, data_out, alu_opcode, alu_a, alu_enable);
 
module t6507lp_fsm(clk, reset_n, alu_result, alu_status, data_in, address, control, data_out, alu_opcode, alu_a, alu_enable);
parameter DATA_SIZE = 4'd8;
parameter ADDR_SIZE = 4'd13;
 
input clk_in;
input rst_in_n;
input clk;
input reset_n;
input [DATA_SIZE-1:0] alu_result;
input [DATA_SIZE-1:0] alu_status;
input [DATA_SIZE-1:0] data_in;
72,6 → 71,10
localparam FETCH_OP_CALC = 4'b0001;
localparam FETCH_LOW = 4'b0010;
localparam FETCH_HIGH = 4'b0011;
localparam READ_MEM = 4'b0100;
localparam DUMMY_WRT_CALC = 4'b0101;
localparam WRITE_MEM = 4'b0110;
localparam FETCH_OP_CALC_PARAM = 4'b0111;
 
// OPCODES TODO: verify how this get synthesised
`include "../T6507LP_Package.v"
83,7 → 86,7
reg [ADDR_SIZE-1:0] pc; // program counter
reg [DATA_SIZE-1:0] sp; // stack pointer
reg [DATA_SIZE-1:0] ir; // instruction register
reg [ADDR_SIZE:0] temp_add; // temporary address
reg [ADDR_SIZE:0] temp_addr; // temporary address
reg [DATA_SIZE-1:0] temp_data; // temporary data
 
reg [3:0] state, next_state; // current and next state registers
109,19 → 112,23
wire [ADDR_SIZE-1:0] next_pc;
assign next_pc = pc + 13'b0000000000001;
 
always @ (posedge clk_in or negedge rst_in_n) begin // sequencial always block
if (rst_in_n == 1'b0) begin
// TODO: all internal flip-flops must assume default values
always @ (posedge clk or negedge reset_n) begin // sequencial always block
if (reset_n == 1'b0) begin
// all registers must assume default values
pc <= 0; // TODO: this is written somewhere. something about a reset vector. must be checked.
sp <= 0; // TODO: the default is not 0. maybe $0100 or something like that. must be checked.
ir <= 0;
temp_add <= 0;
temp_addr <= 0;
temp_data <= 0;
state <= RESET;
// registered outputs also receive default values
address <= 0;
control <= 0; // check if these 2 shouldnt be on the other always block along with the address
data_out <= 0;
end
else begin
state <= next_state;
control <= MEM_READ;
case (state)
RESET: begin
130,65 → 137,78
FETCH_OP: begin // this state is the simplest one. it is a simple fetch that must be done when the cpu was reset or
// the last cycle was a memory write.
pc <= next_pc;
address <= next_pc;
ir <= data_in;
end
FETCH_OP_CALC: begin // this is the pipeline happening!
FETCH_OP_CALC, FETCH_OP_CALC_PARAM: begin // this is the pipeline happening!
pc <= next_pc;
address <= next_pc;
ir <= data_in;
end
FETCH_LOW: begin // in this state the opcode is already known so truly execution begins
if (accumulator || implied) begin
pc <= pc; // is this better?
address <= pc;
end
else if (immediate) begin
pc <= next_pc;
address <= next_pc;
temp_data <= data_in; // the follow-up byte is saved in temp_data
end
else if (absolute) begin
pc <= next_pc;
address <= next_pc;
temp_addr[7:0] <= data_in;
end
end
default: begin
$write("unknown state"); // TODO: check if synth really ignores this 2 lines. Otherwise wrap it with a `ifdef
$finish(0);
FETCH_HIGH: begin
if (jump) begin
pc <= {data_in[4:0], temp_addr}; // PCL <= first byte, PCH <= second byte
address <= {data_in[4:0], temp_addr};
end
else begin
if (write) begin
pc <= next_pc;
temp_addr[12:8] <= data_in[4:0];
address <= {data_in[4:0],temp_addr[7:0]};
control <= MEM_WRITE;
end
else begin // read_modify_write or just read
pc <= next_pc;
temp_addr[12:8] <= data_in[4:0];
address <= {data_in[4:0],temp_addr[7:0]};
end
end
//else begin
// $write("FETCHHIGH PROBLEM");
// $finish(0);
//end
end
endcase
end
end
 
always @ (posedge clk_in or negedge rst_in_n) begin
if (rst_in_n == 1'b0) begin
// TODO: all outputs must assume default values
address <= 0;
control <= 0; // one bit is enough? read = 0, write = 1
data_out <= 0;
alu_opcode <= 0;
alu_a <= 0;
alu_enable <= 0;
end
else begin
 
address <= pc;
case (state)
RESET: begin
// The processor was reset. No output whatsoever.
READ_MEM: begin
if (read_modify_write) begin
pc <= pc;
address <= temp_addr;
control <= MEM_WRITE;
temp_data <= data_in;
data_out <= data_in; // writeback the same value
end
else begin
pc <= pc;
address <= pc;
temp_data <= data_in;
end
end
FETCH_OP: begin
// it is a simple fetch. no output change.
DUMMY_WRT_CALC: begin
pc <= pc;
address <= temp_addr;
control <= MEM_WRITE;
data_out <= alu_result;
end
FETCH_OP_CALC: begin // this is the pipeline happening!
alu_opcode <= ir;
alu_a <= temp_data;
alu_enable <= 1'b1;
WRITE_MEM: begin
pc <= pc;
address <= pc;
data_out = 8'hzz;
end
FETCH_LOW: begin // in this state the opcode is already known so truly execution begins
if (accumulator || implied) begin
alu_opcode <= ir;
alu_enable <= 1'b1;
end
else begin // nothing?
end
end
default: begin
$write("unknown state"); // TODO: check if synth really ignores this 2 lines. Otherwise wrap it with a `ifdef
$finish(0);
196,50 → 216,92
endcase
end
 
end
 
always @ (*) begin // this is the next_state logic always block
//address = pc;
always @ (*) begin // this is the next_state logic and the output logic always block
//control = MEM_READ;
//data_out = 8'h00;
//alu_opcode = 8'h00;
//alu_a = 8'h00;
//alu_enable = 1'b0;
alu_opcode = 8'h00;
alu_a = 8'h00;
alu_enable = 1'b0;
//address = pc;
 
next_state = RESET; // this prevents the latch
next_state = RESET; // this prevents the latch
 
begin
case (state)
RESET: begin
case (state)
RESET: begin
next_state = FETCH_OP;
end
FETCH_OP: begin
next_state = FETCH_LOW;
//address = pc;
end
FETCH_OP_CALC: begin
next_state = FETCH_LOW;
alu_opcode = ir;
alu_enable = 1'b1;
//address = next_pc;
 
end
FETCH_OP_CALC_PARAM: begin
next_state = FETCH_LOW;
alu_opcode = ir;
alu_enable = 1'b1;
alu_a = temp_data;
//address = next_pc;
end
FETCH_LOW: begin
if (accumulator || implied) begin
alu_opcode = ir;
alu_enable = 1'b1;
next_state = FETCH_OP;
end
else if (immediate) begin
next_state = FETCH_OP_CALC_PARAM;
end
else begin // at least the absolute address mode falls here
next_state = FETCH_HIGH;
end
//address = next_pc;
 
end
FETCH_HIGH: begin
if (jump) begin
next_state = FETCH_OP;
end
FETCH_OP: begin
next_state = FETCH_LOW;
else if (read || read_modify_write) begin
next_state = READ_MEM;
end
FETCH_OP_CALC: begin
next_state = FETCH_LOW;
//alu_opcode = ir;
//alu_enable = 1'b1;
else if (write) begin
next_state = WRITE_MEM;
end
FETCH_LOW: begin
if (accumulator || implied) begin
//alu_opcode = data_in;
//alu_enable = 1'b1;
next_state = FETCH_OP;
end
else if (immediate) begin
next_state = FETCH_OP_CALC;
end
else begin // at least the immediate address mode falls here
next_state = FETCH_HIGH;
end
else begin
$write("unknown behavior");
$finish(0);
end
default: begin
next_state = RESET;
end
READ_MEM: begin
if (read) begin
next_state = FETCH_OP_CALC_PARAM;
end
endcase
end
else if (read_modify_write) begin
next_state = DUMMY_WRT_CALC;
end
end
DUMMY_WRT_CALC: begin
alu_opcode = ir;
alu_enable = 1'b1;
alu_a = data_in;
next_state = WRITE_MEM;
end
WRITE_MEM: begin
next_state = FETCH_OP;
end
default: begin
next_state = RESET;
end
endcase
end
 
// this always block is responsible for updating the address mode
293,34 → 355,29
ORA_IDY, SBC_IDY, STA_IDY: begin // all these opcodes are 8'hX1; TODO: optimize this
indirect = 1'b1;
end
default: begin
$write("unknown OPCODE!");
$finish();
end
endcase
case (ir)
ASL_ACC, ASL_ZPG, ASL_ZPX, ASL_ABS, ASL_ABX, LSR_ACC, LSR_ZPG, LSR_ZPX, LSR_ABS, LSR_ABX, ROL_ACC, ROL_ZPG, ROL_ZPX, ROL_ABS,
ROL_ABX, ROR_ACC, ROR_ZPG, ROR_ZPX, ROR_ABS, ROR_ABX, INC_ZPG, INC_ZPX, INC_ABS, INC_ABX, DEC_ZPG, DEC_ZPX, DEC_ABS,
DEC_ABX: begin
read_modify_write = 1'b1;
end
STA_ZPG, STA_ZPX, STA_ABS, STA_ABX, STA_ABY, STA_IDX, STA_IDY, STX_ZPG, STX_ZPY, STX_ABS, STY_ZPG, STY_ZPX, STY_ABS: begin
write = 1'b1;
end
default: begin // this should work fine since the previous case statement will detect the unknown/undocumented/unsupported opcodes
read = 1'b1;
end
endcase
if (data_in == JMP_ABS || data_in == JMP_IND) begin // the opcodes are 8'h4C and 8'h6C
if (ir == JMP_ABS || ir == JMP_IND) begin // the opcodes are 8'h4C and 8'h6C
jump = 1'b1;
end
 
// if (data_in == )
/*LDA_IMM = 8'hA9,
LDA_ZPG = 8'hA5,
LDA_ZPX = 8'hB5,
LDA_ABS = 8'hAD,
LDA_ABX = 8'hBD,
LDA_ABY = 8'hB9,
LDA_IDX = 8'hA1,
LDA_IDY = 8'hB1;
LDX_IMM = 8'hA2,
LDX_ZPG = 8'hA6,
LDX_ZPY = 8'hB6,
LDX_ABS = 8'hAE,
LDX_ABY = 8'hBE;
LDY_IMM = 8'hA0,
LDY_ZPG = 8'hA4,
LDY_ZPX = 8'hB4,
LDY_ABS = 8'hAC,
LDY_ABX = 8'hBC;
*/
 
end // no way
endmodule
 

powered by: WebSVN 2.1.0

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