Last active
March 19, 2023 14:46
-
-
Save kazuokada/e3fa7f3ec82dd69b9c1f555688f5f917 to your computer and use it in GitHub Desktop.
wishbone→PSRAM interface bridge
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
`timescale 1ns/1ps | |
// wishbone → PSRAM バスブリッジ | |
// 64burst(64byte) 転送 | |
// data幅 32bit | |
module brd_wb2ps ( | |
input RST, | |
input cpuclk, // wishbone clk | |
// wishbone | |
// reg i/f | |
// 不要? | |
// Tcmd間隔はHDMI側にも必要なので共通regにする方がよいのでは? | |
//input wire [11:0] reg_mem_addr, | |
//input wire [31:0] reg_mem_wdata, | |
//output reg [31:0] reg_mem_rdata, | |
//input wire [3:0] reg_mem_wstrb, | |
//input wire reg_mem_valid, | |
//output wire reg_mem_ready, | |
// PSRAM 32Mbit x 2 | |
// cpuclk domain | |
input wire [20:0] ps_mem_addr, | |
input wire [31:0] ps_mem_wdata, | |
output reg [31:0] ps_mem_rdata, | |
input wire [3:0] ps_mem_wstrb, | |
input wire ps_mem_valid, | |
output wire ps_mem_ready, | |
// PSRAM i/f | |
// psramclk domain | |
input wire half_psramclk, // 83MHz clk | |
output reg cmd0, //input cmd0 | |
output reg cmd_en0, //input cmd_en0 | |
output reg [20:0] addr0, | |
output wire [31:0] wr_data0, | |
input wire [31:0] rd_data0, | |
input wire rd_data_valid0, | |
output wire [3:0] data_mask0, | |
// PSRAM parameter | |
input [5:0] tcmd // cmd間隔 64burst = 26 | |
); | |
wire psramclk = half_psramclk; | |
wire WSHRST; | |
wire PSRAMRST; | |
reg RST_cpuclk_sync1; | |
reg RST_cpuclk_sync2; | |
reg RST_psramclk_sync1; | |
reg RST_psramclk_sync2; | |
reg ready_high; | |
wire psmem_bst_end_cpuclk_1shot; | |
wire start_cputrans; | |
reg run_cputrans; | |
reg cpucmd_assert; | |
reg cpucmd_assert_sync1; // psramclk | |
reg cpucmd_assert_sync2; | |
reg cpucmd_assert_sync3; | |
wire cpucmd_assert_rise_psramclk; | |
reg cpucmd_assert_rise_detect; | |
reg cpucmd_assert_sync1_cpuclk; // cpuclk | |
reg cpucmd_assert_sync2_cpuclk; | |
reg [3:0] psram_rbst_cnt; // psramclk | |
reg [3:0] psram_wbst_cnt; // psramclk | |
reg [4:0] cmd_interval_timer_memclk; | |
reg cmd_interval_ok; | |
reg wait_rd_valid; // psramclk, read cmd発行からrd_data_valid受けつけまで | |
reg psmem_bst_end; // psramclk | |
reg psmem_bst_end_sync1; // cpuclk | |
reg psmem_bst_end_sync2; | |
reg psmem_bst_end_sync3; | |
reg clr_psmem_bst_end_sync1; // psramclk | |
reg clr_psmem_bst_end_sync2; // psramclk | |
reg clr_psmem_bst_end_sync3; // psramclk | |
reg [20:0] ps_mem_addr_psramclk; | |
reg [31:0] ps_mem_data_psramclk; | |
reg [3:0] ps_mem_wstrb_psramclk; | |
reg [31:0] psram_data_fifo[0:15]; // 64byte | |
wire RHIT; // read cache hit | |
reg RVAL; // read cache valid | |
reg [20:6] read_cache_addr; // read cache addr | |
// --------------------------------- | |
// 各種リセット同期化 | |
// --------------------------------- | |
always@(posedge cpuclk or posedge RST) | |
if(RST) begin | |
RST_cpuclk_sync1 <= 1'b1; | |
RST_cpuclk_sync2 <= 1'b1; | |
end | |
else begin | |
RST_cpuclk_sync1 <= RST; | |
RST_cpuclk_sync2 <= RST_cpuclk_sync1; | |
end | |
assign WSHRST = RST_cpuclk_sync2; | |
always@(posedge psramclk or posedge RST) | |
if(RST) begin | |
RST_psramclk_sync1 <= 1'b1; | |
RST_psramclk_sync2 <= 1'b1; | |
end | |
else begin | |
RST_psramclk_sync1 <= RST; | |
RST_psramclk_sync2 <= RST_psramclk_sync1; | |
end | |
assign PSRAMRST = RST_psramclk_sync2; | |
// --------------------------------- | |
// ps_mem_ready | |
// --------------------------------- | |
assign ps_mem_ready = ready_high; | |
always@(posedge cpuclk or posedge WSHRST) | |
if(WSHRST) | |
ready_high <= 1'b0; | |
else if (ready_high) | |
ready_high <= 1'b0; | |
else if (psmem_bst_end_cpuclk_1shot | RHIT) | |
ready_high <= 1'b1; | |
// --------------------------------- | |
// ps_mem_rdata | |
// --------------------------------- | |
always@(posedge cpuclk) | |
if(RHIT|psmem_bst_end_cpuclk_1shot) begin | |
ps_mem_rdata <= psram_data_fifo[ps_mem_addr[5:2]]; | |
end | |
// --------------------------------- | |
// RHIT | |
// cache read hit | |
// --------------------------------- | |
assign RHIT = start_cputrans & RVAL & | |
(ps_mem_wstrb==4'h0) & | |
(read_cache_addr[20:6]== ps_mem_addr[20:6]); | |
// --------------------------------- | |
// run_cputrans (transcation中) | |
// start_cputrans (transcation開始パルス) | |
// --------------------------------- | |
always@(posedge cpuclk or posedge WSHRST) | |
if(WSHRST) | |
run_cputrans <= 1'b0; | |
else | |
run_cputrans <= ( ~ps_mem_ready & ps_mem_valid); | |
assign start_cputrans = ps_mem_valid & (~run_cputrans); | |
// --------------------------------- | |
// cpucmd_assert | |
// --------------------------------- | |
always@(posedge cpuclk or posedge WSHRST) | |
if(WSHRST) | |
cpucmd_assert <= 1'b0; | |
else if(start_cputrans & ~RHIT) | |
cpucmd_assert <= 1'b1; | |
else if(cpucmd_assert_sync2_cpuclk) | |
cpucmd_assert <= 1'b0; | |
always@(posedge psramclk or posedge PSRAMRST) | |
if(PSRAMRST) begin | |
cpucmd_assert_sync1 <= 1'b0; | |
cpucmd_assert_sync2 <= 1'b0; | |
cpucmd_assert_sync3 <= 1'b0; | |
end | |
else begin | |
cpucmd_assert_sync1 <= cpucmd_assert; | |
cpucmd_assert_sync2 <= cpucmd_assert_sync1; | |
cpucmd_assert_sync3 <= cpucmd_assert_sync2; | |
end | |
assign cpucmd_assert_rise_psramclk = cpucmd_assert_sync2&(~cpucmd_assert_sync3); | |
always@(posedge cpuclk or posedge WSHRST) | |
if(WSHRST) begin | |
cpucmd_assert_sync1_cpuclk <= 1'b0; | |
cpucmd_assert_sync2_cpuclk <= 1'b0; | |
end | |
else begin | |
cpucmd_assert_sync1_cpuclk <= cpucmd_assert_sync2; | |
cpucmd_assert_sync2_cpuclk <= cpucmd_assert_sync1_cpuclk; | |
end | |
// --------------------------------- | |
// 64byte 単面キャッシュ | |
// --------------------------------- | |
always@(posedge cpuclk or posedge WSHRST) | |
if(WSHRST) | |
RVAL <= 1'b0; | |
else if(start_cputrans) begin | |
// read cacheのアドレスと今回のwrite要求アドレスが一致ならvalidを破棄 | |
if( (|ps_mem_wstrb)& | |
(RVAL & (read_cache_addr[20:6]== ps_mem_addr[20:6])) ) | |
RVAL <= 1'b0; | |
else if(ps_mem_wstrb==0) | |
RVAL <= 1'b1; | |
else | |
RVAL <= 1'b0; | |
end | |
always@(posedge cpuclk) | |
if(ps_mem_wstrb==4'h0) | |
read_cache_addr[20:6] <= ps_mem_addr[20:6]; | |
// --------------------------------- | |
// cpucmd_assert_rise_detect // psramclk | |
// cpucmd_assert riseエッジ検出(psramclk) | |
// --------------------------------- | |
always@(posedge psramclk or posedge PSRAMRST) | |
if(PSRAMRST) | |
cpucmd_assert_rise_detect <= 1'b0; | |
else if(cmd_en0) | |
cpucmd_assert_rise_detect <= 1'b0; | |
else if(cpucmd_assert_rise_psramclk) | |
cpucmd_assert_rise_detect <= 1'b1; | |
// --------------------------------- | |
// 一旦CPU I/F信号をラッチ | |
// --------------------------------- | |
always@(posedge psramclk) | |
if(cpucmd_assert_rise_psramclk) begin | |
ps_mem_addr_psramclk <= ps_mem_addr; | |
ps_mem_data_psramclk <= ps_mem_wdata; | |
ps_mem_wstrb_psramclk <= ps_mem_wstrb; | |
end | |
// --------------------------------- | |
// PSRAM I/F | |
// --------------------------------- | |
always@(posedge psramclk) | |
if(cpucmd_assert_rise_detect & cmd_interval_ok) | |
cmd0 <= |ps_mem_wstrb_psramclk; // r:0 , w:1 | |
always@(posedge psramclk or posedge PSRAMRST) | |
if(PSRAMRST) | |
cmd_en0 <= 1'b0; | |
else if(cmd_en0) | |
cmd_en0 <= 1'b0; | |
else if(cpucmd_assert_rise_detect & cmd_interval_ok) | |
cmd_en0 <= 1'b1; | |
assign data_mask0 = (ps_mem_addr_psramclk[5:2] == psram_wbst_cnt) ? | |
(~ps_mem_wstrb_psramclk) : 4'hf; | |
always@(posedge psramclk) | |
if(cpucmd_assert_rise_detect & cmd_interval_ok) | |
addr0 <= {ps_mem_addr_psramclk[20:6],6'h00}; // 64byteバウンダリ | |
assign wr_data0 = ps_mem_data_psramclk; | |
always@(posedge psramclk) | |
if(rd_data_valid0) begin | |
//$write("psram_data_fifo[%d]=%h\n",psram_rbst_cnt,rd_data0); | |
psram_data_fifo[psram_rbst_cnt] <= rd_data0; | |
end | |
// --------------------------------- | |
// psram_bst_cnt | |
// (PSRAM burst counter) | |
// --------------------------------- | |
always@(posedge psramclk or posedge PSRAMRST) | |
if(PSRAMRST) | |
psram_wbst_cnt <= 4'h0; | |
else if(cpucmd_assert_rise_psramclk) | |
psram_wbst_cnt <= 4'h0; | |
else if(cmd_en0&cmd0) // write時 | |
psram_wbst_cnt <= 4'h1; | |
//else if(wait_rd_valid & rd_data_valid0) // read | |
// psram_bst_cnt <= 4'h1; | |
else if(psram_wbst_cnt != 4'h0) | |
psram_wbst_cnt <= psram_wbst_cnt + 4'h1; | |
always@(posedge psramclk or posedge PSRAMRST) | |
if(PSRAMRST) | |
psram_rbst_cnt <= 4'h0; | |
else if(cpucmd_assert_rise_psramclk) | |
psram_rbst_cnt <= 4'h0; | |
else if(wait_rd_valid & rd_data_valid0) // read | |
psram_rbst_cnt <= 4'h1; | |
else if((psram_rbst_cnt != 4'h0)&rd_data_valid0) | |
psram_rbst_cnt <= psram_rbst_cnt + 4'h1; | |
// --------------------------------- | |
// wait_rd_valid | |
// (read cmd発行からrd_data_valid受けつけまで) | |
// --------------------------------- | |
always@(posedge psramclk or posedge PSRAMRST) | |
if(PSRAMRST) | |
wait_rd_valid <= 1'b0; | |
else if(cmd_en0&(~cmd0)) | |
wait_rd_valid <= 1'b1; | |
else if(rd_data_valid0) | |
wait_rd_valid <= 1'b0; | |
// --------------------------------- | |
// psmem_bst_end | |
// --------------------------------- | |
always@(posedge psramclk or posedge PSRAMRST) | |
if(PSRAMRST) | |
psmem_bst_end <= 1'b0; | |
else if( (psram_wbst_cnt==4'hf)|((psram_rbst_cnt==4'hf)&rd_data_valid0) ) | |
psmem_bst_end <= 1'b1; | |
else if(clr_psmem_bst_end_sync2&(~clr_psmem_bst_end_sync3)) | |
psmem_bst_end <= 1'b0; | |
always@(posedge psramclk or posedge PSRAMRST) | |
if(PSRAMRST) begin | |
clr_psmem_bst_end_sync1 <= 1'b0; | |
clr_psmem_bst_end_sync2 <= 1'b0; | |
clr_psmem_bst_end_sync3 <= 1'b0; | |
end | |
else begin | |
clr_psmem_bst_end_sync1 <= psmem_bst_end_sync2; | |
clr_psmem_bst_end_sync2 <= clr_psmem_bst_end_sync1; | |
clr_psmem_bst_end_sync3 <= clr_psmem_bst_end_sync3; | |
end | |
// --------------------------------- | |
// cmd_interval_timer_memclk | |
// --------------------------------- | |
always@(posedge psramclk or posedge PSRAMRST) | |
if(PSRAMRST) | |
cmd_interval_timer_memclk <= 5'h00; | |
else if(cpucmd_assert_rise_psramclk) | |
cmd_interval_timer_memclk <= 5'h00; | |
else if(cmd_en0) | |
cmd_interval_timer_memclk <= 5'h01; | |
else if(cmd_interval_timer_memclk != 5'h00) begin | |
if(cmd_interval_timer_memclk == (tcmd-5'h03)) | |
cmd_interval_timer_memclk <= 5'h00; | |
else | |
cmd_interval_timer_memclk <= cmd_interval_timer_memclk + 5'h01; | |
end | |
// --------------------------------- | |
// cmd_interval_ok | |
// --------------------------------- | |
always@(posedge psramclk or posedge PSRAMRST) | |
if(PSRAMRST) | |
cmd_interval_ok <= 1'b0; | |
else | |
cmd_interval_ok <= (cmd_interval_timer_memclk==5'h00); | |
// --------------------------------- | |
// psmem_bst_end_sync1/2/3 | |
// psmem_bst_endをcpuclkで同期化 | |
// --------------------------------- | |
always@(posedge cpuclk or posedge WSHRST) | |
if(WSHRST) begin | |
psmem_bst_end_sync1 <= 1'b0; | |
psmem_bst_end_sync2 <= 1'b0; | |
psmem_bst_end_sync3 <= 1'b0; | |
end | |
else begin | |
psmem_bst_end_sync1 <= psmem_bst_end; | |
psmem_bst_end_sync2 <= psmem_bst_end_sync1; | |
psmem_bst_end_sync3 <= psmem_bst_end_sync2; | |
end | |
assign psmem_bst_end_cpuclk_1shot = | |
psmem_bst_end_sync2 & (~psmem_bst_end_sync3); | |
endmodule |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment