repo2/mcctv_5200/sdram_ctrl_4_ports.v
288 | markw | `timescale 1 ns / 1 ps
|
|
module sdram_ctrl /* verilator tracing_off */
|
|||
(
|
|||
//-----------------------------
|
|||
// Clock and reset
|
|||
//-----------------------------
|
|||
input rst, // Global reset
|
|||
input clk, // Master clock (72 MHz)
|
|||
output ram_rdy_n, // SDRAM ready
|
|||
output ram_ref, // SDRAM refresh
|
|||
output [3:0] ram_cyc, // SDRAM cycles
|
|||
output [3:0] ram_ph, // SDRAM phases
|
|||
output [8:0] ram_ph_ctr, // Phase counter
|
|||
//-----------------------------
|
|||
// Access bank #0
|
|||
//-----------------------------
|
|||
input rden_b0, // Read enable
|
|||
input wren_b0, // Write enable
|
|||
input [22:2] addr_b0, // Address (up to 8 MB)
|
|||
output valid_b0, // Read data valid
|
|||
output fetch_b0, // Write data fetch
|
|||
output [15:0] rdata_b0, // Read data
|
|||
input [15:0] wdata_b0, // Write data
|
|||
input [1:0] bena_b0, // Byte enable
|
|||
//-----------------------------
|
|||
// Access bank #1
|
|||
//-----------------------------
|
|||
input rden_b1, // Read enable
|
|||
input wren_b1, // Write enable
|
|||
input [22:2] addr_b1, // Address (up to 8 MB)
|
|||
output valid_b1, // Read data valid
|
|||
output fetch_b1, // Write data fetch
|
|||
output [15:0] rdata_b1, // Read data
|
|||
input [15:0] wdata_b1, // Write data
|
|||
input [1:0] bena_b1, // Byte enable
|
|||
//-----------------------------
|
|||
// Access bank #2
|
|||
//-----------------------------
|
|||
input rden_b2, // Read enable
|
|||
input wren_b2, // Write enable
|
|||
input [22:2] addr_b2, // Address (up to 8 MB)
|
|||
output valid_b2, // Read data valid
|
|||
output fetch_b2, // Write data fetch
|
|||
output [15:0] rdata_b2, // Read data
|
|||
input [15:0] wdata_b2, // Write data
|
|||
input [1:0] bena_b2, // Byte enable
|
|||
//-----------------------------
|
|||
// Access bank #3
|
|||
//-----------------------------
|
|||
input rden_b3, // Read enable
|
|||
input wren_b3, // Write enable
|
|||
input [22:2] addr_b3, // Address (up to 8 MB)
|
|||
output valid_b3, // Read data valid
|
|||
output fetch_b3, // Write data fetch
|
|||
output [15:0] rdata_b3, // Read data
|
|||
input [15:0] wdata_b3, // Write data
|
|||
input [1:0] bena_b3, // Byte enable
|
|||
//-----------------------------
|
|||
// SDRAM memory signals
|
|||
//-----------------------------
|
|||
output sdram_cs_n, // SDRAM chip select
|
|||
output reg sdram_ras_n, // SDRAM row address strobe
|
|||
output reg sdram_cas_n, // SDRAM column address strobe
|
|||
output reg sdram_we_n, // SDRAM write enable
|
|||
//
|
|||
output reg [1:0] sdram_ba, // SDRAM bank address
|
|||
output reg [12:0] sdram_addr, // SDRAM address
|
|||
//
|
|||
output reg [3:0] sdram_dqm_n, // SDRAM DQ masks
|
|||
output reg sdram_dq_oe, // SDRAM data output enable
|
|||
output reg [31:0] sdram_dq_o, // SDRAM data output
|
|||
input [31:0] sdram_dq_i // SDRAM data input
|
|||
);
|
|||
// SDRAM memory size (16 or 32 MB)
|
|||
parameter SDRAM_SIZE = 16;
|
|||
// SDRAM memory width (16 or 32 bits)
|
|||
parameter SDRAM_WIDTH = 16;
|
|||
// Clock-to-output delay (for simulation)
|
|||
parameter Tco_dly = 4.5;
|
|||
// SDRAM commands
|
|||
localparam [2:0]
|
|||
CMD_LMR = 3'b000,
|
|||
CMD_REF = 3'b001,
|
|||
CMD_PRE = 3'b010,
|
|||
CMD_ACT = 3'b011,
|
|||
CMD_WR = 3'b100,
|
|||
CMD_RD = 3'b101,
|
|||
CMD_BST = 3'b110,
|
|||
CMD_NOP = 3'b111;
|
|||
// ======================================================
|
|||
// SDRAM sequencer control
|
|||
// ======================================================
|
|||
reg [3:0] r_ram_cyc;
|
|||
reg [3:0] r_ram_ph;
|
|||
reg [1:0] r_ba0_ctr;
|
|||
reg [1:0] r_ba1_ctr;
|
|||
reg [8:0] r_ph_ctr;
|
|||
reg [2:0] r_ini_ctr;
|
|||
reg r_ref_ena;
|
|||
wire w_bus_eol;
|
|||
assign w_bus_eol = r_ph_ctr[8] & r_ph_ctr[5] & r_ram_ph[3]; // 288
|
|||
always@(posedge rst or posedge clk) begin : SEQUENCER_CTRL
|
|||
if (rst) begin
|
|||
r_ram_cyc <= 4'b1000;
|
|||
r_ram_ph <= 4'b1000;
|
|||
r_ba0_ctr <= 2'd0;
|
|||
r_ba1_ctr <= 2'd3;
|
|||
r_ph_ctr <= 9'd3;
|
|||
r_ini_ctr <= 3'd0;
|
|||
r_ref_ena <= 1'b0;
|
|||
end
|
|||
else begin
|
|||
r_ram_cyc <= { r_ram_cyc[2:0], r_ram_cyc[3] };
|
|||
if (r_ram_cyc[3]) begin
|
|||
r_ram_ph <= { r_ram_ph[2:0], r_ram_ph[3] };
|
|||
r_ba0_ctr <= r_ba0_ctr + 2'd1;
|
|||
r_ba1_ctr <= r_ba1_ctr + 2'd1;
|
|||
// Phase counter : 3 - 288
|
|||
if (r_ram_ph[3]) begin
|
|||
r_ph_ctr <= (w_bus_eol) ? 9'd3 : r_ph_ctr + 9'd1;
|
|||
end
|
|||
// Initialization done after 4 scanlines
|
|||
if (w_bus_eol & r_ram_ph[3] & ~r_ini_ctr[2])
|
|||
r_ini_ctr <= r_ini_ctr + 3'd1;
|
|||
// Refreshes are enabled during phase 284 - 288
|
|||
//r_ref_ena <= r_ph_ctr[8] & (r_ph_ctr[5] | &r_ph_ctr[4:2]);
|
|||
r_ref_ena <= r_ram_ph[1]; // r_ph_ctr[8] & (r_ph_ctr[5] | &r_ph_ctr[4:2]);
|
|||
end
|
|||
end
|
|||
end
|
|||
assign ram_ref = r_ref_ena;
|
|||
assign ram_cyc = r_ram_cyc;
|
|||
assign ram_ph = r_ram_ph;
|
|||
assign ram_ph_ctr = r_ph_ctr;
|
|||
assign ram_rdy_n = ~r_ini_ctr[2];
|
|||
// ======================================================
|
|||
// SDRAM phase generation
|
|||
// ======================================================
|
|||
reg [3:0] r_rd_act;
|
|||
reg [3:0] r_wr_act;
|
|||
reg r_act_ph; // Activate phase
|
|||
reg r_rd_ph; // Burst read phase
|
|||
reg r_wr_ph; // Burst write phase
|
|||
reg r_ref_ph; // Auto-refresh phase
|
|||
reg [3:0] r_ini_ph; // Initialization phases
|
|||
reg r_pre_ph; // Precharge phase
|
|||
reg r_lmr_ph; // Load mode register phase
|
|||
always@(posedge rst or posedge clk) begin : PHASE_GEN
|
|||
if (rst) begin
|
|||
r_rd_act <= 4'b0000;
|
|||
r_wr_act <= 4'b0000;
|
|||
r_act_ph <= 1'b0;
|
|||
r_rd_ph <= 1'b0;
|
|||
r_wr_ph <= 1'b0;
|
|||
r_ref_ph <= 1'b0;
|
|||
r_ini_ph <= 4'b0000;
|
|||
r_pre_ph <= 1'b0;
|
|||
r_lmr_ph <= 1'b0;
|
|||
end
|
|||
else begin
|
|||
if (r_ram_cyc[0]) begin
|
|||
// Access port #0 read/write
|
|||
if (r_ram_ph[0]) begin
|
|||
r_rd_act[0] <= rden_b0 & ~r_ref_ena;
|
|||
r_wr_act[0] <= wren_b0 & ~r_ref_ena & ~rden_b0;
|
|||
end
|
|||
else if (r_ram_ph[2]) begin
|
|||
r_rd_act[0] <= 1'b0;
|
|||
r_wr_act[0] <= 1'b0;
|
|||
end
|
|||
// Access port #1 read/write
|
|||
if (r_ram_ph[1]) begin
|
|||
r_rd_act[1] <= rden_b1 & ~r_ref_ena;
|
|||
r_wr_act[1] <= wren_b1 & ~r_ref_ena & ~rden_b1;
|
|||
end
|
|||
else if (r_ram_ph[3]) begin
|
|||
r_rd_act[1] <= 1'b0;
|
|||
r_wr_act[1] <= 1'b0;
|
|||
end
|
|||
// Access port #2 read/write
|
|||
if (r_ram_ph[2]) begin
|
|||
r_rd_act[2] <= rden_b2 & ~r_ref_ena;
|
|||
r_wr_act[2] <= wren_b2 & ~r_ref_ena & ~rden_b2;
|
|||
end
|
|||
else if (r_ram_ph[0]) begin
|
|||
r_rd_act[2] <= 1'b0;
|
|||
r_wr_act[2] <= 1'b0;
|
|||
end
|
|||
// Access port #3 read/write
|
|||
if (r_ram_ph[3]) begin
|
|||
r_rd_act[3] <= rden_b3 & ~r_ref_ena;
|
|||
r_wr_act[3] <= wren_b3 & ~r_ref_ena & ~rden_b3;
|
|||
end
|
|||
else if (r_ram_ph[1]) begin
|
|||
r_rd_act[3] <= 1'b0;
|
|||
r_wr_act[3] <= 1'b0;
|
|||
end
|
|||
end
|
|||
if (r_ram_cyc[0] & r_ini_ctr[2]) begin
|
|||
// Activate phase
|
|||
r_act_ph <= (r_ram_ph[0] & (rden_b0 | wren_b0) & ~r_ref_ena)
|
|||
| (r_ram_ph[1] & (rden_b1 | wren_b1) & ~r_ref_ena)
|
|||
| (r_ram_ph[2] & (rden_b2 | wren_b2) & ~r_ref_ena)
|
|||
| (r_ram_ph[3] & (rden_b3 | wren_b3) & ~r_ref_ena);
|
|||
end
|
|||
if (r_ram_cyc[3] & r_ini_ctr[2]) begin
|
|||
// Read phase
|
|||
r_rd_ph <= (r_ram_ph[0] & r_rd_act[0])
|
|||
| (r_ram_ph[1] & r_rd_act[1])
|
|||
| (r_ram_ph[2] & r_rd_act[2])
|
|||
| (r_ram_ph[3] & r_rd_act[3]);
|
|||
// Write phase
|
|||
r_wr_ph <= (r_ram_ph[0] & r_wr_act[0])
|
|||
| (r_ram_ph[1] & r_wr_act[1])
|
|||
| (r_ram_ph[2] & r_wr_act[2])
|
|||
| (r_ram_ph[3] & r_wr_act[3]);
|
|||
end
|
|||
// Initialization phases (0:PRE, 1:REF, 2:REF, 3:LMR)
|
|||
if (r_ram_cyc[3] & r_ram_ph[2]) begin
|
|||
if (r_ref_ena & r_ini_ctr[0] & r_ini_ctr[1]) begin
|
|||
r_ini_ph <= { r_ini_ph[2:0], ~|r_ini_ph };
|
|||
end
|
|||
else begin
|
|||
r_ini_ph <= 4'b0000;
|
|||
end
|
|||
end
|
|||
// Precharge phase
|
|||
r_pre_ph <= r_ini_ph[0] & r_ram_ph[0];
|
|||
// Refresh phase
|
|||
//r_ref_ph <= r_ref_ena & r_ini_ctr[2] & (r_ram_ph[0] | r_ram_ph[2]) & r_ph_ctr[8] // Normal
|
|||
// | (r_ini_ph[1] | r_ini_ph[2]) & r_ram_ph[0]; // Init
|
|||
r_ref_ph <= r_ref_ena & r_ini_ctr[2] // Normal
|
|||
| (r_ini_ph[1] | r_ini_ph[2]) & r_ram_ph[0]; // Init
|
|||
// Load mode register phase
|
|||
r_lmr_ph <= r_ini_ph[3] & r_ram_ph[0];
|
|||
end
|
|||
end
|
|||
// ======================================================
|
|||
// SDRAM address generation
|
|||
// ======================================================
|
|||
reg [22:2] r_addr_mux;
|
|||
reg [10:2] r_addr_col;
|
|||
reg [12:0] r_addr_sdr;
|
|||
reg [1:0] r_ba_sdr;
|
|||
always@(posedge rst or posedge clk) begin : ADDRESS_GEN
|
|||
if (rst) begin
|
|||
r_addr_mux <= 21'd0;
|
|||
r_addr_col <= 9'd0;
|
|||
r_addr_sdr <= 13'd0;
|
|||
r_ba_sdr <= 2'b00;
|
|||
end
|
|||
else begin
|
|||
// Port address multiplexer
|
|||
if (r_ram_cyc[0]) begin
|
|||
r_addr_mux <= addr_b0 & {21{r_ram_ph[0] & (rden_b0 | wren_b0) }}
|
|||
| addr_b1 & {21{r_ram_ph[1] & (rden_b1 | wren_b1) }}
|
|||
| addr_b2 & {21{r_ram_ph[2] & (rden_b2 | wren_b2) }}
|
|||
| addr_b3 & {21{r_ram_ph[3] & (rden_b3 | wren_b3) }};
|
|||
end
|
|||
// Column address (for read/write op.)
|
|||
if (r_ram_cyc[3]) begin
|
|||
r_addr_col <= r_addr_mux[10:2];
|
|||
end
|
|||
// Memories layouts :
|
|||
// ------------------
|
|||
// SDRAM 4M x 32b (128 Mb) : 4 banks x 4096 rows x 256 cols x 32 bits
|
|||
// SDRAM 8M x 32b (256 Mb) : 4 banks x 4096 rows x 512 cols x 32 bits
|
|||
// SDRAM 8M x 16b (128 Mb) : 4 banks x 4096 rows x 512 cols x 16 bits
|
|||
// SDRAM 16M x 16b (256 Mb) : 4 banks x 8192 rows x 512 cols x 16 bits
|
|||
// Row / col address
|
|||
if (SDRAM_WIDTH == 32) begin
|
|||
// 32-bit bus
|
|||
if (SDRAM_SIZE == 32) begin
|
|||
// 32 MB
|
|||
r_addr_sdr <= { 4'b0000, r_addr_col[10: 3], 1'b0 } & {13{r_rd_ph & r_ram_cyc[0]}} // 512 cols
|
|||
| { 1'b0, r_addr_mux[22:11] } & {13{r_act_ph & r_ram_cyc[1]}} // 4096 rows
|
|||
| { 4'b0010, r_addr_col[10: 3], 1'b1 } & {13{r_rd_ph & r_ram_cyc[2]}} // 512 cols
|
|||
| { 4'b0010, r_addr_col[10: 2] } & {13{r_wr_ph & r_ram_cyc[3]}} // 512 cols
|
|||
| { 3'b001, 10'b000000000 } & {13{r_ini_ph[0] }} // Init : precharge all
|
|||
| { 3'b000, 10'b1_00_010_0_000 } & {13{r_ini_ph[3] }}; // Init : load mode register (BL=1, CAS=2)
|
|||
end
|
|||
else begin
|
|||
// 16 MB
|
|||
r_addr_sdr <= { 5'b00000, r_addr_col[ 9: 3], 1'b0 } & {13{r_rd_ph & r_ram_cyc[0]}} // 256 cols
|
|||
| { 1'b0, r_addr_mux[21:10] } & {13{r_act_ph & r_ram_cyc[1]}} // 4096 rows
|
|||
| { 5'b00100, r_addr_col[ 9: 3], 1'b1 } & {13{r_rd_ph & r_ram_cyc[2]}} // 256 cols
|
|||
| { 5'b00100, r_addr_col[ 9: 2] } & {13{r_wr_ph & r_ram_cyc[3]}} // 256 cols
|
|||
| { 3'b001, 10'b000000000 } & {13{r_ini_ph[0] }} // Init : precharge all
|
|||
| { 3'b000, 10'b1_00_010_0_000 } & {13{r_ini_ph[3] }}; // Init : load mode register (BL=1, CAS=2)
|
|||
end
|
|||
end
|
|||
else begin
|
|||
// 16-bit bus
|
|||
if (SDRAM_SIZE == 32) begin
|
|||
// 32 MB
|
|||
r_addr_sdr <= { 4'b0000, r_addr_col[9:3], 2'b00 } & {13{r_rd_ph & r_ram_cyc[0]}} // 512 cols
|
|||
| r_addr_mux[22:10] & {13{r_act_ph & r_ram_cyc[1]}} // 8192 rows
|
|||
| { 4'b0010, r_addr_col[9:3], 2'b10 } & {13{r_rd_ph & r_ram_cyc[2]}} // 512 cols
|
|||
| { 4'b0010, r_addr_col[9:2], 1'b0 } & {13{r_wr_ph & r_ram_cyc[3]}} // 512 cols
|
|||
| { 3'b001, 10'b000000000 } & {13{r_ini_ph[0] }} // Init : precharge all
|
|||
| { 3'b000, 10'b1_00_010_0_001 } & {13{r_ini_ph[3] }}; // Init : load mode register (BL=2, CAS=2)
|
|||
end
|
|||
else begin
|
|||
// 16 MB
|
|||
r_addr_sdr <= { 4'b0000, r_addr_col[9:3], 2'b00 } & {13{r_rd_ph & r_ram_cyc[0]}} // 512 cols
|
|||
| { 1'b0, r_addr_mux[21:10] } & {13{r_act_ph & r_ram_cyc[1]}} // 4096 rows
|
|||
| { 4'b0010, r_addr_col[9:3], 2'b10 } & {13{r_rd_ph & r_ram_cyc[2]}} // 512 cols
|
|||
| { 4'b0010, r_addr_col[9:2], 1'b0 } & {13{r_wr_ph & r_ram_cyc[3]}} // 512 cols
|
|||
| { 3'b001, 10'b000000000 } & {13{r_ini_ph[0] }} // Init : precharge all
|
|||
| { 3'b000, 10'b0_00_010_0_001 } & {13{r_ini_ph[3] }}; // Init : load mode register (BL=2, CAS=2)
|
|||
end
|
|||
end
|
|||
// Bank address
|
|||
r_ba_sdr <= r_ba1_ctr & {2{r_rd_ph & r_ram_cyc[0]}} // 32-bit read
|
|||
| r_ba0_ctr & {2{r_act_ph & r_ram_cyc[1]}} // Activate
|
|||
| r_ba1_ctr & {2{r_rd_ph & r_ram_cyc[2]}} // 32-bit read with auto-precharge
|
|||
| r_ba1_ctr & {2{r_wr_ph & r_ram_cyc[3]}}; // 32-bit write with auto-precharge
|
|||
end
|
|||
end
|
|||
// ======================================================
|
|||
// SDRAM command generation
|
|||
// ======================================================
|
|||
reg [2:0] r_cmd_sdr;
|
|||
always@(posedge rst or posedge clk) begin : COMMAND_GEN
|
|||
reg [2:0] v_cmd_0;
|
|||
reg [2:0] v_cmd_1;
|
|||
reg [2:0] v_cmd_2;
|
|||
reg [2:0] v_cmd_3;
|
|||
reg [2:0] v_cmd_4;
|
|||
reg [2:0] v_cmd_5;
|
|||
reg [2:0] v_cmd_6;
|
|||
if (rst) begin
|
|||
r_cmd_sdr <= CMD_NOP;
|
|||
end
|
|||
else begin
|
|||
v_cmd_0 = CMD_RD | {3{~r_rd_ph }};
|
|||
v_cmd_1 = CMD_ACT | {3{~r_act_ph}};
|
|||
v_cmd_2 = CMD_RD | {3{~r_rd_ph }};
|
|||
v_cmd_3 = CMD_WR | {3{~r_wr_ph }};
|
|||
v_cmd_4 = CMD_PRE | {3{~r_pre_ph}};
|
|||
v_cmd_5 = CMD_REF | {3{~r_ref_ph}};
|
|||
v_cmd_6 = CMD_LMR | {3{~r_lmr_ph}};
|
|||
r_cmd_sdr <= (v_cmd_0 | {3{~r_ram_cyc[0]}})
|
|||
& (v_cmd_1 | {3{~r_ram_cyc[1]}})
|
|||
& (v_cmd_2 | {3{~r_ram_cyc[2]}})
|
|||
& (v_cmd_3 | {3{~r_ram_cyc[3]}})
|
|||
& (v_cmd_4 | {3{~r_ram_cyc[3]}})
|
|||
& (v_cmd_5 | {3{~r_ram_cyc[3]}})
|
|||
& (v_cmd_6 | {3{~r_ram_cyc[3]}});
|
|||
end
|
|||
end
|
|||
assign sdram_cs_n = 1'b0;
|
|||
// Command and address
|
|||
/* verilator lint_off STMTDLY */
|
|||
always@(*) sdram_ras_n = #Tco_dly r_cmd_sdr[2];
|
|||
always@(*) sdram_cas_n = #Tco_dly r_cmd_sdr[1];
|
|||
always@(*) sdram_we_n = #Tco_dly r_cmd_sdr[0];
|
|||
always@(*) sdram_ba = #Tco_dly r_ba_sdr;
|
|||
always@(*) sdram_addr = #Tco_dly r_addr_sdr;
|
|||
/* verilator lint_on STMTDLY */
|
|||
// ======================================================
|
|||
// Data being read
|
|||
// ======================================================
|
|||
reg [3:0] r_data_vld;
|
|||
reg r_data_sel;
|
|||
reg [15:0] r_lrdata_p0;
|
|||
reg [15:0] r_hrdata_p0;
|
|||
reg [15:0] r_hrdata_p1;
|
|||
wire [15:0] w_rdata_p0;
|
|||
always@(posedge rst or posedge clk) begin : DATA_READ
|
|||
if (rst) begin
|
|||
r_data_vld <= 4'b0000;
|
|||
r_data_sel <= 1'b0;
|
|||
r_lrdata_p0 <= 16'h0000;
|
|||
r_hrdata_p0 <= 16'h0000;
|
|||
r_hrdata_p1 <= 16'h0000;
|
|||
end
|
|||
else begin
|
|||
if (r_ram_cyc[3]) begin
|
|||
r_data_vld[0] <= r_rd_act[0] & r_ram_ph[1];
|
|||
r_data_vld[1] <= r_rd_act[1] & r_ram_ph[2];
|
|||
r_data_vld[2] <= r_rd_act[2] & r_ram_ph[3];
|
|||
r_data_vld[3] <= r_rd_act[3] & r_ram_ph[0];
|
|||
end
|
|||
r_data_sel <= r_ram_cyc[1] | r_ram_cyc[3];
|
|||
r_lrdata_p0 <= sdram_dq_i[15:0];
|
|||
r_hrdata_p0 <= sdram_dq_i[31:16];
|
|||
r_hrdata_p1 <= r_hrdata_p0;
|
|||
end
|
|||
end
|
|||
// 32-bit to 16-bit multiplexer
|
|||
assign w_rdata_p0 = (r_data_sel) ? r_hrdata_p1 : r_lrdata_p0;
|
|||
// Access Port #0
|
|||
assign rdata_b0 = (SDRAM_WIDTH == 32) ? w_rdata_p0 : r_lrdata_p0;
|
|||
assign valid_b0 = r_data_vld[0];
|
|||
// Access Port #1
|
|||
assign rdata_b1 = (SDRAM_WIDTH == 32) ? w_rdata_p0 : r_lrdata_p0;
|
|||
assign valid_b1 = r_data_vld[1];
|
|||
// Access Port #2
|
|||
assign rdata_b2 = (SDRAM_WIDTH == 32) ? w_rdata_p0 : r_lrdata_p0;
|
|||
assign valid_b2 = r_data_vld[2];
|
|||
// Access Port #3
|
|||
assign rdata_b3 = (SDRAM_WIDTH == 32) ? w_rdata_p0 : r_lrdata_p0;
|
|||
assign valid_b3 = r_data_vld[3];
|
|||
// ======================================================
|
|||
// Data being written
|
|||
// ======================================================
|
|||
reg [3:0] r_data_fe_p0;
|
|||
reg [3:0] r_data_fe_p1;
|
|||
reg r_data_oe;
|
|||
reg [15:0] r_wdata_p2a;
|
|||
reg [15:0] r_wdata_p2b;
|
|||
reg [31:0] r_wdata_p3;
|
|||
reg [1:0] r_bena_p2a;
|
|||
reg [1:0] r_bena_p2b;
|
|||
reg [3:0] r_bena_p3;
|
|||
always@(posedge rst or posedge clk) begin : DATA_WRITE
|
|||
if (rst) begin
|
|||
r_data_fe_p0 <= 4'b0000;
|
|||
r_data_fe_p1 <= 4'b0000;
|
|||
r_data_oe <= 1'b0;
|
|||
r_wdata_p2a <= 16'h0000;
|
|||
r_wdata_p2b <= 16'h0000;
|
|||
r_wdata_p3 <= 32'h0000_0000;
|
|||
r_bena_p2a <= 2'b00;
|
|||
r_bena_p2b <= 2'b00;
|
|||
r_bena_p3 <= 4'b00_00;
|
|||
end
|
|||
else begin
|
|||
if (r_ram_cyc[3]) begin
|
|||
r_data_fe_p0 <= r_wr_act & r_ram_ph;
|
|||
r_data_oe <= r_wr_ph;
|
|||
end
|
|||
else if (r_ram_cyc[1]) begin
|
|||
r_data_fe_p0 <= 4'b0000;
|
|||
r_data_oe <= 1'b0;
|
|||
end
|
|||
r_data_fe_p1 <= r_data_fe_p0;
|
|||
if (SDRAM_WIDTH == 32) begin
|
|||
// 16-bit -> 32-bit bus
|
|||
if (r_data_sel) begin
|
|||
r_wdata_p2b <= wdata_b0 & {16{r_data_fe_p1[0]}}
|
|||
| wdata_b1 & {16{r_data_fe_p1[1]}}
|
|||
| wdata_b2 & {16{r_data_fe_p1[2]}}
|
|||
| wdata_b3 & {16{r_data_fe_p1[3]}};
|
|||
r_bena_p2b <= bena_b0 & {2{r_data_fe_p1[0]}}
|
|||
| bena_b1 & {2{r_data_fe_p1[1]}}
|
|||
| bena_b2 & {2{r_data_fe_p1[2]}}
|
|||
| bena_b3 & {2{r_data_fe_p1[3]}}
|
|||
| {2{~|r_data_fe_p1}};
|
|||
end
|
|||
else begin
|
|||
r_wdata_p2a <= wdata_b0 & {16{r_data_fe_p1[0]}}
|
|||
| wdata_b1 & {16{r_data_fe_p1[1]}}
|
|||
| wdata_b2 & {16{r_data_fe_p1[2]}}
|
|||
| wdata_b3 & {16{r_data_fe_p1[3]}};
|
|||
r_bena_p2a <= bena_b0 & {2{r_data_fe_p1[0]}}
|
|||
| bena_b1 & {2{r_data_fe_p1[1]}}
|
|||
| bena_b2 & {2{r_data_fe_p1[2]}}
|
|||
| bena_b3 & {2{r_data_fe_p1[3]}}
|
|||
| {2{~|r_data_fe_p1}};
|
|||
end
|
|||
r_wdata_p3 <= { r_wdata_p2b, r_wdata_p2a };
|
|||
r_bena_p3 <= { r_bena_p2b, r_bena_p2a };
|
|||
end
|
|||
else begin
|
|||
// 16-bit bus
|
|||
r_wdata_p2a <= wdata_b0 & {16{r_data_fe_p1[0]}}
|
|||
| wdata_b1 & {16{r_data_fe_p1[1]}}
|
|||
| wdata_b2 & {16{r_data_fe_p1[2]}}
|
|||
| wdata_b3 & {16{r_data_fe_p1[3]}};
|
|||
r_wdata_p2b <= r_wdata_p2a;
|
|||
r_wdata_p3 <= { 16'h0000, r_wdata_p2b };
|
|||
r_bena_p2a <= bena_b0 & {2{r_data_fe_p1[0]}}
|
|||
| bena_b1 & {2{r_data_fe_p1[1]}}
|
|||
| bena_b2 & {2{r_data_fe_p1[2]}}
|
|||
| bena_b3 & {2{r_data_fe_p1[3]}}
|
|||
| {2{~|r_data_fe_p1}};
|
|||
r_bena_p2b <= r_bena_p2a;
|
|||
r_bena_p3 <= { 2'b00, r_bena_p2b };
|
|||
end
|
|||
end
|
|||
end
|
|||
// Output mask, data & enable
|
|||
/* verilator lint_off STMTDLY */
|
|||
always@(*) sdram_dqm_n = #Tco_dly ~r_bena_p3;
|
|||
always@(*) sdram_dq_o = #Tco_dly r_wdata_p3;
|
|||
always@(*) sdram_dq_oe = #Tco_dly r_data_oe;
|
|||
/* verilator lint_on STMTDLY */
|
|||
// Access Port #0
|
|||
assign fetch_b0 = r_data_fe_p0[0];
|
|||
// Access Port #1
|
|||
assign fetch_b1 = r_data_fe_p0[1];
|
|||
// Access Port #2
|
|||
assign fetch_b2 = r_data_fe_p0[2];
|
|||
// Access Port #3
|
|||
assign fetch_b3 = r_data_fe_p0[3];
|
|||
endmodule /* verilator tracing_on */
|