View Single Post
Old 01 July 2014, 01:01   #128
FrenchShark
FPGAmiga rulez!
FrenchShark's Avatar
 
Join Date: Dec 2007
Location: South of France
Age: 44
Posts: 155
Quote:
Originally Posted by pandy71 View Post
Hardware proven?



So... perhaps You can share details about internal Paula architecture?
There is some limited amount of information about DPLL (USPTO 4,780,844) and overall Paula architecture (USPTO 4,829,473) - but probably there is lot more than this.
This is really no big deal.
I have done it myself. I am sure Mike had no problem implementing that part.
Here is the DPLL verilog code :-)
Read has been tested. Write, not yet.

// This module is based on :
//
// Patent #4,780,844 from Commodore-Amiga Inc.
// DATA INPUT CIRCUIT WITH DIGITAL PHASE LOCKED LOOP

module mfm_dpll
(
input rst, // Global reset
input clk, // Ref. 21, 85 MHz clock
input clk_ena, // Ref. 21, 100 for HD, 100000 for DD, 100000000000 for SD
input dsk_rd_n, // Ref. 11, disk read port
output [15:0] buf_rd, // Ref. 15, read shift register
output buf_rdy, // Data buffer ready
input start, // DMA start strobe
input dma_on, // DMA active flag
input wr_mode, // Ref. 23, read (0), write (1)
input sync_arm, // MFM synchronization armed
input sync_ena, // MFM synchronization enabled
input [15:0] sync_word, // MFM synchronization word value
output sync_det // MFM synchronization detected
);

// ================================
// == Falling edge detector (71) ==
// ================================

reg [2:0] r_dsk_rd_cc; // Ref. 71
wire w_dsk_rd_edge; // Ref. 93

always@(posedge rst or posedge clk) begin
if (rst)
r_dsk_rd_cc <= 3'b111;
else if (clk_ena) begin
if (sync_arm | ~wr_mode)
r_dsk_rd_cc <= { r_dsk_rd_cc[1:0], dsk_rd_n };
end
end
assign w_dsk_rd_edge = r_dsk_rd_cc[2] & ~r_dsk_rd_cc[1];

// ================================
// == MFM/GCR bit flip-flop (81) ==
// == 16-bit shift register (15) ==
// ================================

reg r_bit_ff; // Ref. 81
reg [15:0] r_buf_rd; // Ref. 15

always@(posedge rst or posedge clk) begin
if (rst) begin
r_bit_ff <= 1'b0;
r_buf_rd <= 16'h0000;
end else if (clk_ena) begin
if (w_dsk_rd_edge)
r_bit_ff <= 1'b1;
else if (w_roll_over)
r_bit_ff <= 1'b0;
if (w_roll_over)
r_buf_rd <= { r_buf_rd[14:0], r_bit_ff };
end
end
assign buf_rd = r_buf_rd;

// ==============================
// == MFM synchronization word ==
// == MFM word alignment ==
// ==============================

reg r_sync_equ;
reg r_sync_det;
reg [3:0] r_bit_ctr;
reg r_buf_rdy;

always@(posedge rst or posedge clk) begin
if (rst) begin
r_sync_equ <= 1'b0;
r_sync_det <= 1'b0;
r_bit_ctr <= 4'd0;
r_buf_rdy <= 1'b0;
end else if (clk_ena) begin
// MFM synchronization
r_sync_equ <= ({ r_buf_rd[14:0], r_bit_ff } == sync_word) ? 1'b1 : 1'b0;
if (w_roll_over) r_sync_det <= r_sync_equ;
// MFM word alignment
if ((w_roll_over & r_sync_equ & sync_ena) | start)
r_bit_ctr <= 4'd0;
else if (w_roll_over)
r_bit_ctr <= r_bit_ctr + 4'd1;
if (((&r_bit_ctr & ~sync_arm) | (r_sync_equ & sync_ena)) & w_roll_over)
r_buf_rdy <= r_buf_rdy ^ dma_on;
end
end
assign sync_det = r_sync_det;
assign buf_rdy = r_buf_rdy;

// ==================================
// == Window history register (91) ==
// ==================================

reg [1:0] r_msb_hist; // Ref. 91

