Last active
June 17, 2018 10:54
-
-
Save gregdavill/5e2be11abf8e0554248f4b61a3da1c5d to your computer and use it in GitHub Desktop.
Simple Bindings for BML's HyperRAM into PicoSoC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* PicoSoC - A simple example SoC using PicoRV32 | |
* | |
* Copyright (C) 2017 Clifford Wolf <[email protected]> | |
* 2018 Gregory Davill <[email protected]> | |
* | |
* Permission to use, copy, modify, and/or distribute this software for any | |
* purpose with or without fee is hereby granted, provided that the above | |
* copyright notice and this permission notice appear in all copies. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
* | |
*/ | |
/* | |
* HyperRAM connections: | |
* - HRAM_CK = Clock input to HyperRAM (CK[0] is positive ck, CK[1] is negative ck) | |
* - HRAM_DQ = Bidirectional DDR databus to HyperRAM | |
* - HRAM_CS = Chip Select. Active LOW | |
* - HRAM_RESET = Reset. Active LOW | |
* - HRAM_RWDS = Read Write Data Strobe, (Also Latency indicator.) | |
*/ | |
/* | |
* For use with PicoSOC: https://github.com/cliffordwolf/picorv32/tree/master/picosoc | |
*/ | |
module ecp5demo ( | |
input clk_input, | |
output ser_tx, | |
input ser_rx, | |
output led, | |
output flash_csb, | |
//output flash_clk, /* CLK pin requires special USRMCLK module */ | |
inout flash_io0, | |
inout flash_io1, | |
/* HYPER RAM SIGNALS */ | |
inout [1:0] HRAM_CK, | |
output HRAM_CS, | |
inout HRAM_RWDS, | |
inout [7:0] HRAM_DQ, | |
output HRAM_RESET, | |
); | |
wire clk; | |
assign clk = clk_input; | |
reg [10:0] reset_cnt = 0; | |
wire resetn = &reset_cnt; | |
always @(posedge clk) begin | |
reset_cnt <= reset_cnt + !resetn; | |
end | |
wire flash_io0_oe, flash_io0_do, flash_io0_di; | |
wire flash_io1_oe, flash_io1_do, flash_io1_di; | |
wire flash_clk; | |
/* Flash IO buffers */ | |
USRMCLK u1 (.USRMCLKI(flash_clk), .USRMCLKTS(!resetn)) /* synthesis syn_noprune=1 */; | |
BBPU flash_io_buf[1:0] ( | |
.B({flash_io1, flash_io0}), | |
.T({!flash_io1_oe, !flash_io0_oe}), | |
.I({flash_io1_do, flash_io0_do}), | |
.O({flash_io1_di, flash_io0_di}) | |
); | |
wire iomem_valid; | |
reg iomem_ready; | |
wire [3:0] iomem_wstrb; | |
wire [31:0] iomem_addr; | |
wire [31:0] iomem_wdata; | |
reg [31:0] iomem_rdata; | |
reg [31:0] gpio; | |
assign led = gpio[0]; | |
reg [31:0] hyperram_ctrl_addr; | |
reg hyperram_ctrl; | |
reg [7:0] latency_1x; | |
reg [7:0] latency_2x; | |
reg rd_jk; | |
reg rd_req; | |
reg wr_req; | |
wire [31:0] addr; | |
wire [31:0] wr_d; | |
wire [31:0] rd_d; | |
wire rd_rdy; | |
wire busy; | |
always @(posedge clk) begin | |
if (!resetn) begin | |
gpio <= 0; | |
hyperram_ctrl <= 0; | |
hyperram_ctrl_addr <= 0; | |
latency_1x <= 8'h12; | |
latency_2x <= 8'h16; | |
end else begin | |
iomem_ready <= 0; | |
if(iomem_valid && !iomem_ready && iomem_addr[31:24] == 8'h 03) begin | |
/* GPIO outputs [0x0300 0000]*/ | |
if (iomem_addr[7:0] == 8'h 00) begin | |
iomem_ready <= 1; | |
iomem_rdata <= {gpio[31:0]}; | |
if (iomem_wstrb[0]) gpio[ 7: 0] <= iomem_wdata[ 7: 0]; | |
if (iomem_wstrb[1]) gpio[15: 8] <= iomem_wdata[15: 8]; | |
if (iomem_wstrb[2]) gpio[23:16] <= iomem_wdata[23:16]; | |
if (iomem_wstrb[3]) gpio[31:24] <= iomem_wdata[31:24]; | |
end | |
/* hyperram_ctrl_a [0x0300 0010] */ | |
if(iomem_addr[7:0] == 8'h 10) begin | |
iomem_ready <= 1; | |
iomem_rdata <= {16'b0,latency_2x,latency_1x}; | |
if (iomem_wstrb[0]) latency_1x <= iomem_wdata[ 7: 0]; | |
if (iomem_wstrb[1]) latency_2x <= iomem_wdata[15: 8]; | |
end | |
/* hyperram_ctrl_b [0x0300 0014] */ | |
if(iomem_addr[7:0] == 8'h 14) begin | |
/* Write */ | |
if (|iomem_wstrb) begin | |
if(!busy) begin | |
hyperram_ctrl <= 1; | |
hyperram_ctrl_addr <= 32'h0000_0800; | |
wr_req <= 1; | |
end | |
if(wr_req) begin | |
wr_req <= 0; | |
iomem_ready <= 1; /* No need to wait for writes */ | |
hyperram_ctrl <= 0; | |
end | |
end else begin | |
if(!busy) begin | |
hyperram_ctrl <= 1; | |
hyperram_ctrl_addr <= 32'h0000_0800; | |
rd_jk <= 1; | |
end | |
if(rd_rdy) begin | |
iomem_ready <= 1; | |
rd_jk <= 0; | |
hyperram_ctrl <= 0; | |
end | |
iomem_rdata <= rd_d; | |
end | |
end | |
end | |
/* HyperRAM mem-map [0x0400 0000+] */ | |
if (iomem_valid && !iomem_ready && iomem_addr[31:24] == 8'h 04 ) begin | |
if (|iomem_wstrb) begin | |
if(!busy) begin | |
wr_req <= 1; | |
end | |
if(wr_req) begin | |
wr_req <= 0; | |
iomem_ready <= 1; /* No need to wait for writes */ | |
end | |
end else begin | |
rd_jk <= !busy; | |
if(rd_rdy) begin | |
iomem_ready <= 1; | |
rd_jk <= 0; | |
end | |
iomem_rdata <= rd_d; | |
end | |
end | |
end | |
end | |
picosoc soc ( | |
.clk (clk ), | |
.resetn (resetn ), | |
.ser_tx (ser_tx ), | |
.ser_rx (ser_rx ), | |
.flash_csb (flash_csb ), | |
.flash_clk (flash_clk ), | |
.flash_io0_oe (flash_io0_oe), | |
.flash_io1_oe (flash_io1_oe), | |
.flash_io0_do (flash_io0_do), | |
.flash_io1_do (flash_io1_do), | |
.flash_io0_di (flash_io0_di), | |
.flash_io1_di (flash_io1_di), | |
.irq_5 (1'b0 ), | |
.irq_6 (1'b0 ), | |
.irq_7 (1'b0 ), | |
.iomem_valid (iomem_valid ), | |
.iomem_ready (iomem_ready ), | |
.iomem_wstrb (iomem_wstrb ), | |
.iomem_addr (iomem_addr ), | |
.iomem_wdata (iomem_wdata ), | |
.iomem_rdata (iomem_rdata ) | |
); | |
/* Module to IO */ | |
wire [7:0] dram_dq_in; | |
wire [7:0] dram_dq_out; | |
wire dram_dq_oe_l; | |
wire dram_rwds_in; | |
wire dram_rwds_out; | |
wire dram_rwds_oe_l; | |
wire dram_ck; | |
wire dram_rst_l; | |
wire dram_cs_l; | |
assign addr = hyperram_ctrl ? hyperram_ctrl_addr : {10'b0, iomem_addr[23:2]}; | |
assign wr_d = iomem_wdata; | |
/* rd_req pulse generator */ | |
reg rd_jk_sr; | |
always @(posedge clk) begin | |
if (!resetn) begin | |
rd_jk_sr <= 0; | |
end | |
rd_jk_sr <= rd_jk; | |
rd_req <= 0; | |
if(!rd_jk_sr && rd_jk) | |
rd_req <= 1; | |
end | |
/* BML's HyperRAM module | |
* https://github.com/blackmesalabs/hyperram | |
*/ | |
hyper_xface u_hyper_xface | |
( | |
.reset ( !resetn ), | |
.clk ( clk ), | |
.rd_req ( rd_req ), | |
.wr_req ( wr_req ), | |
.mem_or_reg ( hyperram_ctrl ), | |
.wr_byte_en ( 4'hF ), | |
.addr ( addr[31:0] ), | |
.rd_num_dwords ( 6'b000001 ), | |
.wr_d ( wr_d[31:0] ), | |
.rd_d ( rd_d[31:0] ), | |
.rd_rdy ( rd_rdy ), | |
.burst_wr_rdy ( burst_wr_rdy ), | |
.busy ( busy ), | |
.latency_1x ( latency_1x ), | |
.latency_2x ( latency_2x ), | |
.dram_dq_in ( dram_dq_in[7:0] ), | |
.dram_dq_out ( dram_dq_out[7:0] ), | |
.dram_dq_oe_l ( dram_dq_oe_l ), | |
.dram_rwds_in ( dram_rwds_in ), | |
.dram_rwds_out ( dram_rwds_out ), | |
.dram_rwds_oe_l ( dram_rwds_oe_l ), | |
.dram_ck ( dram_ck ), | |
.dram_rst_l ( dram_rst_l ), | |
.dram_cs_l ( dram_cs_l ) | |
); | |
/* IO bindings OB - OutputBuffer, BB - BidirectionalBuffer */ | |
OB hyperram_cs ( | |
.O(HRAM_CS), | |
.I(dram_cs_l) | |
); | |
OB hyperram_reset ( | |
.O(HRAM_RESET), | |
.I(dram_rst_l) | |
); | |
BB hyperram_rwds ( | |
.B ( HRAM_RWDS ), | |
.T ( dram_rwds_oe_l), | |
.I (dram_rwds_out), | |
.O (dram_rwds_in) | |
); | |
OB hyperram_ck [1:0] ( | |
.O ( HRAM_CK ), | |
.I ({~dram_ck, dram_ck}) | |
); | |
BB hyperram_dq [7:0] ( | |
.B ( HRAM_DQ ), | |
.T ( dram_dq_oe_l), | |
.I (dram_dq_out), | |
.O (dram_dq_in) | |
); | |
endmodule |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment