The audio output is still messed up, but this commit gets everything as ready as it can get. Fixed up all the testbenches and added state machines for everything
This commit is contained in:
@@ -31,11 +31,14 @@ module audio_buffer(
|
||||
// Inputs for the memory buffer
|
||||
audio_buffer_interface.receiver driver
|
||||
);
|
||||
logic [9:0] address;
|
||||
// Size of samples, 8bit or 16bit supported
|
||||
parameter SIZE=16;
|
||||
(* MARK_DEBUG = "TRUE" *)
|
||||
logic [11-(SIZE/8):0] address;
|
||||
|
||||
// State register
|
||||
logic enb;
|
||||
logic [15:0] doutb;
|
||||
logic [(SIZE-1):0] doutb;
|
||||
|
||||
// A single bit counter, to avoid feeding samples given the 1 cycle read delay
|
||||
logic delay;
|
||||
@@ -44,7 +47,7 @@ logic delay;
|
||||
// half of the 2KiB buffer
|
||||
//
|
||||
// The MSB of the address == higher/lower half address
|
||||
assign driver.address_half = address[9];
|
||||
assign driver.address_half = address[11-(SIZE/8)];
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
enb <= 0;
|
||||
@@ -75,7 +78,7 @@ always_ff @(posedge clk) begin
|
||||
// NOTE: I really don't know a good way to generate the load
|
||||
// signal. It maybe could be an inverted 48khz clock?
|
||||
if (delay == 0) begin
|
||||
sample <= doutb;
|
||||
sample[15-:SIZE] <= doutb;
|
||||
end
|
||||
else begin
|
||||
sample <= '0;
|
||||
@@ -91,7 +94,7 @@ end
|
||||
//) buffer ();
|
||||
xpm_memory_sdpram #(
|
||||
.ADDR_WIDTH_A(11), // DECIMAL
|
||||
.ADDR_WIDTH_B(10), // DECIMAL
|
||||
.ADDR_WIDTH_B(12-(SIZE/8)), // DECIMAL
|
||||
.AUTO_SLEEP_TIME(0), // DECIMAL
|
||||
.BYTE_WRITE_WIDTH_A(8), // DECIMAL
|
||||
.CASCADE_HEIGHT(0), // DECIMAL
|
||||
@@ -107,7 +110,7 @@ xpm_memory_sdpram #(
|
||||
.MEMORY_SIZE(16*1024), // DECIMAL
|
||||
.MESSAGE_CONTROL(0), // DECIMAL
|
||||
.RAM_DECOMP("auto"), // String
|
||||
.READ_DATA_WIDTH_B(16), // DECIMAL
|
||||
.READ_DATA_WIDTH_B(SIZE), // DECIMAL
|
||||
.READ_LATENCY_B(1), // DECIMAL
|
||||
.READ_RESET_VALUE_B("0"), // String
|
||||
.RST_MODE_A("SYNC"), // String
|
||||
|
||||
@@ -21,6 +21,7 @@ module pwm(
|
||||
parameter DEPTH=11;
|
||||
|
||||
logic [DEPTH-1:0] pulse_counter;
|
||||
(* MARK_DEBUG = "TRUE" *)
|
||||
logic [15:0] sample_buffer;
|
||||
logic should_output;
|
||||
|
||||
|
||||
+30
-19
@@ -88,54 +88,65 @@ end
|
||||
|
||||
display_anode_driver anodeDriver(clk_1khz,reset,AN,segment_mux_select);
|
||||
|
||||
seconds_display secondsSegment (seconds, segments[1], segments[0]);
|
||||
seconds_display minutesSegment (minutes, segments[3], segments[2]);
|
||||
seconds_display hoursSegment (hours, segments[5], segments[4]);
|
||||
sixty_display secondsSegment (seconds, segments[1], segments[0]);
|
||||
sixty_display minutesSegment (minutes, segments[3], segments[2]);
|
||||
sixty_display hoursSegment (hours, segments[5], segments[4]);
|
||||
|
||||
// Run the playback speed state machine at a lower rate
|
||||
// Gets rid of button bouncing
|
||||
playback_controller playbackController (clk_10hz,reset,BTNC, BTNR, speed);
|
||||
|
||||
pwm audioOutput(CLK100MHZ, reset, clk_48khz, audio_sample, AUD_PWM);
|
||||
audio_buffer audioBuffer(
|
||||
clk_48khz,
|
||||
reset,
|
||||
sd_ready,
|
||||
'0, // stop signal not used right now
|
||||
speed,
|
||||
playing,
|
||||
audio_sample,
|
||||
audio_interface.receiver
|
||||
);
|
||||
|
||||
`ifdef ROM
|
||||
rom_sd #("even_flow_16.mem") romSdPlayer(clk_1mhz,reset,sd_ready,audio_interface.driver);
|
||||
assign {SD_RESET,SD_DAT,SD_CMD,SD_SCK} = 'z;
|
||||
audio_buffer audioBuffer(
|
||||
clk_48khz,
|
||||
reset,
|
||||
sd_ready,
|
||||
'0, // stop signal not used right now
|
||||
speed,
|
||||
playing,
|
||||
audio_sample,
|
||||
audio_interface.receiver
|
||||
);
|
||||
pwm audioOutput(CLK100MHZ, reset, clk_48khz, audio_sample, AUD_PWM);
|
||||
`else
|
||||
// Power the sd slot
|
||||
assign SD_RESET = 0;
|
||||
// We don't use more than one dat line
|
||||
assign SD_DAT[3:1] = 'z;
|
||||
logic clk_100khz;
|
||||
logic clk_25mhz;
|
||||
// Actually 200khz now
|
||||
// 200khz is slightly unstable??????
|
||||
modular_clock_gen #(1000) slowSdClock(CLK100MHZ, reset, clk_100khz);
|
||||
modular_clock_gen #(500) slowSdClock(CLK100MHZ, reset, clk_100khz);
|
||||
// Try clocking this slower than max speed
|
||||
// To see if that makes it actually work ...
|
||||
modular_clock_gen #(1000) fastSdClock(CLK100MHZ, reset, clk_25mhz);
|
||||
// If these are different speeds bad things happen :) oops
|
||||
modular_clock_gen #(400) fastSdClock(CLK100MHZ, reset, clk_25mhz);
|
||||
sd_controller realSdPlayer(
|
||||
clk_100khz,
|
||||
clk_25mhz,
|
||||
CLK100MHZ,
|
||||
reset,
|
||||
SD_DAT[0],
|
||||
SD_DAT,
|
||||
SD_CMD,
|
||||
sd_ready,
|
||||
SD_SCK,
|
||||
audio_interface.driver
|
||||
);
|
||||
|
||||
audio_buffer #(.SIZE(8)) audioBuffer(
|
||||
clk_48khz,
|
||||
reset,
|
||||
sd_ready,
|
||||
'0, // stop signal not used right now
|
||||
speed,
|
||||
playing,
|
||||
audio_sample,
|
||||
audio_interface.receiver
|
||||
);
|
||||
pwm #(8) audioOutput(CLK100MHZ, reset, clk_48khz, audio_sample, AUD_PWM);
|
||||
|
||||
`endif
|
||||
|
||||
|
||||
|
||||
+19
-15
@@ -4,8 +4,7 @@
|
||||
module read_data(
|
||||
input clk,
|
||||
input reset,
|
||||
input sd_data,
|
||||
(* MARK_DEBUG = "TRUE" *)
|
||||
input [3:0] sd_data,
|
||||
audio_buffer_interface.driver buffer
|
||||
);
|
||||
// Block data is a start bit, 512 bytes sent msb first, then a CRC16 and end
|
||||
@@ -16,7 +15,7 @@ module read_data(
|
||||
// played. However, as long as the sd card controller doesn't request extra
|
||||
// blocks this shouldn't be an issue
|
||||
|
||||
localparam BLOCK_SIZE=512*8+16+2;
|
||||
localparam BLOCK_SIZE=512*2+16*4+2;
|
||||
logic [$clog2(BLOCK_SIZE):0] counter;
|
||||
|
||||
logic [7:0] byte_shift;
|
||||
@@ -28,36 +27,41 @@ assign buffer.clka = clk;
|
||||
always_ff @(posedge clk) begin
|
||||
if (reset) begin
|
||||
buffer.ena <= 0;
|
||||
buffer.addra <= '1;
|
||||
// Start negative so adding bytes will get us to the right address
|
||||
buffer.addra <= 0 - 512;
|
||||
buffer.dina <= 0;
|
||||
end
|
||||
else begin
|
||||
// We ignore the lower 17 bits of the block
|
||||
if (counter > 16) begin
|
||||
// We ignore the lower 16*4+1 bits of the block
|
||||
// CRC is apparently sent on each line, back to back
|
||||
if (counter > 16*4) begin
|
||||
counter <= counter - 1;
|
||||
byte_shift <= {byte_shift[6:0],sd_data};
|
||||
byte_shift <= {byte_shift[3:0],sd_data};
|
||||
byte_counter <= byte_counter - 1;
|
||||
|
||||
// Store received byte in audio buffer and reset counter
|
||||
if (byte_counter == 0) begin
|
||||
byte_counter <= 7;
|
||||
buffer.dina <= byte_shift;//{byte_shift[6:0],sd_data};
|
||||
byte_counter <= 1;
|
||||
buffer.dina <= {byte_shift[3:0],sd_data};
|
||||
buffer.ena <= 1;
|
||||
end
|
||||
|
||||
// Turn the enable signal off so we don't accidentally write
|
||||
// anything weird
|
||||
if (byte_counter == 4) begin
|
||||
buffer.ena <= 0;
|
||||
buffer.addra <= buffer.addra + 1;
|
||||
if (byte_counter == 1) begin
|
||||
buffer.addra <= buffer.addra - 1;
|
||||
end
|
||||
|
||||
end
|
||||
else if (counter != 0)
|
||||
else if (counter != 0) begin
|
||||
counter<=counter-1;
|
||||
buffer.ena <= 0;
|
||||
end
|
||||
else if (sd_data == 0) begin
|
||||
counter <= BLOCK_SIZE-1;
|
||||
byte_counter <= 8;
|
||||
// In wide bus mode we read bytes in a descending order
|
||||
buffer.addra <= buffer.addra + 1024;
|
||||
counter <= BLOCK_SIZE;
|
||||
byte_counter <= 3;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
+64
-12
@@ -14,7 +14,7 @@ module sd_controller(
|
||||
input logic crc_clk,
|
||||
input logic reset,
|
||||
(* MARK_DEBUG = "TRUE" *)
|
||||
input logic sd_data,
|
||||
input logic [3:0] sd_data,
|
||||
inout logic sd_cmd,
|
||||
output logic ready,
|
||||
output wire clk,
|
||||
@@ -22,7 +22,6 @@ module sd_controller(
|
||||
audio_buffer_interface.driver buffer
|
||||
);
|
||||
// NOTE: this gets encoded as one-hot, even if in here I set it as a logic[5:0]
|
||||
(* MARK_DEBUG = "TRUE" *)
|
||||
enum logic [5:0] {
|
||||
INIT,WAIT,SEND_CMD0,WAIT_CMD0,DELAY_CMD0, // last 4
|
||||
SEND_CMD8,WAIT_CMD8,LISTEN_RESPONSE_CMD8,WAIT_RESPONSE_CMD8, // last 8
|
||||
@@ -31,13 +30,15 @@ enum logic [5:0] {
|
||||
SEND_CMD2,WAIT_CMD2,LISTEN_RESPONSE_CMD2,WAIT_RESPONSE_CMD2, //21
|
||||
SEND_CMD3,WAIT_CMD3,LISTEN_RESPONSE_CMD3,WAIT_RESPONSE_CMD3, //25
|
||||
SEND_CMD7,WAIT_CMD7,LISTEN_RESPONSE_CMD7,WAIT_RESPONSE_CMD7, //29
|
||||
SEND2_CMD55,WAIT2_CMD55,LISTEN_RESPONSE2_CMD55,WAIT_RESPONSE2_CMD55,
|
||||
SEND_ACMD6,WAIT_ACMD6,LISTEN_RESPONSE_ACMD6,WAIT_RESPONSE_ACMD6,
|
||||
READY_TO_TRANSMIT,
|
||||
DELAY_CLOCK_SWITCH,
|
||||
TRANSMIT,WAIT_TRANSMIT,WAIT_END,FINISH_TRANSMIT,
|
||||
TRANSMIT2,WAIT_TRANSMIT2,WAIT_END2,FINISH_TRANSMIT2,
|
||||
WAIT_FOR_BUFFER
|
||||
} state, next_state;
|
||||
|
||||
(* MARK_DEBUG = "TRUE" *)
|
||||
logic fast_clk_enable;
|
||||
assign clk = fast_clk_enable ? fast_clk : slow_clk;
|
||||
|
||||
@@ -49,7 +50,6 @@ logic [31:0] address;
|
||||
logic send_command_start;//, send_command_start_fast;
|
||||
(* MARK_DEBUG = "TRUE" *)
|
||||
logic [5:0] cmd;
|
||||
(* MARK_DEBUG = "TRUE" *)
|
||||
logic [31:0] arg;
|
||||
(* MARK_DEBUG = "TRUE" *)
|
||||
wire send_command_ready;//, send_command_ready_fast;
|
||||
@@ -189,7 +189,7 @@ always_comb begin
|
||||
next_state=WAIT_RESPONSE_CMD7;
|
||||
WAIT_RESPONSE_CMD7:
|
||||
if (read_command_received)
|
||||
next_state=READY_TO_TRANSMIT;
|
||||
next_state=SEND2_CMD55;
|
||||
else
|
||||
next_state=WAIT_RESPONSE_CMD7;
|
||||
|
||||
@@ -230,8 +230,42 @@ always_comb begin
|
||||
else
|
||||
next_state=ACMD41_DELAY;
|
||||
|
||||
SEND2_CMD55:
|
||||
next_state=WAIT2_CMD55;
|
||||
WAIT2_CMD55:
|
||||
if (send_command_ready)
|
||||
next_state=LISTEN_RESPONSE2_CMD55;
|
||||
else
|
||||
next_state=WAIT2_CMD55;
|
||||
LISTEN_RESPONSE2_CMD55:
|
||||
next_state=WAIT_RESPONSE2_CMD55;
|
||||
WAIT_RESPONSE2_CMD55:
|
||||
if (read_command_received)
|
||||
next_state=SEND_ACMD6;
|
||||
else
|
||||
next_state=WAIT_RESPONSE2_CMD55;
|
||||
SEND_ACMD6:
|
||||
next_state=WAIT_ACMD6;
|
||||
WAIT_ACMD6:
|
||||
if (send_command_ready)
|
||||
next_state=LISTEN_RESPONSE_ACMD6;
|
||||
else
|
||||
next_state=WAIT_ACMD6;
|
||||
LISTEN_RESPONSE_ACMD6:
|
||||
next_state=WAIT_RESPONSE_ACMD6;
|
||||
WAIT_RESPONSE_ACMD6:
|
||||
if (read_command_received)
|
||||
next_state=READY_TO_TRANSMIT;
|
||||
else
|
||||
next_state=WAIT_RESPONSE_ACMD6;
|
||||
|
||||
READY_TO_TRANSMIT:
|
||||
next_state=TRANSMIT;
|
||||
next_state=DELAY_CLOCK_SWITCH;
|
||||
DELAY_CLOCK_SWITCH:
|
||||
if (counter == 0)
|
||||
next_state = TRANSMIT;
|
||||
else
|
||||
next_state = DELAY_CLOCK_SWITCH;
|
||||
TRANSMIT:
|
||||
next_state=WAIT_TRANSMIT;
|
||||
WAIT_TRANSMIT:
|
||||
@@ -310,7 +344,14 @@ always_ff @(posedge clk) begin
|
||||
arg <= 0;
|
||||
send_command_start <=1;
|
||||
end
|
||||
LISTEN_RESPONSE_CMD55: begin
|
||||
SEND2_CMD55: begin
|
||||
cmd <= 55;
|
||||
// the arg should be the same as the preceding command
|
||||
// and otherwise we'll lose the RCA bits
|
||||
//arg <= 0;
|
||||
send_command_start <=1;
|
||||
end
|
||||
LISTEN_RESPONSE_CMD55,LISTEN_RESPONSE2_CMD55: begin
|
||||
response_type <= 1;
|
||||
read_command_listen <= 1;
|
||||
end
|
||||
@@ -327,6 +368,15 @@ always_ff @(posedge clk) begin
|
||||
read_command_listen<=0;
|
||||
counter<=100;
|
||||
end
|
||||
SEND_ACMD6: begin
|
||||
cmd <= 6;
|
||||
arg <= 'b10;
|
||||
send_command_start <=1;
|
||||
end
|
||||
LISTEN_RESPONSE_ACMD6: begin
|
||||
response_type <= 1;
|
||||
read_command_listen <= 1;
|
||||
end
|
||||
SEND_CMD2: begin
|
||||
cmd <= 2;
|
||||
arg <= 0;
|
||||
@@ -358,6 +408,8 @@ always_ff @(posedge clk) begin
|
||||
fast_clk_enable <= 1;
|
||||
address <= 0;
|
||||
sd_buffer_half <= 0;
|
||||
// Wait to actually transmit until clock is running and stable
|
||||
counter <= 100;
|
||||
end
|
||||
TRANSMIT, TRANSMIT2: begin
|
||||
cmd <= 17;
|
||||
@@ -366,7 +418,7 @@ always_ff @(posedge clk) begin
|
||||
end
|
||||
WAIT_TRANSMIT, WAIT_TRANSMIT2: begin
|
||||
send_command_start <= 0;
|
||||
counter <= 411;
|
||||
counter <= 512*2+16+1;
|
||||
end
|
||||
FINISH_TRANSMIT:
|
||||
address <= address +1;
|
||||
@@ -377,12 +429,12 @@ always_ff @(posedge clk) begin
|
||||
WAIT_FOR_BUFFER:
|
||||
ready <= 1;
|
||||
// The logic is simple enough in these to group them
|
||||
WAIT, DELAY_CMD0, ACMD41_DELAY, WAIT_END, WAIT_END2:
|
||||
WAIT, DELAY_CMD0, ACMD41_DELAY, WAIT_END, WAIT_END2, DELAY_CLOCK_SWITCH:
|
||||
counter <= counter - 1;
|
||||
WAIT_CMD8,WAIT_CMD55,WAIT_ACMD41,WAIT_CMD2,WAIT_CMD3,WAIT_CMD7:
|
||||
WAIT_CMD8,WAIT_CMD55,WAIT_ACMD41,WAIT2_CMD55,WAIT_ACMD6,WAIT_CMD2,WAIT_CMD3,WAIT_CMD7:
|
||||
send_command_start<=0;
|
||||
WAIT_RESPONSE_CMD8,WAIT_RESPONSE_CMD55,WAIT_RESPONSE_CMD2,WAIT_RESPONSE_CMD3,
|
||||
WAIT_RESPONSE_CMD7:
|
||||
WAIT_RESPONSE_CMD8,WAIT_RESPONSE_CMD55,WAIT_RESPONSE2_CMD55,WAIT_RESPONSE_ACMD6,
|
||||
WAIT_RESPONSE_CMD2,WAIT_RESPONSE_CMD3,WAIT_RESPONSE_CMD7:
|
||||
read_command_listen<=0;
|
||||
default: ;
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/***
|
||||
* seconds_display.sv - converts a five bit seconds counter to its seven segement display equivalent.
|
||||
* sixty_display.sv - converts a five bit seconds counter to its seven segement display equivalent.
|
||||
*
|
||||
* @author: Dilanthi Prentice, Waylon Cude
|
||||
* @date: 6/12/25
|
||||
*
|
||||
*/
|
||||
|
||||
module seconds_display
|
||||
module sixty_display
|
||||
(
|
||||
input [$clog2(60)-1:0] seconds,
|
||||
input [$clog2(60)-1:0] number,
|
||||
output [6:0] display_tens,
|
||||
output [6:0] display_ones
|
||||
);
|
||||
@@ -18,8 +18,8 @@ logic [4:0] tens_digit;
|
||||
|
||||
always_comb
|
||||
begin
|
||||
ones_digit = seconds % 10;
|
||||
tens_digit = seconds / 10;
|
||||
ones_digit = number % 10;
|
||||
tens_digit = number / 10;
|
||||
end
|
||||
|
||||
//instantiate the display_converter to convert the counter
|
||||
Reference in New Issue
Block a user