mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-25 23:24:15 +01:00
almost working
This commit is contained in:
parent
97b7291001
commit
5524487f80
@ -301,5 +301,6 @@ set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
|
||||
# end ENTITY(SummerCart64)
|
||||
# ------------------------
|
||||
set_global_assignment -name QIP_FILE rtl/intel/gpio/intel_gpio_ddro.qip
|
||||
|
||||
set_global_assignment -name SLD_FILE db/stp_auto_stripped.stp
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
@ -7,7 +7,7 @@ volatile int counter = 0;
|
||||
|
||||
void print (const char *text) {
|
||||
while (*text != '\0') {
|
||||
while (!(UART_SR & UART_SR_TXE));
|
||||
while (!(UART_SCR & UART_SCR_TXE));
|
||||
UART_DR = *text++;
|
||||
}
|
||||
}
|
||||
@ -50,38 +50,147 @@ void print_nice_date(uint8_t *date) {
|
||||
print_02hex(date[0]);
|
||||
}
|
||||
|
||||
const char CMD[3] = {'C', 'M', 'D'};
|
||||
const char CMD_R = 'R';
|
||||
const char CMD_W = 'W';
|
||||
|
||||
const char CMP[3] = {'C', 'M', 'P'};
|
||||
|
||||
__NAKED__ int main (void) {
|
||||
uint8_t rtc_data[7];
|
||||
uint8_t rtc_new_data[7];
|
||||
int index = 0;
|
||||
uint8_t data;
|
||||
uint8_t cmd = '-';
|
||||
uint32_t arg1, arg2;
|
||||
char tmp[2];
|
||||
|
||||
tmp[1] = 0;
|
||||
|
||||
GPIO_OE = (1 << 0);
|
||||
GPIO_O = (1 << 0);
|
||||
|
||||
rtc_init();
|
||||
DMA_SCR = DMA_SCR_STOP;
|
||||
USB_SCR = USB_SCR_FLUSH_TX | USB_SCR_FLUSH_TX;
|
||||
|
||||
while (1) {
|
||||
GPIO_O = (1 << 0);
|
||||
arg1 = 0;
|
||||
arg2 = 0;
|
||||
|
||||
print("\033[2J\033[H\r\n --- Hello --- \r\n\r\n");
|
||||
print(" RTC Data:\r\n\r\n ");
|
||||
print("\r\nLoop start\r\n");
|
||||
|
||||
rtc_get_time(rtc_data);
|
||||
|
||||
print_nice_date(rtc_data);
|
||||
|
||||
print("\r\n");
|
||||
GPIO_O = 0x00;
|
||||
|
||||
while (counter++ < 0x0003FFFF);
|
||||
counter = 0;
|
||||
|
||||
if (USB_SR & USB_SR_RXNE) {
|
||||
rtc_new_data[index++] = USB_DR;
|
||||
if (index == 7) {
|
||||
index = 0;
|
||||
rtc_set_time(rtc_new_data);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
while (!(USB_SCR & USB_SCR_RXNE));
|
||||
data = USB_DR;
|
||||
if (i < 3 && data != CMD[i]) {
|
||||
i = 0;
|
||||
print("Wrong data ");
|
||||
print_02hex(data);
|
||||
print("\r\n");
|
||||
} else {
|
||||
cmd = data;
|
||||
}
|
||||
}
|
||||
|
||||
print("Received CMD");
|
||||
tmp[0] = cmd;
|
||||
print(tmp);
|
||||
print("\r\n");
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
while (!(USB_SCR & USB_SCR_RXNE));
|
||||
arg1 = (arg1 << 8) | USB_DR;
|
||||
}
|
||||
|
||||
print("Received ARG_1 0x");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
print_02hex((uint8_t) (arg1 >> ((3 - i) * 8)));
|
||||
}
|
||||
print("\r\n");
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
while (!(USB_SCR & USB_SCR_RXNE));
|
||||
arg2 = (arg2 << 8) | USB_DR;
|
||||
}
|
||||
|
||||
print("Received ARG_2 0x");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
print_02hex((uint8_t) (arg2 >> ((3 - i) * 8)));
|
||||
}
|
||||
print("\r\n");
|
||||
|
||||
DMA_MADDR = arg1;
|
||||
DMA_ID_LEN = arg2;
|
||||
DMA_SCR = (cmd == CMD_W ? DMA_SCR_DIR : 0) | DMA_SCR_START;
|
||||
|
||||
print("Started DMA\r\n");
|
||||
|
||||
while (DMA_SCR & DMA_SCR_BUSY);
|
||||
|
||||
// for (int i = 0; i < arg2; i++) {
|
||||
// while (!(USB_SCR & USB_SCR_RXNE));
|
||||
// data = USB_DR;
|
||||
// }
|
||||
|
||||
print("Finished DMA\r\n");
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
while (!(USB_SCR & USB_SCR_TXE));
|
||||
if (i < 3) {
|
||||
USB_DR = CMP[i];
|
||||
} else {
|
||||
USB_DR = cmd;
|
||||
}
|
||||
}
|
||||
|
||||
print("Sent response ");
|
||||
tmp[0] = cmd;
|
||||
print(tmp);
|
||||
print("\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
// __NAKED__ int main (void) {
|
||||
// uint8_t rtc_data[7];
|
||||
// uint8_t rtc_new_data[7];
|
||||
// int index = 0;
|
||||
|
||||
// GPIO_OE = (1 << 0);
|
||||
// GPIO_O = (1 << 0);
|
||||
|
||||
// rtc_init();
|
||||
|
||||
// while (!(USB_SR & USB_SR_TXE));
|
||||
// USB_DR = 0x55;
|
||||
// USB_DR = 0xAA;
|
||||
// USB_DR = 0x00;
|
||||
// USB_DR = 'D';
|
||||
// USB_DR = 'E';
|
||||
// USB_DR = 'A';
|
||||
// USB_DR = 'D';
|
||||
// USB_DR = 0xFF;
|
||||
// USB_DR = 0xAA;
|
||||
// USB_DR = 0x55;
|
||||
|
||||
// while (1) {
|
||||
// GPIO_O = (1 << 0);
|
||||
|
||||
// print("\033[2J\033[H\r\n --- Hello --- \r\n\r\n");
|
||||
// print(" RTC Data:\r\n\r\n ");
|
||||
|
||||
// rtc_get_time(rtc_data);
|
||||
|
||||
// print_nice_date(rtc_data);
|
||||
|
||||
// print("\r\n");
|
||||
// GPIO_O = 0x00;
|
||||
|
||||
// while (counter++ < 0x0003FFFF);
|
||||
// counter = 0;
|
||||
|
||||
// if (USB_SR & USB_SR_RXNE) {
|
||||
// rtc_new_data[index++] = USB_DR;
|
||||
// if (index == 7) {
|
||||
// index = 0;
|
||||
// rtc_set_time(rtc_new_data);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
@ -11,16 +11,22 @@
|
||||
typedef volatile uint8_t * io8_t;
|
||||
typedef volatile uint32_t * io32_t;
|
||||
|
||||
#define RAM (*((io32_t) 0x00000000))
|
||||
#define BOOTLOADER (*((io32_t) 0x10000000))
|
||||
#define GPIO (*((io32_t) 0x20000000))
|
||||
#define GPIO_O (*((io8_t) 0x20000000))
|
||||
#define GPIO_I (*((io8_t) 0x20000001))
|
||||
#define GPIO_OE (*((io8_t) 0x20000002))
|
||||
#define I2C_SR (*((io8_t) 0x30000000))
|
||||
#define I2C_DR (*((io8_t) 0x30000004))
|
||||
#define USB_SR (*((io8_t) 0x40000000))
|
||||
#define USB_SCR (*((io8_t) 0x40000000))
|
||||
#define USB_DR (*((io8_t) 0x40000004))
|
||||
#define UART_SR (*((io8_t) 0x50000000))
|
||||
#define UART_SCR (*((io8_t) 0x50000000))
|
||||
#define UART_DR (*((io8_t) 0x50000004))
|
||||
#define DMA_SCR (*((io8_t) 0x60000000))
|
||||
#define DMA_MADDR (*((io32_t) 0x60000004))
|
||||
#define DMA_ID_LEN (*((io32_t) 0x60000008))
|
||||
#define SDRAM (*((io32_t) 0x68000000))
|
||||
|
||||
#define I2C_SR_START (1 << 0)
|
||||
#define I2C_SR_STOP (1 << 1)
|
||||
@ -29,11 +35,21 @@ typedef volatile uint32_t * io32_t;
|
||||
#define I2C_SR_BUSY (1 << 4)
|
||||
#define I2C_ADDR_READ (1 << 0)
|
||||
|
||||
#define USB_SR_RXNE (1 << 0)
|
||||
#define USB_SR_TXE (1 << 1)
|
||||
#define USB_SCR_RXNE (1 << 0)
|
||||
#define USB_SCR_TXE (1 << 1)
|
||||
#define USB_SCR_FLUSH_RX (1 << 2)
|
||||
#define USB_SCR_FLUSH_TX (1 << 3)
|
||||
|
||||
#define UART_SR_RXNE (1 << 0)
|
||||
#define UART_SR_TXE (1 << 1)
|
||||
#define UART_SCR_RXNE (1 << 0)
|
||||
#define UART_SCR_TXE (1 << 1)
|
||||
|
||||
#define DMA_SCR_START (1 << 0)
|
||||
#define DMA_SCR_STOP (1 << 1)
|
||||
#define DMA_SCR_DIR (1 << 2)
|
||||
#define DMA_SCR_BUSY (1 << 3)
|
||||
|
||||
#define DMA_ID_USB (0)
|
||||
#define DMA_ID_SD (1)
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,16 @@
|
||||
interface if_dma ();
|
||||
|
||||
localparam [1:0] NUM_DEVICES = sc64::__ID_DMA_END;
|
||||
|
||||
sc64::e_dma_id id;
|
||||
|
||||
logic rx_empty;
|
||||
logic rx_read;
|
||||
logic [7:0] rx_rdata;
|
||||
logic tx_full;
|
||||
logic tx_write;
|
||||
logic [7:0] tx_wdata;
|
||||
|
||||
logic request;
|
||||
logic ack;
|
||||
logic write;
|
||||
@ -7,7 +18,16 @@ interface if_dma ();
|
||||
logic [15:0] rdata;
|
||||
logic [15:0] wdata;
|
||||
|
||||
modport cpu (
|
||||
modport controller (
|
||||
output id,
|
||||
|
||||
input rx_empty,
|
||||
output rx_read,
|
||||
input rx_rdata,
|
||||
input tx_full,
|
||||
output tx_write,
|
||||
output tx_wdata,
|
||||
|
||||
output request,
|
||||
input ack,
|
||||
output write,
|
||||
@ -25,4 +45,136 @@ interface if_dma ();
|
||||
input wdata
|
||||
);
|
||||
|
||||
logic [7:0] device_rx_rdata [(NUM_DEVICES - 1):0];
|
||||
logic device_rx_empty [(NUM_DEVICES - 1):0];
|
||||
logic device_tx_full [(NUM_DEVICES - 1):0];
|
||||
|
||||
always_comb begin
|
||||
rx_rdata = 8'd0;
|
||||
|
||||
for (integer i = 0; i < NUM_DEVICES; i++) begin
|
||||
rx_rdata = rx_rdata | device_rx_rdata[i];
|
||||
rx_empty = rx_empty | (device_rx_empty[i] && id == i[1:0]);
|
||||
tx_full = tx_full | (device_tx_full[i] && id == i[1:0]);
|
||||
end
|
||||
end
|
||||
|
||||
genvar n;
|
||||
generate
|
||||
for (n = 0; n < NUM_DEVICES; n++) begin : at
|
||||
logic device_selected;
|
||||
logic device_rx_read;
|
||||
logic device_tx_write;
|
||||
|
||||
always_comb begin
|
||||
device_selected = id == n[1:0];
|
||||
device_rx_read = device_selected && rx_read;
|
||||
device_tx_write = device_selected && tx_write;
|
||||
end
|
||||
|
||||
modport device (
|
||||
output .rx_empty(device_rx_empty[n]),
|
||||
input .rx_read(device_rx_read),
|
||||
output .rx_rdata(device_rx_rdata[n]),
|
||||
output .tx_full(device_tx_full[n]),
|
||||
input .tx_write(device_tx_write),
|
||||
input .tx_wdata(tx_wdata)
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endinterface
|
||||
|
||||
|
||||
module cpu_dma (
|
||||
if_system.sys sys,
|
||||
if_cpu_bus bus,
|
||||
if_dma.controller dma
|
||||
);
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
bus.ack <= 1'b0;
|
||||
if (bus.request) begin
|
||||
bus.ack <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
bus.rdata = 32'd0;
|
||||
// if (bus.ack) begin
|
||||
// case (bus.address[2:2])
|
||||
// 0: bus.rdata = {30'd0, ~tx_full, ~rx_empty};
|
||||
// 1: bus.rdata = {24'd0, rx_rdata};
|
||||
// default: bus.rdata = 32'd0;
|
||||
// endcase
|
||||
// end
|
||||
end
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
// rx_flush <= 1'b0;
|
||||
// cpu_rx_read <= 1'b0;
|
||||
|
||||
// tx_flush <= 1'b0;
|
||||
// cpu_tx_write <= 1'b0;
|
||||
|
||||
// if (bus.request) begin
|
||||
// case (bus.address[2:2])
|
||||
// 2'd0: begin
|
||||
// if (bus.wmask[0]) begin
|
||||
// {tx_flush, rx_flush} <= bus.wdata[3:2];
|
||||
// end
|
||||
// end
|
||||
|
||||
// 2'd1: begin
|
||||
// if (bus.wmask[0]) begin
|
||||
// cpu_tx_write <= 1'b1;
|
||||
// end else begin
|
||||
// cpu_rx_read <= 1'b1;
|
||||
// end
|
||||
// end
|
||||
// endcase
|
||||
// end
|
||||
end
|
||||
// typedef enum bit [0:0] {
|
||||
// S_IDLE,
|
||||
// S_WAIT
|
||||
// } e_state;
|
||||
|
||||
// e_state state;
|
||||
|
||||
// logic byte_counter;
|
||||
|
||||
// always_ff @(posedge sys.clk) begin
|
||||
// rx_read <= 1'b0;
|
||||
|
||||
// if (sys.reset) begin
|
||||
// dma.request <= 1'b0;
|
||||
// dma.write <= 1'b1;
|
||||
// dma.address <= 32'd0;
|
||||
// state <= S_IDLE;
|
||||
// byte_counter <= 1'b0;
|
||||
// end else begin
|
||||
// case (state)
|
||||
// S_IDLE: begin
|
||||
// if (!rx_empty && !rx_read) begin
|
||||
// byte_counter <= ~byte_counter;
|
||||
// rx_read <= 1'b1;
|
||||
// dma.wdata <= {dma.wdata[7:0], rx_rdata};
|
||||
// if (byte_counter) begin
|
||||
// dma.request <= 1'b1;
|
||||
// state <= S_WAIT;
|
||||
// end
|
||||
// end
|
||||
// end
|
||||
|
||||
// S_WAIT: begin
|
||||
// if (dma.ack) begin
|
||||
// dma.address <= dma.address + 2'd2;
|
||||
// dma.request <= 1'b0;
|
||||
// state <= S_IDLE;
|
||||
// end
|
||||
// end
|
||||
// endcase
|
||||
// end
|
||||
// end
|
||||
endmodule
|
||||
|
@ -61,7 +61,7 @@ module cpu_soc (
|
||||
cpu_usb cpu_usb_inst (
|
||||
.sys(sys),
|
||||
.bus(bus.at[sc64::ID_CPU_USB].device),
|
||||
.dma(dma),
|
||||
.dma(dma.at[sc64::ID_DMA_USB].device),
|
||||
.usb_clk(usb_clk),
|
||||
.usb_cs(usb_cs),
|
||||
.usb_miso(usb_miso),
|
||||
@ -78,4 +78,10 @@ module cpu_soc (
|
||||
.uart_rts(uart_rts)
|
||||
);
|
||||
|
||||
cpu_dma cpu_dma_inst (
|
||||
.sys(sys),
|
||||
.bus(bus.at[sc64::ID_CPU_DMA].device),
|
||||
.dma(dma)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
@ -1,7 +1,7 @@
|
||||
module cpu_usb (
|
||||
if_system sys,
|
||||
if_cpu_bus bus,
|
||||
if_dma.cpu dma,
|
||||
if_dma dma,
|
||||
|
||||
output usb_clk,
|
||||
output usb_cs,
|
||||
@ -20,86 +20,57 @@ module cpu_usb (
|
||||
logic tx_write;
|
||||
logic [7:0] tx_wdata;
|
||||
|
||||
// always_ff @(posedge sys.clk) begin
|
||||
// bus.ack <= 1'b0;
|
||||
// if (bus.request) begin
|
||||
// bus.ack <= 1'b1;
|
||||
// end
|
||||
// end
|
||||
logic cpu_rx_read;
|
||||
logic cpu_tx_write;
|
||||
|
||||
// always_comb begin
|
||||
// bus.rdata = 32'd0;
|
||||
// if (bus.ack) begin
|
||||
// case (bus.address[2:2])
|
||||
// 0: bus.rdata = {30'd0, ~tx_full, ~rx_empty};
|
||||
// 1: bus.rdata = {24'd0, rx_rdata};
|
||||
// default: bus.rdata = 32'd0;
|
||||
// endcase
|
||||
// end
|
||||
// end
|
||||
always_comb begin
|
||||
dma.rx_empty = rx_empty;
|
||||
rx_read = cpu_rx_read || dma.rx_read;
|
||||
dma.rx_rdata = rx_rdata;
|
||||
|
||||
// always_ff @(posedge sys.clk) begin
|
||||
// rx_flush <= 1'b0;
|
||||
// rx_read <= 1'b0;
|
||||
|
||||
// tx_flush <= 1'b0;
|
||||
// tx_write <= 1'b0;
|
||||
|
||||
// if (bus.request) begin
|
||||
// case (bus.address[2:2])
|
||||
// 2'd0: if (bus.wmask[0]) begin
|
||||
// {tx_flush, rx_flush} <= bus.wdata[3:2];
|
||||
// end
|
||||
|
||||
// 2'd1: if (bus.wmask[0]) begin
|
||||
// if (!tx_full) begin
|
||||
// tx_write <= 1'b1;
|
||||
// tx_wdata <= bus.wdata[7:0];
|
||||
// end
|
||||
// end else begin
|
||||
// rx_read <= 1'b1;
|
||||
// end
|
||||
// endcase
|
||||
// end
|
||||
// end
|
||||
|
||||
typedef enum bit [0:0] {
|
||||
S_IDLE,
|
||||
S_WAIT
|
||||
} e_state;
|
||||
|
||||
e_state state;
|
||||
|
||||
logic byte_counter;
|
||||
dma.tx_full = tx_full;
|
||||
tx_write = cpu_tx_write || dma.tx_write;
|
||||
tx_wdata = dma.tx_write ? dma.tx_wdata : bus.wdata[7:0];
|
||||
end
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
rx_read <= 1'b0;
|
||||
bus.ack <= 1'b0;
|
||||
if (bus.request) begin
|
||||
bus.ack <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
if (sys.reset) begin
|
||||
dma.request <= 1'b0;
|
||||
dma.write <= 1'b1;
|
||||
dma.address <= 32'd0;
|
||||
state <= S_IDLE;
|
||||
byte_counter <= 1'b0;
|
||||
end else begin
|
||||
case (state)
|
||||
S_IDLE: begin
|
||||
if (!rx_empty && !rx_read) begin
|
||||
byte_counter <= ~byte_counter;
|
||||
rx_read <= 1'b1;
|
||||
dma.wdata <= {dma.wdata[7:0], rx_rdata};
|
||||
if (byte_counter) begin
|
||||
dma.request <= 1'b1;
|
||||
state <= S_WAIT;
|
||||
end
|
||||
always_comb begin
|
||||
bus.rdata = 32'd0;
|
||||
if (bus.ack) begin
|
||||
case (bus.address[2:2])
|
||||
0: bus.rdata = {30'd0, ~tx_full, ~rx_empty};
|
||||
1: bus.rdata = {24'd0, rx_rdata};
|
||||
default: bus.rdata = 32'd0;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
rx_flush <= 1'b0;
|
||||
cpu_rx_read <= 1'b0;
|
||||
|
||||
tx_flush <= 1'b0;
|
||||
cpu_tx_write <= 1'b0;
|
||||
|
||||
if (bus.request) begin
|
||||
case (bus.address[2:2])
|
||||
2'd0: begin
|
||||
if (bus.wmask[0]) begin
|
||||
{tx_flush, rx_flush} <= bus.wdata[3:2];
|
||||
end
|
||||
end
|
||||
|
||||
S_WAIT: begin
|
||||
if (dma.ack) begin
|
||||
dma.address <= dma.address + 2'd2;
|
||||
dma.request <= 1'b0;
|
||||
state <= S_IDLE;
|
||||
2'd1: begin
|
||||
if (bus.wmask[0]) begin
|
||||
cpu_tx_write <= 1'b1;
|
||||
end else begin
|
||||
cpu_rx_read <= 1'b1;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
@ -120,10 +91,10 @@ module cpu_usb (
|
||||
.rx_read(rx_read),
|
||||
.rx_rdata(rx_rdata),
|
||||
|
||||
// .tx_flush(tx_flush),
|
||||
// .tx_full(tx_full),
|
||||
// .tx_write(tx_write),
|
||||
// .tx_wdata(tx_wdata)
|
||||
.tx_flush(tx_flush),
|
||||
.tx_full(tx_full),
|
||||
.tx_write(tx_write),
|
||||
.tx_wdata(tx_wdata)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
@ -4,7 +4,7 @@ module memory_sdram (
|
||||
input request,
|
||||
output ack,
|
||||
input write,
|
||||
input [31:0] address,
|
||||
input [25:0] address,
|
||||
output [15:0] rdata,
|
||||
input [15:0] wdata,
|
||||
|
||||
|
@ -73,7 +73,7 @@ module n64_sdram (
|
||||
.request(mem_request),
|
||||
.ack(mem_ack),
|
||||
.write(mem_write),
|
||||
.address(mem_address),
|
||||
.address(mem_address[25:0]),
|
||||
.rdata(mem_rdata),
|
||||
.wdata(mem_wdata),
|
||||
|
||||
|
@ -16,13 +16,20 @@ package sc64;
|
||||
ID_CPU_I2C,
|
||||
ID_CPU_USB,
|
||||
ID_CPU_UART,
|
||||
ID_CPU_DMA,
|
||||
__ID_CPU_END
|
||||
} e_cpu_id;
|
||||
|
||||
typedef enum bit [1:0] {
|
||||
ID_DMA_USB,
|
||||
ID_DMA_SD,
|
||||
__ID_DMA_END
|
||||
} e_dma_id;
|
||||
|
||||
parameter int CLOCK_FREQUENCY = 32'd100_000_000;
|
||||
|
||||
parameter int UART_BAUD_RATE = 32'd1_000_000;
|
||||
|
||||
parameter bit DEBUG_ENABLED = 1'b0;
|
||||
parameter bit DEBUG_ENABLED = 1'b1;
|
||||
|
||||
endpackage
|
||||
|
@ -9,39 +9,34 @@ module usb_ft1248 (
|
||||
|
||||
input rx_flush,
|
||||
output rx_empty,
|
||||
// output rx_almost_empty,
|
||||
input rx_read,
|
||||
output [7:0] rx_rdata,
|
||||
|
||||
input tx_flush,
|
||||
output tx_full,
|
||||
// output tx_almost_full,
|
||||
input tx_write,
|
||||
input [7:0] tx_wdata
|
||||
);
|
||||
|
||||
// FIFOs
|
||||
|
||||
wire rx_full;
|
||||
wire rx_almost_full;
|
||||
reg rx_write;
|
||||
reg [7:0] rx_wdata;
|
||||
logic rx_full;
|
||||
logic rx_write;
|
||||
logic [7:0] rx_wdata;
|
||||
|
||||
wire tx_empty;
|
||||
reg tx_read;
|
||||
wire [7:0] tx_rdata;
|
||||
logic tx_empty;
|
||||
logic tx_read;
|
||||
logic [7:0] tx_rdata;
|
||||
|
||||
intel_fifo_8 fifo_8_rx_inst (
|
||||
.clock(sys.clk),
|
||||
.sclr(rx_flush),
|
||||
|
||||
.empty(rx_empty),
|
||||
// .almost_empty(rx_almost_empty),
|
||||
.rdreq(rx_read),
|
||||
.q(rx_rdata),
|
||||
|
||||
.full(rx_full),
|
||||
// .almost_full(rx_almost_full),
|
||||
.wrreq(rx_write),
|
||||
.data(rx_wdata)
|
||||
);
|
||||
@ -55,21 +50,18 @@ module usb_ft1248 (
|
||||
.q(tx_rdata),
|
||||
|
||||
.full(tx_full),
|
||||
// .almost_full(tx_almost_full),
|
||||
.wrreq(tx_write),
|
||||
.data(tx_wdata)
|
||||
);
|
||||
|
||||
|
||||
// FT1248 interface controller
|
||||
|
||||
// Constants definition
|
||||
|
||||
typedef enum bit [2:0] {
|
||||
S_TRY_RX = 3'b000,
|
||||
S_TRY_TX = 3'b001,
|
||||
S_COMMAND = 3'b100,
|
||||
S_DATA = 3'b101,
|
||||
S_END = 3'b111
|
||||
typedef enum bit [1:0] {
|
||||
S_TRY_RX,
|
||||
S_TRY_TX,
|
||||
S_COMMAND,
|
||||
S_DATA
|
||||
} e_state;
|
||||
|
||||
typedef enum bit [7:0] {
|
||||
@ -77,78 +69,103 @@ module usb_ft1248 (
|
||||
C_READ = 8'h04
|
||||
} e_command;
|
||||
|
||||
// FSM state
|
||||
typedef enum bit [1:0] {
|
||||
P_PRE_RISING,
|
||||
P_RISING,
|
||||
P_PRE_FALLING,
|
||||
P_FALLING
|
||||
} e_clock_phase;
|
||||
|
||||
e_state state;
|
||||
|
||||
// Clock divider and generator
|
||||
logic [3:0] clock_phase;
|
||||
|
||||
reg [3:0] clock_divider;
|
||||
wire rising_edge = clock_divider[1];
|
||||
logic usb_clk_output;
|
||||
logic usb_cs_output;
|
||||
logic [3:0] usb_miosi_input;
|
||||
logic [3:0] usb_miosi_output;
|
||||
logic [3:0] usb_miosi_output_data;
|
||||
logic usb_miosi_output_enable;
|
||||
logic usb_miosi_output_enable_data;
|
||||
logic usb_miso_input;
|
||||
logic usb_pwren_input;
|
||||
|
||||
logic is_cmd_write;
|
||||
logic [1:0] nibble_counter;
|
||||
logic [7:0] tx_buffer;
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
if (sys.reset || state == S_TRY_RX || state == S_TRY_TX) begin
|
||||
clock_divider <= 4'b0001;
|
||||
clock_phase <= 4'b0001;
|
||||
end else begin
|
||||
clock_divider <= {clock_divider[2:0], clock_divider[3]};
|
||||
clock_phase <= {clock_phase[2:0], clock_phase[3]};
|
||||
end
|
||||
end
|
||||
|
||||
// Output chip select and data register behavior
|
||||
always_ff @(posedge sys.clk) begin
|
||||
usb_clk <= usb_clk_output;
|
||||
usb_cs <= usb_cs_output;
|
||||
|
||||
reg [1:0] bit_counter;
|
||||
reg [7:0] tx_buffer;
|
||||
usb_miosi_input <= usb_miosi;
|
||||
usb_miosi_output <= usb_miosi_output_data;
|
||||
usb_miosi_output_enable <= usb_miosi_output_enable_data;
|
||||
|
||||
usb_miso_input <= usb_miso;
|
||||
usb_pwren_input <= usb_pwren;
|
||||
|
||||
wire clk_data;
|
||||
reg cs_data;
|
||||
wire [3:0] miosi_data;
|
||||
reg miosi_output_enable_data;
|
||||
|
||||
reg clk_output;
|
||||
reg cs_output;
|
||||
reg [3:0] miosi_input;
|
||||
reg [3:0] miosi_output;
|
||||
reg miosi_output_enable;
|
||||
reg miso_input;
|
||||
tx_buffer <= tx_rdata;
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
clk_data = 1'b0;
|
||||
if (state == S_COMMAND || state == S_DATA) clk_data = (clock_divider[2] | clock_divider[3]);
|
||||
usb_clk = clk_output;
|
||||
usb_cs = cs_output;
|
||||
miosi_data = bit_counter[0] ? tx_buffer[3:0] : tx_buffer[7:4];
|
||||
usb_miosi = miosi_output_enable ? miosi_output : 4'bZZZZ;
|
||||
usb_miosi = usb_miosi_output_enable ? usb_miosi_output : 4'bZZZZ;
|
||||
end
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
clk_output <= clk_data;
|
||||
cs_output <= cs_data;
|
||||
miosi_input <= usb_miosi;
|
||||
miosi_output <= miosi_data;
|
||||
miosi_output_enable <= miosi_output_enable_data;
|
||||
miso_input <= usb_miso;
|
||||
always_comb begin
|
||||
case (state)
|
||||
S_COMMAND: begin
|
||||
usb_clk_output = clock_phase[P_PRE_FALLING] || clock_phase[P_FALLING];
|
||||
usb_cs_output = 1'b0;
|
||||
if (is_cmd_write) begin
|
||||
usb_miosi_output_data = nibble_counter[0] ? C_WRITE[3:0] : C_WRITE[7:4];
|
||||
end else begin
|
||||
usb_miosi_output_data = nibble_counter[0] ? C_READ[3:0] : C_READ[7:4];
|
||||
end
|
||||
usb_miosi_output_enable_data = nibble_counter < 2'd2;
|
||||
end
|
||||
|
||||
S_DATA: begin
|
||||
usb_clk_output = clock_phase[P_PRE_FALLING] || clock_phase[P_FALLING];
|
||||
usb_cs_output = 1'b0;
|
||||
usb_miosi_output_data = nibble_counter[0] ? tx_buffer[7:4] : tx_buffer[3:0];
|
||||
usb_miosi_output_enable_data = is_cmd_write;
|
||||
end
|
||||
|
||||
default: begin
|
||||
usb_clk_output = 1'b0;
|
||||
usb_cs_output = 1'b1;
|
||||
usb_miosi_output_data = 4'hF;
|
||||
usb_miosi_output_enable_data = 1'b0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
// FSM
|
||||
|
||||
reg is_write;
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
rx_write <= 1'b0;
|
||||
tx_read <= 1'b0;
|
||||
|
||||
if (clock_phase[P_RISING]) begin
|
||||
nibble_counter <= nibble_counter + 1'd1;
|
||||
end
|
||||
|
||||
if (sys.reset) begin
|
||||
state <= S_TRY_RX;
|
||||
cs_data <= 1'b1;
|
||||
miosi_output_enable_data <= 1'b0;
|
||||
end else begin
|
||||
case (state)
|
||||
S_TRY_RX: begin
|
||||
if (!rx_full) begin
|
||||
state <= S_COMMAND;
|
||||
tx_buffer <= C_READ;
|
||||
bit_counter <= 2'b11;
|
||||
is_write <= 1'b0;
|
||||
is_cmd_write <= 1'b0;
|
||||
nibble_counter <= 2'b11;
|
||||
end else begin
|
||||
state <= S_TRY_TX;
|
||||
end
|
||||
@ -157,71 +174,45 @@ module usb_ft1248 (
|
||||
S_TRY_TX: begin
|
||||
if (!tx_empty) begin
|
||||
state <= S_COMMAND;
|
||||
tx_buffer <= C_WRITE;
|
||||
bit_counter <= 2'b11;
|
||||
is_write <= 1'b1;
|
||||
is_cmd_write <= 1'b1;
|
||||
nibble_counter <= 2'b11;
|
||||
end else begin
|
||||
state <= S_TRY_RX;
|
||||
end
|
||||
end
|
||||
|
||||
S_COMMAND: begin
|
||||
cs_data <= 1'b0;
|
||||
if (rising_edge) begin
|
||||
bit_counter <= bit_counter + 1'd1;
|
||||
miosi_output_enable_data <= 1'b1;
|
||||
if (bit_counter == 2'd1) begin
|
||||
miosi_output_enable_data <= 1'b0;
|
||||
end
|
||||
if (bit_counter == 2'd2) begin
|
||||
if (!miso_input) begin
|
||||
state <= S_DATA;
|
||||
bit_counter <= 2'b11;
|
||||
tx_buffer <= tx_rdata;
|
||||
miosi_output_enable_data <= is_write;
|
||||
if (clock_phase[P_RISING]) begin
|
||||
if (nibble_counter == 2'd2) begin
|
||||
if (usb_miso_input) begin
|
||||
state <= is_cmd_write ? S_TRY_RX : S_TRY_TX;
|
||||
end else begin
|
||||
state <= S_END;
|
||||
miosi_output_enable_data <= 1'b0;
|
||||
state <= S_DATA;
|
||||
nibble_counter <= 2'd0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
S_DATA: begin
|
||||
if (rising_edge) begin
|
||||
bit_counter <= {1'b0, ~bit_counter[0]};
|
||||
miosi_output_enable_data <= is_write;
|
||||
rx_wdata <= {miosi_input, rx_wdata[7:4]};
|
||||
if (bit_counter == 1'd1) begin
|
||||
tx_buffer <= tx_rdata;
|
||||
if (clock_phase[P_FALLING]) begin
|
||||
if (nibble_counter[0]) begin
|
||||
tx_read <= is_cmd_write;
|
||||
end
|
||||
if (!is_write && (bit_counter[0] == 1'd0)) begin
|
||||
rx_write <= 1'b1;
|
||||
end
|
||||
if (clock_phase[P_RISING]) begin
|
||||
rx_wdata <= {usb_miosi_input, rx_wdata[7:4]};
|
||||
if (nibble_counter[0]) begin
|
||||
rx_write <= !is_cmd_write;
|
||||
end
|
||||
if (is_write && (bit_counter[0] == 1'd1)) begin
|
||||
tx_read <= 1'b1;
|
||||
end
|
||||
if (
|
||||
(bit_counter[0] == 1'd1 && miso_input) ||
|
||||
(bit_counter[0] == 1'd0 && (
|
||||
(is_write && tx_empty) ||
|
||||
(!is_write && rx_almost_full)
|
||||
))) begin
|
||||
state <= S_END;
|
||||
miosi_output_enable_data <= 1'b0;
|
||||
if (usb_miso_input || (!is_cmd_write && rx_full) || (is_cmd_write && tx_empty)) begin
|
||||
state <= is_cmd_write ? S_TRY_RX : S_TRY_TX;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
S_END: begin
|
||||
cs_data <= 1'b1;
|
||||
state <= is_write ? S_TRY_RX : S_TRY_TX;
|
||||
end
|
||||
|
||||
default: begin
|
||||
state <= S_TRY_RX;
|
||||
cs_data <= 1'b1;
|
||||
miosi_output_enable_data <= 1'b0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
1605
fw/stp.stp
1605
fw/stp.stp
File diff suppressed because one or more lines are too long
@ -1,91 +0,0 @@
|
||||
module device_arbiter #(
|
||||
parameter NUM_CONTROLLERS = 2,
|
||||
parameter ADDRESS_WIDTH = 26,
|
||||
parameter [3:0] DEVICE_BANK = 4'd0,
|
||||
parameter ACK_FIFO_LENGTH = 4
|
||||
) (
|
||||
input i_clk,
|
||||
input i_reset,
|
||||
|
||||
input [(NUM_CONTROLLERS - 1):0] i_request,
|
||||
input [(NUM_CONTROLLERS - 1):0] i_write,
|
||||
output reg [(NUM_CONTROLLERS - 1):0] o_busy,
|
||||
output reg [(NUM_CONTROLLERS - 1):0] o_ack,
|
||||
input [((NUM_CONTROLLERS * 4) - 1):0] i_bank,
|
||||
input [((NUM_CONTROLLERS * ADDRESS_WIDTH) - 1):0] i_address,
|
||||
output reg [((NUM_CONTROLLERS * 32) - 1):0] o_data,
|
||||
input [((NUM_CONTROLLERS * 32) - 1):0] i_data,
|
||||
|
||||
output reg o_device_request,
|
||||
output reg o_device_write,
|
||||
input i_device_busy,
|
||||
input i_device_ack,
|
||||
output reg [(ADDRESS_WIDTH - 1):0] o_device_address,
|
||||
input [31:0] i_device_data,
|
||||
output reg [31:0] o_device_data
|
||||
);
|
||||
|
||||
localparam FIFO_ADDRESS_WIDTH = $clog2(ACK_FIFO_LENGTH);
|
||||
|
||||
reg [(NUM_CONTROLLERS - 1):0] r_request;
|
||||
reg [(NUM_CONTROLLERS - 1):0] r_request_successful;
|
||||
|
||||
reg [(NUM_CONTROLLERS - 1):0] r_ack_fifo_mem [0:(ACK_FIFO_LENGTH - 1)];
|
||||
|
||||
reg [FIFO_ADDRESS_WIDTH:0] r_ack_fifo_wrptr;
|
||||
reg [FIFO_ADDRESS_WIDTH:0] r_ack_fifo_rdptr;
|
||||
|
||||
wire w_ack_fifo_wrreq = |(r_request_successful & ~i_write);
|
||||
wire w_ack_fifo_rdreq = i_device_ack;
|
||||
|
||||
wire w_empty = r_ack_fifo_wrptr[FIFO_ADDRESS_WIDTH] == r_ack_fifo_rdptr[FIFO_ADDRESS_WIDTH];
|
||||
wire w_full_or_empty = r_ack_fifo_wrptr[(FIFO_ADDRESS_WIDTH - 1):0] == r_ack_fifo_rdptr[(FIFO_ADDRESS_WIDTH - 1):0];
|
||||
|
||||
wire w_ack_fifo_full = !w_empty && w_full_or_empty;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_reset) begin
|
||||
r_ack_fifo_wrptr <= {(FIFO_ADDRESS_WIDTH + 1){1'b0}};
|
||||
r_ack_fifo_rdptr <= {(FIFO_ADDRESS_WIDTH + 1){1'b0}};
|
||||
end else begin
|
||||
if (w_ack_fifo_wrreq) begin
|
||||
r_ack_fifo_mem[r_ack_fifo_wrptr[(FIFO_ADDRESS_WIDTH - 1):0]] <= r_request_successful & ~i_write;
|
||||
r_ack_fifo_wrptr <= r_ack_fifo_wrptr + 1'd1;
|
||||
end
|
||||
if (w_ack_fifo_rdreq) begin
|
||||
r_ack_fifo_rdptr <= r_ack_fifo_rdptr + 1'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(*) begin
|
||||
for (integer i = 0; i < NUM_CONTROLLERS; i = i + 1) begin
|
||||
r_request[i] = i_request[i] && i_bank[(i * 4) +: 4] == DEVICE_BANK;
|
||||
o_busy[i] = r_request[i] && (
|
||||
i_device_busy ||
|
||||
|(r_request & (({{(NUM_CONTROLLERS - 1){1'b0}}, 1'b1} << i) - 1)) ||
|
||||
(!i_write[i] && w_ack_fifo_full)
|
||||
);
|
||||
end
|
||||
|
||||
r_request_successful = r_request & ~o_busy;
|
||||
o_ack = {NUM_CONTROLLERS{i_device_ack}} & r_ack_fifo_mem[r_ack_fifo_rdptr[(FIFO_ADDRESS_WIDTH - 1):0]];
|
||||
o_data = {NUM_CONTROLLERS{i_device_data}};
|
||||
end
|
||||
|
||||
always @(*) begin
|
||||
o_device_request = |r_request;
|
||||
o_device_write = 1'b0;
|
||||
o_device_address = {ADDRESS_WIDTH{1'b0}};
|
||||
o_device_data = 32'h0000_0000;
|
||||
|
||||
for (integer i = (NUM_CONTROLLERS - 1); i >= 0 ; i = i - 1) begin
|
||||
if (r_request[i]) begin
|
||||
o_device_write = i_write[i];
|
||||
o_device_address = i_address[(i * ADDRESS_WIDTH) +: ADDRESS_WIDTH];
|
||||
o_device_data = i_data[(i * 32) +: 32];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
@ -1,4 +0,0 @@
|
||||
set_global_assignment -name IP_TOOL_NAME "FIFO"
|
||||
set_global_assignment -name IP_TOOL_VERSION "20.1"
|
||||
set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{MAX 10}"
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "fifo8.v"]
|
@ -1,179 +0,0 @@
|
||||
// megafunction wizard: %FIFO%
|
||||
// GENERATION: STANDARD
|
||||
// VERSION: WM1.0
|
||||
// MODULE: scfifo
|
||||
|
||||
// ============================================================
|
||||
// File Name: fifo8.v
|
||||
// Megafunction Name(s):
|
||||
// scfifo
|
||||
//
|
||||
// Simulation Library Files(s):
|
||||
// altera_mf
|
||||
// ============================================================
|
||||
// ************************************************************
|
||||
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
|
||||
//
|
||||
// 20.1.1 Build 720 11/11/2020 SJ Lite Edition
|
||||
// ************************************************************
|
||||
|
||||
|
||||
//Copyright (C) 2020 Intel Corporation. All rights reserved.
|
||||
//Your use of Intel Corporation's design tools, logic functions
|
||||
//and other software and tools, and any partner logic
|
||||
//functions, and any output files from any of the foregoing
|
||||
//(including device programming or simulation files), and any
|
||||
//associated documentation or information are expressly subject
|
||||
//to the terms and conditions of the Intel Program License
|
||||
//Subscription Agreement, the Intel Quartus Prime License Agreement,
|
||||
//the Intel FPGA IP License Agreement, or other applicable license
|
||||
//agreement, including, without limitation, that your use is for
|
||||
//the sole purpose of programming logic devices manufactured by
|
||||
//Intel and sold by Intel or its authorized distributors. Please
|
||||
//refer to the applicable agreement for further details, at
|
||||
//https://fpgasoftware.intel.com/eula.
|
||||
|
||||
|
||||
// synopsys translate_off
|
||||
`timescale 1 ps / 1 ps
|
||||
// synopsys translate_on
|
||||
module fifo8 (
|
||||
clock,
|
||||
data,
|
||||
rdreq,
|
||||
sclr,
|
||||
wrreq,
|
||||
almost_empty,
|
||||
almost_full,
|
||||
empty,
|
||||
full,
|
||||
q);
|
||||
|
||||
input clock;
|
||||
input [7:0] data;
|
||||
input rdreq;
|
||||
input sclr;
|
||||
input wrreq;
|
||||
output almost_empty;
|
||||
output almost_full;
|
||||
output empty;
|
||||
output full;
|
||||
output [7:0] q;
|
||||
|
||||
wire sub_wire0;
|
||||
wire sub_wire1;
|
||||
wire sub_wire2;
|
||||
wire sub_wire3;
|
||||
wire [7:0] sub_wire4;
|
||||
wire almost_empty = sub_wire0;
|
||||
wire almost_full = sub_wire1;
|
||||
wire empty = sub_wire2;
|
||||
wire full = sub_wire3;
|
||||
wire [7:0] q = sub_wire4[7:0];
|
||||
|
||||
scfifo scfifo_component (
|
||||
.clock (clock),
|
||||
.data (data),
|
||||
.rdreq (rdreq),
|
||||
.sclr (sclr),
|
||||
.wrreq (wrreq),
|
||||
.almost_empty (sub_wire0),
|
||||
.almost_full (sub_wire1),
|
||||
.empty (sub_wire2),
|
||||
.full (sub_wire3),
|
||||
.q (sub_wire4),
|
||||
.aclr (),
|
||||
.eccstatus (),
|
||||
.usedw ());
|
||||
defparam
|
||||
scfifo_component.add_ram_output_register = "ON",
|
||||
scfifo_component.almost_empty_value = 2,
|
||||
scfifo_component.almost_full_value = 1023,
|
||||
scfifo_component.intended_device_family = "MAX 10",
|
||||
scfifo_component.lpm_numwords = 1024,
|
||||
scfifo_component.lpm_showahead = "ON",
|
||||
scfifo_component.lpm_type = "scfifo",
|
||||
scfifo_component.lpm_width = 8,
|
||||
scfifo_component.lpm_widthu = 10,
|
||||
scfifo_component.overflow_checking = "ON",
|
||||
scfifo_component.underflow_checking = "ON",
|
||||
scfifo_component.use_eab = "ON";
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
// ============================================================
|
||||
// CNX file retrieval info
|
||||
// ============================================================
|
||||
// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "2"
|
||||
// Retrieval info: PRIVATE: AlmostFull NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "1023"
|
||||
// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: Clock NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: Depth NUMERIC "1024"
|
||||
// Retrieval info: PRIVATE: Empty NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: Full NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "MAX 10"
|
||||
// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: Optimize NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
|
||||
// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: UsedW NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: Width NUMERIC "8"
|
||||
// Retrieval info: PRIVATE: dc_aclr NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: diff_widths NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: msb_usedw NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: output_width NUMERIC "8"
|
||||
// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: rsFull NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: sc_aclr NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: sc_sclr NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: wsEmpty NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: wsFull NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"
|
||||
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
|
||||
// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "ON"
|
||||
// Retrieval info: CONSTANT: ALMOST_EMPTY_VALUE NUMERIC "2"
|
||||
// Retrieval info: CONSTANT: ALMOST_FULL_VALUE NUMERIC "1023"
|
||||
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "MAX 10"
|
||||
// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "1024"
|
||||
// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "ON"
|
||||
// Retrieval info: CONSTANT: LPM_TYPE STRING "scfifo"
|
||||
// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "8"
|
||||
// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "10"
|
||||
// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
|
||||
// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
|
||||
// Retrieval info: CONSTANT: USE_EAB STRING "ON"
|
||||
// Retrieval info: USED_PORT: almost_empty 0 0 0 0 OUTPUT NODEFVAL "almost_empty"
|
||||
// Retrieval info: USED_PORT: almost_full 0 0 0 0 OUTPUT NODEFVAL "almost_full"
|
||||
// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL "clock"
|
||||
// Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL "data[7..0]"
|
||||
// Retrieval info: USED_PORT: empty 0 0 0 0 OUTPUT NODEFVAL "empty"
|
||||
// Retrieval info: USED_PORT: full 0 0 0 0 OUTPUT NODEFVAL "full"
|
||||
// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]"
|
||||
// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL "rdreq"
|
||||
// Retrieval info: USED_PORT: sclr 0 0 0 0 INPUT NODEFVAL "sclr"
|
||||
// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL "wrreq"
|
||||
// Retrieval info: CONNECT: @clock 0 0 0 0 clock 0 0 0 0
|
||||
// Retrieval info: CONNECT: @data 0 0 8 0 data 0 0 8 0
|
||||
// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0
|
||||
// Retrieval info: CONNECT: @sclr 0 0 0 0 sclr 0 0 0 0
|
||||
// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0
|
||||
// Retrieval info: CONNECT: almost_empty 0 0 0 0 @almost_empty 0 0 0 0
|
||||
// Retrieval info: CONNECT: almost_full 0 0 0 0 @almost_full 0 0 0 0
|
||||
// Retrieval info: CONNECT: empty 0 0 0 0 @empty 0 0 0 0
|
||||
// Retrieval info: CONNECT: full 0 0 0 0 @full 0 0 0 0
|
||||
// Retrieval info: CONNECT: q 0 0 8 0 @q 0 0 8 0
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo8.v TRUE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo8.inc FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo8.cmp FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo8.bsf FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo8_inst.v FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo8_bb.v FALSE
|
||||
// Retrieval info: LIB_FILE: altera_mf
|
@ -1,445 +0,0 @@
|
||||
-- __ __ __ __ __ __
|
||||
-- /\ "-.\ \ /\ \/\ \ /\ \ /\ \
|
||||
-- \ \ \-. \ \ \ \_\ \ \ \ \____ \ \ \____
|
||||
-- \ \_\\"\_\ \ \_____\ \ \_____\ \ \_____\
|
||||
-- \/_/ \/_/ \/_____/ \/_____/ \/_____/
|
||||
-- ______ ______ __ ______ ______ ______
|
||||
-- /\ __ \ /\ == \ /\ \ /\ ___\ /\ ___\ /\__ _\
|
||||
-- \ \ \/\ \ \ \ __< _\_\ \ \ \ __\ \ \ \____ \/_/\ \/
|
||||
-- \ \_____\ \ \_____\ /\_____\ \ \_____\ \ \_____\ \ \_\
|
||||
-- \/_____/ \/_____/ \/_____/ \/_____/ \/_____/ \/_/
|
||||
--
|
||||
-- https://joshbassett.info
|
||||
-- https://twitter.com/nullobject
|
||||
-- https://github.com/nullobject
|
||||
--
|
||||
-- Copyright (c) 2020 Josh Bassett
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
-- of this software and associated documentation files (the "Software"), to deal
|
||||
-- in the Software without restriction, including without limitation the rights
|
||||
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
-- copies of the Software, and to permit persons to whom the Software is
|
||||
-- furnished to do so, subject to the following conditions:
|
||||
--
|
||||
-- The above copyright notice and this permission notice shall be included in all
|
||||
-- copies or substantial portions of the Software.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
-- SOFTWARE.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.math_real.all;
|
||||
|
||||
-- This SDRAM controller provides a symmetric 32-bit synchronous read/write
|
||||
-- interface for a 16Mx16-bit SDRAM chip (e.g. AS4C16M16SA-6TCN, IS42S16400F,
|
||||
-- etc.).
|
||||
entity sdram is
|
||||
generic (
|
||||
-- clock frequency (in MHz)
|
||||
--
|
||||
-- This value must be provided, as it is used to calculate the number of
|
||||
-- clock cycles required for the other timing values.
|
||||
CLK_FREQ : real := 100.0;
|
||||
|
||||
-- 32-bit controller interface
|
||||
ADDR_WIDTH : natural := 25;
|
||||
DATA_WIDTH : natural := 32;
|
||||
|
||||
-- SDRAM interface
|
||||
SDRAM_ADDR_WIDTH : natural := 13;
|
||||
SDRAM_DATA_WIDTH : natural := 16;
|
||||
SDRAM_COL_WIDTH : natural := 10;
|
||||
SDRAM_ROW_WIDTH : natural := 13;
|
||||
SDRAM_BANK_WIDTH : natural := 2;
|
||||
|
||||
-- The delay in clock cycles, between the start of a read command and the
|
||||
-- availability of the output data.
|
||||
CAS_LATENCY : natural := 2; -- 2=below 133MHz, 3=above 133MHz
|
||||
|
||||
-- The number of 16-bit words to be bursted during a read/write.
|
||||
BURST_LENGTH : natural := 2;
|
||||
|
||||
-- timing values (in nanoseconds)
|
||||
--
|
||||
-- These values can be adjusted to match the exact timing of your SDRAM
|
||||
-- chip (refer to the datasheet).
|
||||
T_DESL : real := 100000.0; -- startup delay
|
||||
T_MRD : real := 14.0; -- mode register cycle time
|
||||
T_RC : real := 60.0; -- row cycle time
|
||||
T_RCD : real := 15.0; -- RAS to CAS delay
|
||||
T_RP : real := 15.0; -- precharge to activate delay
|
||||
T_WR : real := 22.0; -- write recovery time
|
||||
T_REFI : real := 7800.0 -- average refresh interval
|
||||
);
|
||||
port (
|
||||
-- reset
|
||||
reset : in std_logic := '0';
|
||||
|
||||
-- clock
|
||||
clk : in std_logic;
|
||||
|
||||
-- address bus
|
||||
addr : in unsigned(ADDR_WIDTH-1 downto 0);
|
||||
|
||||
-- input data bus
|
||||
data : in std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||
|
||||
-- When the write enable signal is asserted, a write operation will be performed.
|
||||
we : in std_logic;
|
||||
|
||||
-- When the request signal is asserted, an operation will be performed.
|
||||
req : in std_logic;
|
||||
|
||||
-- The acknowledge signal is asserted by the SDRAM controller when
|
||||
-- a request has been accepted.
|
||||
ack : out std_logic;
|
||||
|
||||
-- The valid signal is asserted when there is a valid word on the output
|
||||
-- data bus.
|
||||
valid : out std_logic;
|
||||
|
||||
-- output data bus
|
||||
q : out std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||
|
||||
-- SDRAM interface (e.g. AS4C16M16SA-6TCN, IS42S16400F, etc.)
|
||||
sdram_a : out unsigned(SDRAM_ADDR_WIDTH-1 downto 0);
|
||||
sdram_ba : out unsigned(SDRAM_BANK_WIDTH-1 downto 0);
|
||||
sdram_dq : inout std_logic_vector(SDRAM_DATA_WIDTH-1 downto 0);
|
||||
sdram_cke : out std_logic;
|
||||
sdram_cs_n : out std_logic;
|
||||
sdram_ras_n : out std_logic;
|
||||
sdram_cas_n : out std_logic;
|
||||
sdram_we_n : out std_logic;
|
||||
sdram_dqml : out std_logic;
|
||||
sdram_dqmh : out std_logic
|
||||
);
|
||||
end sdram;
|
||||
|
||||
architecture arch of sdram is
|
||||
function ilog2(n : natural) return natural is
|
||||
begin
|
||||
return natural(ceil(log2(real(n))));
|
||||
end ilog2;
|
||||
|
||||
subtype command_t is std_logic_vector(3 downto 0);
|
||||
|
||||
-- commands
|
||||
constant CMD_DESELECT : command_t := "1---";
|
||||
constant CMD_LOAD_MODE : command_t := "0000";
|
||||
constant CMD_AUTO_REFRESH : command_t := "0001";
|
||||
constant CMD_PRECHARGE : command_t := "0010";
|
||||
constant CMD_ACTIVE : command_t := "0011";
|
||||
constant CMD_WRITE : command_t := "0100";
|
||||
constant CMD_READ : command_t := "0101";
|
||||
constant CMD_STOP : command_t := "0110";
|
||||
constant CMD_NOP : command_t := "0111";
|
||||
|
||||
-- the ordering of the accesses within a burst
|
||||
constant BURST_TYPE : std_logic := '0'; -- 0=sequential, 1=interleaved
|
||||
|
||||
-- the write burst mode enables bursting for write operations
|
||||
constant WRITE_BURST_MODE : std_logic := '0'; -- 0=burst, 1=single
|
||||
|
||||
-- the value written to the mode register to configure the memory
|
||||
constant MODE_REG : unsigned(SDRAM_ADDR_WIDTH-1 downto 0) := (
|
||||
"000" &
|
||||
WRITE_BURST_MODE &
|
||||
"00" &
|
||||
to_unsigned(CAS_LATENCY, 3) &
|
||||
BURST_TYPE &
|
||||
to_unsigned(ilog2(BURST_LENGTH), 3)
|
||||
);
|
||||
|
||||
-- calculate the clock period (in nanoseconds)
|
||||
constant CLK_PERIOD : real := 1.0/CLK_FREQ*1000.0;
|
||||
|
||||
-- the number of clock cycles to wait before initialising the device
|
||||
constant INIT_WAIT : natural := natural(ceil(T_DESL/CLK_PERIOD));
|
||||
|
||||
-- the number of clock cycles to wait while a LOAD MODE command is being
|
||||
-- executed
|
||||
constant LOAD_MODE_WAIT : natural := natural(ceil(T_MRD/CLK_PERIOD));
|
||||
|
||||
-- the number of clock cycles to wait while an ACTIVE command is being
|
||||
-- executed
|
||||
constant ACTIVE_WAIT : natural := natural(ceil(T_RCD/CLK_PERIOD));
|
||||
|
||||
-- the number of clock cycles to wait while a REFRESH command is being
|
||||
-- executed
|
||||
constant REFRESH_WAIT : natural := natural(ceil(T_RC/CLK_PERIOD));
|
||||
|
||||
-- the number of clock cycles to wait while a PRECHARGE command is being
|
||||
-- executed
|
||||
constant PRECHARGE_WAIT : natural := natural(ceil(T_RP/CLK_PERIOD));
|
||||
|
||||
-- the number of clock cycles to wait while a READ command is being executed
|
||||
constant READ_WAIT : natural := CAS_LATENCY+BURST_LENGTH;
|
||||
|
||||
-- the number of clock cycles to wait while a WRITE command is being executed
|
||||
constant WRITE_WAIT : natural := BURST_LENGTH+natural(ceil((T_WR+T_RP)/CLK_PERIOD));
|
||||
|
||||
-- the number of clock cycles before the memory controller needs to refresh
|
||||
-- the SDRAM
|
||||
constant REFRESH_INTERVAL : natural := natural(floor(T_REFI/CLK_PERIOD))-10;
|
||||
|
||||
type state_t is (INIT, MODE, IDLE, ACTIVE, READ, WRITE, REFRESH);
|
||||
|
||||
-- state signals
|
||||
signal state, next_state : state_t;
|
||||
|
||||
-- command signals
|
||||
signal cmd, next_cmd : command_t := CMD_NOP;
|
||||
|
||||
-- control signals
|
||||
signal start : std_logic;
|
||||
signal load_mode_done : std_logic;
|
||||
signal active_done : std_logic;
|
||||
signal refresh_done : std_logic;
|
||||
signal first_word : std_logic;
|
||||
signal read_done : std_logic;
|
||||
signal write_done : std_logic;
|
||||
signal should_refresh : std_logic;
|
||||
|
||||
-- counters
|
||||
signal wait_counter : natural range 0 to 16383;
|
||||
signal refresh_counter : natural range 0 to 1023;
|
||||
|
||||
-- registers
|
||||
signal addr_reg : unsigned(SDRAM_COL_WIDTH+SDRAM_ROW_WIDTH+SDRAM_BANK_WIDTH-1 downto 0);
|
||||
signal data_reg : std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||
signal we_reg : std_logic;
|
||||
signal q_reg : std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||
|
||||
-- aliases to decode the address register
|
||||
alias col : unsigned(SDRAM_COL_WIDTH-1 downto 0) is addr_reg(SDRAM_COL_WIDTH-1 downto 0);
|
||||
alias row : unsigned(SDRAM_ROW_WIDTH-1 downto 0) is addr_reg(SDRAM_COL_WIDTH+SDRAM_ROW_WIDTH-1 downto SDRAM_COL_WIDTH);
|
||||
alias bank : unsigned(SDRAM_BANK_WIDTH-1 downto 0) is addr_reg(SDRAM_COL_WIDTH+SDRAM_ROW_WIDTH+SDRAM_BANK_WIDTH-1 downto SDRAM_COL_WIDTH+SDRAM_ROW_WIDTH);
|
||||
begin
|
||||
-- state machine
|
||||
fsm : process (state, wait_counter, req, we_reg, load_mode_done, active_done, refresh_done, read_done, write_done, should_refresh)
|
||||
begin
|
||||
next_state <= state;
|
||||
|
||||
-- default to a NOP command
|
||||
next_cmd <= CMD_NOP;
|
||||
|
||||
case state is
|
||||
-- execute the initialisation sequence
|
||||
when INIT =>
|
||||
if wait_counter = 0 then
|
||||
next_cmd <= CMD_DESELECT;
|
||||
elsif wait_counter = INIT_WAIT-1 then
|
||||
next_cmd <= CMD_PRECHARGE;
|
||||
elsif wait_counter = INIT_WAIT+PRECHARGE_WAIT-1 then
|
||||
next_cmd <= CMD_AUTO_REFRESH;
|
||||
elsif wait_counter = INIT_WAIT+PRECHARGE_WAIT+REFRESH_WAIT-1 then
|
||||
next_cmd <= CMD_AUTO_REFRESH;
|
||||
elsif wait_counter = INIT_WAIT+PRECHARGE_WAIT+REFRESH_WAIT+REFRESH_WAIT-1 then
|
||||
next_state <= MODE;
|
||||
next_cmd <= CMD_LOAD_MODE;
|
||||
end if;
|
||||
|
||||
-- load the mode register
|
||||
when MODE =>
|
||||
if load_mode_done = '1' then
|
||||
next_state <= IDLE;
|
||||
end if;
|
||||
|
||||
-- wait for a read/write request
|
||||
when IDLE =>
|
||||
if should_refresh = '1' then
|
||||
next_state <= REFRESH;
|
||||
next_cmd <= CMD_AUTO_REFRESH;
|
||||
elsif req = '1' then
|
||||
next_state <= ACTIVE;
|
||||
next_cmd <= CMD_ACTIVE;
|
||||
end if;
|
||||
|
||||
-- activate the row
|
||||
when ACTIVE =>
|
||||
if active_done = '1' then
|
||||
if we_reg = '1' then
|
||||
next_state <= WRITE;
|
||||
next_cmd <= CMD_WRITE;
|
||||
else
|
||||
next_state <= READ;
|
||||
next_cmd <= CMD_READ;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- execute a read command
|
||||
when READ =>
|
||||
if read_done = '1' then
|
||||
if should_refresh = '1' then
|
||||
next_state <= REFRESH;
|
||||
next_cmd <= CMD_AUTO_REFRESH;
|
||||
elsif req = '1' then
|
||||
next_state <= ACTIVE;
|
||||
next_cmd <= CMD_ACTIVE;
|
||||
else
|
||||
next_state <= IDLE;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- execute a write command
|
||||
when WRITE =>
|
||||
if write_done = '1' then
|
||||
if should_refresh = '1' then
|
||||
next_state <= REFRESH;
|
||||
next_cmd <= CMD_AUTO_REFRESH;
|
||||
elsif req = '1' then
|
||||
next_state <= ACTIVE;
|
||||
next_cmd <= CMD_ACTIVE;
|
||||
else
|
||||
next_state <= IDLE;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- execute an auto refresh
|
||||
when REFRESH =>
|
||||
if refresh_done = '1' then
|
||||
if req = '1' then
|
||||
next_state <= ACTIVE;
|
||||
next_cmd <= CMD_ACTIVE;
|
||||
else
|
||||
next_state <= IDLE;
|
||||
end if;
|
||||
end if;
|
||||
end case;
|
||||
end process;
|
||||
|
||||
-- latch the next state
|
||||
latch_next_state : process (clk, reset)
|
||||
begin
|
||||
if reset = '1' then
|
||||
state <= INIT;
|
||||
cmd <= CMD_NOP;
|
||||
elsif rising_edge(clk) then
|
||||
state <= next_state;
|
||||
cmd <= next_cmd;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- the wait counter is used to hold the current state for a number of clock
|
||||
-- cycles
|
||||
update_wait_counter : process (clk, reset)
|
||||
begin
|
||||
if reset = '1' then
|
||||
wait_counter <= 0;
|
||||
elsif rising_edge(clk) then
|
||||
if state /= next_state then -- state changing
|
||||
wait_counter <= 0;
|
||||
else
|
||||
wait_counter <= wait_counter + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- the refresh counter is used to periodically trigger a refresh operation
|
||||
update_refresh_counter : process (clk, reset)
|
||||
begin
|
||||
if reset = '1' then
|
||||
refresh_counter <= 0;
|
||||
elsif rising_edge(clk) then
|
||||
if state = REFRESH and wait_counter = 0 then
|
||||
refresh_counter <= 0;
|
||||
else
|
||||
refresh_counter <= refresh_counter + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- latch the rquest
|
||||
latch_request : process (clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if start = '1' then
|
||||
-- we need to multiply the address by two, because we are converting
|
||||
-- from a 32-bit controller address to a 16-bit SDRAM address
|
||||
addr_reg <= shift_left(resize(addr, addr_reg'length), 1);
|
||||
data_reg <= data;
|
||||
we_reg <= we;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- latch the output data as it's bursted from the SDRAM
|
||||
latch_sdram_data : process (clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
valid <= '0';
|
||||
|
||||
if state = READ then
|
||||
if first_word = '1' then
|
||||
q_reg(31 downto 16) <= sdram_dq;
|
||||
elsif read_done = '1' then
|
||||
q_reg(15 downto 0) <= sdram_dq;
|
||||
valid <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- set wait signals
|
||||
load_mode_done <= '1' when wait_counter = LOAD_MODE_WAIT-1 else '0';
|
||||
active_done <= '1' when wait_counter = ACTIVE_WAIT-1 else '0';
|
||||
refresh_done <= '1' when wait_counter = REFRESH_WAIT-1 else '0';
|
||||
first_word <= '1' when wait_counter = CAS_LATENCY else '0';
|
||||
read_done <= '1' when wait_counter = READ_WAIT-1 else '0';
|
||||
write_done <= '1' when wait_counter = WRITE_WAIT-1 else '0';
|
||||
|
||||
-- the SDRAM should be refreshed when the refresh interval has elapsed
|
||||
should_refresh <= '1' when refresh_counter >= REFRESH_INTERVAL-1 else '0';
|
||||
|
||||
-- a new request is only allowed at the end of the IDLE, READ, WRITE, and
|
||||
-- REFRESH states
|
||||
start <= '1' when (state = IDLE) or
|
||||
(state = READ and read_done = '1') or
|
||||
(state = WRITE and write_done = '1') or
|
||||
(state = REFRESH and refresh_done = '1') else '0';
|
||||
|
||||
-- assert the acknowledge signal at the beginning of the ACTIVE state
|
||||
ack <= '1' when state = ACTIVE and wait_counter = 0 else '0';
|
||||
|
||||
-- set output data
|
||||
q <= q_reg;
|
||||
|
||||
-- deassert the clock enable at the beginning of the INIT state
|
||||
sdram_cke <= '0' when state = INIT and wait_counter = 0 else '1';
|
||||
|
||||
-- set SDRAM control signals
|
||||
(sdram_cs_n, sdram_ras_n, sdram_cas_n, sdram_we_n) <= cmd;
|
||||
|
||||
-- set SDRAM bank
|
||||
with state select
|
||||
sdram_ba <=
|
||||
bank when ACTIVE,
|
||||
bank when READ,
|
||||
bank when WRITE,
|
||||
(others => '0') when others;
|
||||
|
||||
-- set SDRAM address
|
||||
with state select
|
||||
sdram_a <=
|
||||
"0010000000000" when INIT,
|
||||
MODE_REG when MODE,
|
||||
row when ACTIVE,
|
||||
"0010" & col when READ, -- auto precharge
|
||||
"0010" & col when WRITE, -- auto precharge
|
||||
(others => '0') when others;
|
||||
|
||||
-- decode the next 16-bit word from the write buffer
|
||||
sdram_dq <= data_reg((BURST_LENGTH-wait_counter)*SDRAM_DATA_WIDTH-1 downto (BURST_LENGTH-wait_counter-1)*SDRAM_DATA_WIDTH) when state = WRITE else (others => 'Z');
|
||||
|
||||
-- set SDRAM data mask
|
||||
sdram_dqmh <= '0';
|
||||
sdram_dqml <= '0';
|
||||
end architecture arch;
|
@ -1,46 +0,0 @@
|
||||
module usb_fifo #(
|
||||
parameter FIFO_LENGTH = 1024,
|
||||
parameter FIFO_WIDTH = 8
|
||||
) (
|
||||
if_system.sys system_if,
|
||||
|
||||
input flush,
|
||||
|
||||
output full,
|
||||
input write,
|
||||
input [(FIFO_WIDTH - 1):0] wdata,
|
||||
|
||||
output empty,
|
||||
input read,
|
||||
output reg [(FIFO_WIDTH - 1):0] rdata
|
||||
);
|
||||
|
||||
localparam FIFO_ADDRESS_WIDTH = $clog2(FIFO_LENGTH);
|
||||
|
||||
reg [(FIFO_WIDTH - 1):0] r_fifo_mem [0:(FIFO_LENGTH - 1)];
|
||||
|
||||
reg [FIFO_ADDRESS_WIDTH:0] r_fifo_wrptr;
|
||||
reg [FIFO_ADDRESS_WIDTH:0] r_fifo_rdptr;
|
||||
|
||||
wire w_full_or_empty = r_fifo_wrptr[(FIFO_ADDRESS_WIDTH - 1):0] == r_fifo_rdptr[(FIFO_ADDRESS_WIDTH - 1):0];
|
||||
|
||||
assign empty = r_fifo_wrptr == r_fifo_rdptr;
|
||||
assign full = !empty && w_full_or_empty;
|
||||
|
||||
always_ff @(posedge system_if.clk) begin
|
||||
rdata <= r_fifo_mem[r_fifo_rdptr[(FIFO_ADDRESS_WIDTH - 1):0]];
|
||||
if (system_if.reset || flush) begin
|
||||
r_fifo_wrptr <= {(FIFO_ADDRESS_WIDTH + 1){1'b0}};
|
||||
r_fifo_rdptr <= {(FIFO_ADDRESS_WIDTH + 1){1'b0}};
|
||||
end else begin
|
||||
if (write) begin
|
||||
r_fifo_mem[r_fifo_wrptr[(FIFO_ADDRESS_WIDTH - 1):0]] <= wdata;
|
||||
r_fifo_wrptr <= r_fifo_wrptr + 1'd1;
|
||||
end
|
||||
if (read) begin
|
||||
r_fifo_rdptr <= r_fifo_rdptr + 1'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
Loading…
Reference in New Issue
Block a user