always@(posedge rst or posedge clk) begin
if (rst)
r_msb_hist <= 2'b00;
else if (w_dsk_rd_edge & clk_ena)
r_msb_hist <= { r_msb_hist[0], r_ph_adder[11] };
end

// ================================
// == 8-bit up/down counter (25) ==
// ================================

`define CTR_MAX_VAL 8'd159
`define CTR_AVG_VAL 8'd146
`define CTR_MIN_VAL 8'd133

reg [7:0] r_up_dn_ctr; // Ref. 25

always@(posedge rst or posedge clk) begin
if (rst)
r_up_dn_ctr <= `CTR_AVG_VAL;
else if (clk_ena) begin
if (start)
r_up_dn_ctr <= `CTR_AVG_VAL;
else if ((r_cnt_up) && (r_up_dn_ctr != `CTR_MAX_VAL))
r_up_dn_ctr <= r_up_dn_ctr + 8'd1;
else if ((r_cnt_dn) && (r_up_dn_ctr != `CTR_MIN_VAL))
r_up_dn_ctr <= r_up_dn_ctr - 8'd1;
end
end

// ==================================
// == Added value multiplexer (41) ==
// ==================================

`define ADD_LO_VAL 9'd34
`define ADD_HI_VAL 9'd258

wire [8:0] w_ctr_val;
wire [8:0] w_add_val; // Ref. 41

assign w_ctr_val = (r_add_four)
? ({1'b0, r_up_dn_ctr} + 9'd4) // Write mode add four
: {1'b0, r_up_dn_ctr}; // Normal mode

assign w_add_val = ({9{r_sel_low}} & `ADD_LO_VAL) // Negative phase correction
| ({9{r_sel_ctr}} & w_ctr_val) // No phase correction
| ({9{r_sel_high}} & `ADD_HI_VAL); // Positive phase correction

// =============================
// == 12-bit phase adder (43) ==
// =============================

reg [11:0] r_ph_adder; // Ref. 43

always@(posedge rst or posedge clk) begin
if (rst)
r_ph_adder <= 12'd0;
else if (clk_ena) begin
if (start)
r_ph_adder <= 12'd0;
else
r_ph_adder <= r_ph_adder + { 3'b000, w_add_val };
end
end

// ==========================
// == Adder roll-over (79) ==
// ==========================

reg r_msb_dly; // Ref. 79
wire w_roll_over; // Ref. 83

always@(posedge rst or posedge clk) begin
if (rst)
r_msb_dly <= 1'b0;
else if (clk_ena)
// Set when 111, cleared otherwise
r_msb_dly <= &r_ph_adder[11:9];
end
// 111 -> 000 : roll-over detection
assign w_roll_over = r_msb_dly & ~(&r_ph_adder[11:9]);

// ===============================
// == Add four instruction (89) ==
// ===============================

reg r_add_four; // Ref. 89

always@(posedge rst or posedge clk) begin
if (rst)
r_add_four <= 1'b0;
else if (clk_ena)
// Add 4 every 14 cycles during write mode
r_add_four <= (&r_ph_adder[10:8]) & wr_mode & ~sync_arm;
end

// ==============================
// == Freq. error decoder (73) ==
// ==============================

reg [3:0] r_freq_err; // Ref. 99
reg r_cnt_up; // Ref. 27
reg r_cnt_dn; // Ref. 29

always@(posedge rst or posedge clk) begin
if (rst) begin
r_freq_err <= 4'd0;
r_cnt_up <= 1'b0;
r_cnt_dn <= 1'b0;
end else if (clk_ena) begin
if (w_dsk_rd_edge) begin
// Compute frequency correction based on:
// - phase history
// - current phase
case ({r_msb_hist, r_ph_adder[11:9]})
5'b00000 : r_freq_err <= 4'b0100; // +4
5'b00001 : r_freq_err <= 4'b0011; // +3
5'b00010 : r_freq_err <= 4'b0010; // +2
5'b00011 : r_freq_err <= 4'b0001; // +1
5'b00100 : r_freq_err <= 4'b1000; // +0
5'b00101 : r_freq_err <= 4'b1001; // -1
5'b00110 : r_freq_err <= 4'b1010; // -2
5'b00111 : r_freq_err <= 4'b1011; // -3
5'b01000 : r_freq_err <= 4'b0000; // +0
5'b01001 : r_freq_err <= 4'b0000; // +0
5'b01010 : r_freq_err <= 4'b0000; // +0
5'b01011 : r_freq_err <= 4'b0000; // +0
5'b01100 : r_freq_err <= 4'b1000; // +0
5'b01101 : r_freq_err <= 4'b1001; // -1
5'b01110 : r_freq_err <= 4'b1010; // -2
5'b01111 : r_freq_err <= 4'b1011; // -3
5'b10000 : r_freq_err <= 4'b0011; // +3
5'b10001 : r_freq_err <= 4'b0010; // +2
5'b10010 : r_freq_err <= 4'b0001; // +1
5'b10011 : r_freq_err <= 4'b0000; // +0
5'b10100 : r_freq_err <= 4'b1000; // +0
5'b10101 : r_freq_err <= 4'b1000; // +0
5'b10110 : r_freq_err <= 4'b1000; // +0
5'b10111 : r_freq_err <= 4'b1000; // +0
5'b11000 : r_freq_err <= 4'b0011; // +3
5'b11001 : r_freq_err <= 4'b0010; // +2
5'b11010 : r_freq_err <= 4'b0001; // +1
5'b11011 : r_freq_err <= 4'b0000; // +0
5'b11100 : r_freq_err <= 4'b1001; // -1
5'b11101 : r_freq_err <= 4'b1010; // -2
5'b11110 : r_freq_err <= 4'b1011; // -3
5'b11111 : r_freq_err <= 4'b1100; // -4
default : ;
endcase
// No frequency correction
r_cnt_up <= 1'b0;
r_cnt_dn <= 1'b0;
end else begin
if (r_freq_err[2:0] != 3'd0) begin
// Apply frequency correction
r_freq_err[2:0] <= r_freq_err[2:0] - 3'd1;
if (r_freq_err[3]) begin
// Decrement frequency
r_cnt_up <= 1'b0;
r_cnt_dn <= 1'b1;
end else begin
// Increment frequency
r_cnt_up <= 1'b1;
r_cnt_dn <= 1'b0;
end
end else begin
// No frequency correction
r_cnt_up <= 1'b0;
r_cnt_dn <= 1'b0;
end
end
end
end

// ==============================
// == Phase error decoder (75) ==
// ==============================

reg [3:0] r_ph_err; // Ref. 101
reg r_sel_low; // Ref. 45
reg r_sel_ctr; // Ref. 47
reg r_sel_high; // Ref. 49

always@(posedge rst or posedge clk) begin
if (rst) begin
r_ph_err <= 4'd0;
r_sel_low <= 1'b0;
r_sel_ctr <= 1'b1;
r_sel_high <= 1'b0;
end else if (clk_ena) begin
if (w_dsk_rd_edge) begin
// Measure phase error
r_ph_err[3] <= r_ph_adder[11];
if (r_ph_adder[11]) begin
// Negative error
r_sel_low <= 1'b1;
r_sel_ctr <= 1'b0;
r_sel_high <= 1'b0;
r_ph_err[2:0] <= r_ph_adder[10:8];
end else begin
// Positive error
r_sel_low <= 1'b0;
r_sel_ctr <= 1'b0;
r_sel_high <= 1'b1;
r_ph_err[2:0] <= ~r_ph_adder[10:8];
end
end else begin
if (r_ph_err[2:0] != 3'd0) begin
// Apply phase correction
r_ph_err[2:0] <= r_ph_err[2:0] - 3'd1;
if (r_ph_err[3]) begin
// Negative phase correction
r_sel_low <= 1'b1;
r_sel_ctr <= 1'b0;
r_sel_high <= 1'b0;
end else begin
// Positive phase correction
r_sel_low <= 1'b0;
r_sel_ctr <= 1'b0;
r_sel_high <= 1'b1;
end
end else begin
// No phase correction
r_sel_low <= 1'b0;
r_sel_ctr <= 1'b1;
r_sel_high <= 1'b0;
end
end
end
end

endmodule


Enjoy !!

Frederic
FrenchShark is offline  
 
Page generated in 0.12667 seconds with 9 queries