gateware

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit fcba5a8307bc7e05e1814a3f024abf0925c0a28c
parent 69e1beb55107e6a3733c77b3f40ea8b00bc01720
Author: Brian Swetland <swetland@frotz.net>
Date:   Fri, 31 Jan 2020 04:09:29 -0800

sdram: more work

- downcounter -> shiftregister
- accept io op before processing, improving timing closure

Diffstat:
Mhdl/sdram/sdram.sv | 137++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Mhdl/sdram/testbench.sv | 8++++++--
2 files changed, 89 insertions(+), 56 deletions(-)

diff --git a/hdl/sdram/sdram.sv b/hdl/sdram/sdram.sv @@ -38,6 +38,7 @@ module sdram #( parameter T_PWR_UP = 25000 // Power on delay ) ( input wire clk, + input wire reset, output wire pin_clk, output wire pin_ras_n, output wire pin_cas_n, @@ -123,12 +124,6 @@ reg [15:0]refresh_next; wire [15:0]refresh_sub1 = refresh - 16'd1; wire refresh_done = refresh[15]; -// general purpose down counter -reg [4:0]count = 0; -reg [4:0]count_next; -wire [4:0]count_sub1 = count - 5'd1; -wire count_done = count[4]; - // sdram bank state reg bank_active[0:BANKCOUNT-1]; reg bank_active_next[0:BANKCOUNT-1]; @@ -145,6 +140,8 @@ localparam REFRESH = 4'd5; localparam ACTIVE = 4'd6; localparam READ = 4'd7; localparam WRITE = 4'd8; +localparam START_READ = 4'd9; +localparam START_WRITE = 4'd10; reg [3:0]state = START; reg [3:0]state_next; @@ -177,9 +174,23 @@ reg io_sel_a10_next; reg io_sel_row = 0; reg io_sel_row_next; +// general purpose down counter +//reg [4:0]count = 0; +//reg [4:0]count_next; +//wire [4:0]count_sub1 = count - 5'd1; +//wire count_done = count[4]; + +reg [8:0]count = 0; +reg [8:0]count_next; +reg count_done = 1; +reg count_done_next; + +reg io_do_rd = 0; +reg io_do_rd_next; + always_comb begin state_next = state; - count_next = count_done ? count : count_sub1; +// count_next = count_done ? count : count_sub1; refresh_next = refresh_done ? refresh : refresh_sub1; cmd_next = CMD_NOP; data_o_next = data_o; @@ -190,9 +201,13 @@ always_comb begin rd_data_next = rd_data; burst_next = burst; io_addr_next = io_addr; + io_do_rd_next = io_do_rd; io_sel_a10_next = io_sel_a10; io_sel_row_next = io_sel_row; + count_done_next = count_done | count[0]; + count_next = { 1'b0, count[8:1] }; + for (i = 0; i < BANKCOUNT; i++) begin bank_active_next[i] = bank_active[i]; bank_row_next[i] = bank_row[i]; @@ -222,53 +237,61 @@ always_comb begin cmd_next = CMD_PRECHARGE; io_sel_row_next = 0; io_sel_a10_next = 1; // ALL BANKS - count_next = T_RP - 2; - end else if (rd_req && !rd_ack) begin + //count_next = T_RP - 2; + count_next[T_RP-2] = 1; count_done_next = 0; + end else if (rd_req) begin + io_do_rd_next = 1; io_addr_next = rd_addr; - if (!bank_active[rd_bank] || (bank_row[rd_bank] != rd_row)) begin - state_next = ACTIVE; - cmd_next = CMD_PRECHARGE; - io_sel_row_next = 0; // column addr - io_sel_a10_next = 0; // one bank only - count_next = T_RP - 2; - end else begin - cmd_next = CMD_READ; - io_sel_row_next = 0; // column addr - io_sel_a10_next = 0; // no auto precharge - rd_pipe_rdy_next = { 1'b1, rd_pipe_rdy[3:1] }; - rd_pipe_bsy_next = 4'b1111; - rd_ack_next = 1; - if (rd_len != 4'd0) begin - state_next = READ; - burst_next = rd_len; - end - end - end else if (wr_req && !rd_pipe_bsy[0] && !wr_ack) begin + burst_next = rd_len; + state_next = START_READ; + rd_ack_next = 1; + end else if (wr_req) begin + io_do_rd_next = 0; io_addr_next = wr_addr; - if (!bank_active[wr_bank] || (bank_row[wr_bank] != wr_row)) begin - state_next = ACTIVE; - // precharge one bank (a10=0) - cmd_next = CMD_PRECHARGE; - io_sel_row_next = 0; // column addr - io_sel_a10_next = 0; // one bank only - count_next = T_RP - 2; - end else begin - cmd_next = CMD_WRITE; - io_sel_row_next = 0; // column addr - io_sel_a10_next = 0; // no auto precharge - data_o_next = wr_data; - data_oe_next = 1; - wr_ack_next = 1; // 1cyc delay eww - if (wr_len != 4'd0) begin - burst_next = wr_len; - state_next = WRITE; - end - end + data_o_next = wr_data; + burst_next = wr_len; + state_next = START_WRITE; + wr_ack_next = 1; + end + end + START_READ: begin + if (!bank_active[io_bank] || (bank_row[io_bank] != io_row)) begin + state_next = ACTIVE; + cmd_next = CMD_PRECHARGE; + io_sel_row_next = 0; // column addr + io_sel_a10_next = 0; // one bank only + //count_next = T_RP - 2; + count_next[T_RP-2] = 1; count_done_next = 0; + end else begin + cmd_next = CMD_READ; + io_sel_row_next = 0; // column addr + io_sel_a10_next = 0; // no auto precharge + rd_pipe_rdy_next = { 1'b1, rd_pipe_rdy[3:1] }; + rd_pipe_bsy_next = 4'b1111; + state_next = (burst != 4'd0) ? READ : IDLE; + end + end + START_WRITE: if (!rd_pipe_bsy[0]) begin + if (!bank_active[io_bank] || (bank_row[io_bank] != io_row)) begin + state_next = ACTIVE; + // precharge one bank (a10=0) + cmd_next = CMD_PRECHARGE; + io_sel_row_next = 0; // column addr + io_sel_a10_next = 0; // one bank only + //count_next = T_RP - 2; + count_next[T_RP-2] = 1; count_done_next = 0; + end else begin + cmd_next = CMD_WRITE; + io_sel_row_next = 0; // column addr + io_sel_a10_next = 0; // no auto precharge + data_oe_next = 1; + state_next = (burst != 4'd0) ? WRITE : IDLE; end end ACTIVE: begin - state_next = IDLE; - count_next = T_RCD - 2; + state_next = io_do_rd ? START_READ : START_WRITE; + //count_next = T_RCD - 2; + count_next[T_RCD-2] = 1; count_done_next = 0; cmd_next = CMD_ACTIVE; io_sel_row_next = 1; // row address bank_active_next[io_bank] = 1; @@ -299,7 +322,8 @@ always_comb begin end INIT0: if (refresh_done) begin state_next = INIT1; - count_next = 2; + //count_next = 2; + count_next[2] = 1; count_done_next = 0; cmd_next = CMD_PRECHARGE; io_sel_row_next = 0; // column addressing io_sel_a10_next = 1; // ALL BANKS @@ -307,7 +331,8 @@ always_comb begin INIT1: begin state_next = INIT2; cmd_next = CMD_SET_MODE; - count_next = T_MRD - 2; + //count_next = T_MRD - 2; + count_next[T_MRD-2] = 1; count_done_next = 0; // r/w burst off, cas lat 3, sequential addr io_addr_next[XWIDTH-1:COLBITS] = { {(AWIDTH - 10){1'b0}}, 10'b0000110000}; io_sel_row_next = 1; // row addressing @@ -315,12 +340,14 @@ always_comb begin INIT2: begin state_next = REFRESH; cmd_next = CMD_REFRESH; - count_next = T_RC - 2; + //count_next = T_RC - 2; + count_next[T_RC-2] = 1; count_done_next = 0; end REFRESH: begin state_next = IDLE; cmd_next = CMD_REFRESH; - count_next = T_RC - 2; + //count_next = T_RC - 2; + count_next[T_RC-2] = 1; count_done_next = 0; refresh_next = T_RI - 1; // we got here after a precharge all @@ -334,10 +361,12 @@ always_comb begin end always_ff @(posedge clk) begin - state <= state_next; + state <= reset ? START : state_next; count <= count_next; + count_done <= count_done_next; refresh <= refresh_next; cmd <= cmd_next; + io_do_rd <= io_do_rd_next; io_sel_a10 <= io_sel_a10_next; io_sel_row <= io_sel_row_next; io_addr <= io_addr_next; diff --git a/hdl/sdram/testbench.sv b/hdl/sdram/testbench.sv @@ -80,6 +80,8 @@ xorshift32 xs( reg [15:0]cycles = 0; reg [15:0]cycles_next; +reg reset = 1; + always_comb begin number_reset = 0; number_next = 0; @@ -103,7 +105,7 @@ always_comb begin case (state) INIT: if (count_done) begin state_next = WRITES; - count_next = 32; //1000; //32; + count_next = 1000; //32; wr_addr_next = 20'hF0; //wr_data_next = 0; wr_data_next= number[15:0]; @@ -117,7 +119,7 @@ always_comb begin WRITES: if (count_done) begin state_next = READS; number_reset = 1; - count_next = 32; //1000; //32; + count_next = 1000; //32; rd_addr_next = 20'hF0; rd_req_next = 1; wr_req_next = 0; @@ -175,6 +177,7 @@ always_ff @(posedge clk) begin cycles <= cycles_next; done <= done_next; error <= error_next; + reset <= 0; end sdram #( @@ -182,6 +185,7 @@ sdram #( .T_RI(T_RI) ) sdram0 ( .clk(clk), + .reset(reset), .pin_clk(sdram_clk), .pin_ras_n(sdram_ras_n),