diff options
Diffstat (limited to 'sources/hdl/verilog/frontend.v')
| -rw-r--r-- | sources/hdl/verilog/frontend.v | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/sources/hdl/verilog/frontend.v b/sources/hdl/verilog/frontend.v new file mode 100644 index 0000000..9225bd9 --- /dev/null +++ b/sources/hdl/verilog/frontend.v @@ -0,0 +1,237 @@ +`include "parameters.vh" +/* + * This module is responsible for the interface + * between XDMA IP and the fetch stage. + * This module encapsulates a X KiB BRAM which + * is used as an instruction memory. + */ +module frontend#(parameter SIM_MEM = "false")( + // common signals + input clk, + input rst, + + // other control signals + input softmc_fin, + output user_rst, + input init_calib_complete, + output reg rbe_switch_mode, + output reg dllt_begin, + output frontend_ready, + + // frontend <-> fetch stage interface + input [`IMEM_ADDR_WIDTH-1:0] addr_in, + input valid_in, + output [`INSTR_WIDTH-1:0] data_out, + output valid_out, + output [`IMEM_ADDR_WIDTH-1:0] addr_out, + output ready_in, + + // frontend <-> xdma interface + input [`XDMA_AXI_DATA_WIDTH-1:0] h2c_tdata_0, + input h2c_tlast_0, + input h2c_tvalid_0, + output h2c_tready_0, + input [`XDMA_AXI_DATA_WIDTH/8-1:0] h2c_tkeep_0, + + // maintenance signals + output per_rd_init, + output per_zq_init, + output per_ref_init + ); + + reg[31:0] delay_fin; + + always @(posedge clk) begin + if(rst || user_rst) + delay_fin <= 32'b0; + else + delay_fin[1+:31] <= delay_fin[0+:31]; + delay_fin[0] <= softmc_fin; + end + + assign frontend_ready = delay_fin[31]; + + wire imem_wr_en, imem_rd_en; + wire [`IMEM_ADDR_WIDTH-1:0] imem_addr; + wire [`INSTR_WIDTH-1:0] imem_wr_data, imem_rd_data; + + generate + if(SIM_MEM == "true") begin + instr_blk_mem_sim imem( + .addra(imem_addr), + .clka(clk), + .dina(imem_wr_data), + .douta(imem_rd_data), + .ena(imem_rd_en || imem_wr_en), + .wea(imem_wr_en) + ); + end + else begin + instr_blk_mem imem( + .addra(imem_addr), + .clka(clk), + .dina(imem_wr_data), + .douta(imem_rd_data), + .ena(imem_rd_en || imem_wr_en), + .wea(imem_wr_en) + ); + end + endgenerate + + wire [`INSTR_WIDTH-1:0] maint_inst; + wire maint_valid; + wire [`IMEM_ADDR_WIDTH-1:0] maint_addr; + wire maint_req; + reg maint_ack; + wire maint_process; + wire program_process; + reg aref_en; + reg aref_en_valid; + + maintenance_controller maint_ctrl + ( + .clk(clk), + .rst(rst | user_rst), + + .init_calib_complete(init_calib_complete), + .softmc_fin(softmc_fin), + + .aref_en(aref_en), + .aref_en_valid(aref_en_valid), + .maint_req(maint_req), + .maint_ack(maint_ack), + .per_rd_init(per_rd_init), + .per_zq_init(per_zq_init), + .per_ref_init(per_ref_init), + .maint_process(maint_process), + .program_process(program_process), + + .in_addr(addr_in), + .in_valid(valid_in), + + .out_data(maint_inst), + .out_valid(maint_valid), + .out_addr(maint_addr) + ); + + localparam IDLE_S = 2'd0; + localparam INIT_MEM_S = 2'd1; + localparam EXECUTE_S = 2'd2; + + reg [1:0] state_r, state_ns; + + reg [4:0] rst_ctr_ns, rst_ctr_r; + reg [`IMEM_ADDR_WIDTH-1:0] xfer_ctr_r, xfer_ctr_ns; + reg [`IMEM_RD_LATENCY-1:0] valid_out_sr; + reg [(`IMEM_RD_LATENCY * `IMEM_ADDR_WIDTH)-1:0] addr_out_sr; + + assign user_rst = (|rst_ctr_r); + + // imem <-> xdma interface + // TODO do we need tkeep? + assign h2c_tready_0 = state_r == INIT_MEM_S; + assign imem_wr_en = h2c_tvalid_0 && (state_r == INIT_MEM_S); + assign imem_wr_data = h2c_tdata_0[`INSTR_WIDTH-1:0]; + assign imem_addr = state_r == INIT_MEM_S ? xfer_ctr_r : addr_in; + // imem <-> pipeline interface + assign imem_rd_en = valid_in && (program_process); + assign data_out = program_process ? imem_rd_data : maint_inst; + assign valid_out = program_process ? valid_out_sr[0] : maint_valid; + assign addr_out = program_process ? addr_out_sr[`IMEM_ADDR_WIDTH-1:0] : maint_addr; + + generate + if(SIM_MEM=="false") + assign ready_in = state_r == EXECUTE_S; + else + assign ready_in = state_r == EXECUTE_S && ~rst; + endgenerate + assign program_process = (state_r == EXECUTE_S) && ~maint_process; + + always @* begin + aref_en_valid = `LOW; + aref_en = `LOW; + state_ns = state_r; + xfer_ctr_ns = xfer_ctr_r; + rst_ctr_ns = {5{`LOW}}; + maint_ack = `LOW; + rbe_switch_mode = `LOW; + dllt_begin = `LOW; + case (state_r) + IDLE_S: begin + if(~((|delay_fin) || softmc_fin)) begin + if(h2c_tvalid_0) + state_ns = INIT_MEM_S; + else begin + if(maint_req) begin + maint_ack = `HIGH; + state_ns = EXECUTE_S; + end + end + end + end + INIT_MEM_S: begin + if(h2c_tvalid_0) begin + if(h2c_tdata_0[`INSTR_WIDTH]) //indicates a reset + rst_ctr_ns = {5{1'b1}}; + else if(h2c_tdata_0[`INSTR_WIDTH+1]) // indicate switch between readback modes + rbe_switch_mode = `HIGH; + else if(h2c_tdata_0[`INSTR_WIDTH+2]) // indicate dll toggle off WIP + dllt_begin = `HIGH; + else if(h2c_tdata_0[`INSTR_WIDTH+3]) begin // enable-disable autoref + aref_en_valid = `HIGH; + aref_en = h2c_tdata_0[0]; + state_ns = IDLE_S; + end + else begin + xfer_ctr_ns = xfer_ctr_r + 1; + if(h2c_tlast_0) begin + state_ns = EXECUTE_S; + xfer_ctr_ns = {`IMEM_ADDR_WIDTH{`LOW}}; + end + end + end + end + EXECUTE_S: begin + if(h2c_tvalid_0) begin + if(h2c_tdata_0[`INSTR_WIDTH]) //indicates a reset + rst_ctr_ns = {5{1'b1}}; + end + if(softmc_fin) + state_ns = IDLE_S; + end + endcase + + end + + always @(posedge clk) begin + if(rst || (|rst_ctr_r)) begin + if(SIM_MEM == "false") + state_r <= IDLE_S; + else + state_r <= EXECUTE_S; + xfer_ctr_r <= {`IMEM_ADDR_WIDTH{`LOW}}; + valid_out_sr <= {`IMEM_RD_LATENCY{`LOW}}; + addr_out_sr <= 0; + if(rst_ctr_r > 0) + rst_ctr_r <= rst_ctr_r - 1; + else + rst_ctr_r <= 0; + end + else begin + state_r <= state_ns; + xfer_ctr_r <= xfer_ctr_ns; + rst_ctr_r <= rst_ctr_ns; + // compute when we should assert valid data to + // fetch stage. + valid_out_sr[`IMEM_RD_LATENCY-1] <= valid_in && (state_r == EXECUTE_S); + addr_out_sr[`IMEM_RD_LATENCY*`IMEM_ADDR_WIDTH-1 : + (`IMEM_RD_LATENCY-1)*`IMEM_ADDR_WIDTH] <= addr_in; + `ifdef IMEM_SR + valid_out_sr[`IMEM_RD_LATENCY-1:0] <= valid_out_sr >> 1; + addr_out_sr[(`IMEM_RD_LATENCY-1)*`IMEM_ADDR_WIDTH-1:0] + <= addr_out_sr >> `IMEM_ADDR_WIDTH; + `endif + end + end +endmodule + |
