-
Notifications
You must be signed in to change notification settings - Fork 88
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Sebastien Bourdeauducq
committed
May 19, 2012
1 parent
7d18736
commit 4e18e45
Showing
13 changed files
with
863 additions
and
9 deletions.
There are no files selected for viewing
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
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
from migen.fhdl.structure import * | ||
from migen.bank.description import * | ||
from migen.bank.eventmanager import * | ||
from migen.bank import csrgen | ||
from migen.bus import wishbone | ||
|
||
_count_width = 11 | ||
|
||
class MiniMAC: | ||
def __init__(self, address): | ||
# PHY signals | ||
self.phy_tx_clk = Signal() | ||
self.phy_tx_data = Signal(BV(4)) | ||
self.phy_tx_en = Signal() | ||
self.phy_tx_er = Signal() | ||
self.phy_rx_clk = Signal() | ||
self.phy_rx_data = Signal(BV(4)) | ||
self.phy_dv = Signal() | ||
self.phy_rx_er = Signal() | ||
self.phy_col = Signal() | ||
self.phy_crs = Signal() | ||
self.phy_rst_n = Signal() | ||
|
||
# CPU interface | ||
self._phy_reset = RegisterField("phy_reset", reset=1) | ||
self._rx_count_0 = RegisterField("rx_count_0", _count_width, access_bus=READ_ONLY, access_dev=WRITE_ONLY) | ||
self._rx_count_1 = RegisterField("rx_count_1", _count_width, access_bus=READ_ONLY, access_dev=WRITE_ONLY) | ||
self._tx_count = RegisterField("tx_count", _count_width, access_dev=READ_WRITE) | ||
regs = [self._phy_reset, self._rx_count_0, self._rx_count_1, self._tx_count] | ||
|
||
self._rx_event_0 = EventSourcePulse() | ||
self._rx_event_1 = EventSourcePulse() | ||
self._tx_event = EventSourcePulse() | ||
self.events = EventManager(self._rx_event_0, self._rx_event_1, self._tx_event) | ||
|
||
self.bank = csrgen.Bank(regs + self.events.get_registers(), address=address) | ||
self.membus = wishbone.Interface() | ||
|
||
def get_fragment(self): | ||
init = Signal(reset=1) | ||
rx_ready_0 = Signal() | ||
rx_ready_1 = Signal() | ||
rx_pending_0 = self._rx_event_0.pending | ||
rx_pending_1 = self._rx_event_1.pending | ||
rx_pending_0_r = Signal() | ||
rx_pending_1_r = Signal() | ||
comb = [ | ||
self.phy_rst_n.eq(~self._phy_reset.field.r), | ||
|
||
rx_ready_0.eq(init | (rx_pending_0_r & ~rx_pending_0)), | ||
rx_ready_1.eq(init | (rx_pending_1_r & ~rx_pending_1)), | ||
|
||
self._tx_count.field.w.eq(0), | ||
self._tx_count.field.we.eq(self._tx_event.trigger) | ||
] | ||
sync = [ | ||
init.eq(0), | ||
rx_pending_0_r.eq(rx_pending_0), | ||
rx_pending_1_r.eq(rx_pending_1) | ||
] | ||
inst = [ | ||
Instance("minimac3", | ||
[ | ||
("rx_done_0", self._rx_event_0.trigger), | ||
("rx_count_0", self._rx_count_0.field.w), | ||
("rx_done_1", self._rx_event_1.trigger), | ||
("rx_count_1", self._rx_count_1.field.w), | ||
|
||
("tx_done", self._tx_event.trigger), | ||
|
||
("wb_dat_o", self.membus.dat_r), | ||
("wb_ack_o", self.membus.ack), | ||
|
||
("phy_tx_data", self.phy_tx_data), | ||
("phy_tx_en", self.phy_tx_en), | ||
("phy_tx_er", self.phy_tx_er), | ||
], [ | ||
("rx_ready_0", rx_ready_0), | ||
("rx_ready_1", rx_ready_1), | ||
|
||
("tx_start", self._tx_count.re), | ||
("tx_count", self._tx_count.field.r), | ||
|
||
("wb_adr_i", self.membus.adr), | ||
("wb_dat_i", self.membus.dat_w), | ||
("wb_sel_i", self.membus.sel), | ||
("wb_stb_i", self.membus.stb), | ||
("wb_cyc_i", self.membus.cyc), | ||
("wb_we_i", self.membus.we), | ||
|
||
("phy_tx_clk", self.phy_tx_clk), | ||
("phy_rx_clk", self.phy_rx_clk), | ||
("phy_rx_data", self.phy_rx_data), | ||
("phy_dv", self.phy_dv), | ||
("phy_rx_er", self.phy_rx_er), | ||
("phy_col", self.phy_col), | ||
("phy_crs", self.phy_crs) | ||
], | ||
clkport="sys_clk", | ||
rstport="sys_rst" | ||
) | ||
] | ||
return Fragment(comb, sync, instances=inst) \ | ||
+ self.events.get_fragment() \ | ||
+ self.bank.get_fragment() |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* | ||
* Milkymist SoC | ||
* Copyright (C) 2007, 2008, 2009, 2010, 2011 Sebastien Bourdeauducq | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation, version 3 of the License. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
module psync( | ||
input clk1, | ||
input i, | ||
input clk2, | ||
output o | ||
); | ||
|
||
reg level; | ||
always @(posedge clk1) | ||
if(i) | ||
level <= ~level; | ||
|
||
reg level1; | ||
reg level2; | ||
reg level3; | ||
always @(posedge clk2) begin | ||
level1 <= level; | ||
level2 <= level1; | ||
level3 <= level2; | ||
end | ||
|
||
assign o = level2 ^ level3; | ||
|
||
initial begin | ||
level <= 1'b0; | ||
level1 <= 1'b0; | ||
level2 <= 1'b0; | ||
level3 <= 1'b0; | ||
end | ||
|
||
endmodule |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
/* | ||
* Milkymist SoC | ||
* Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Sebastien Bourdeauducq | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation, version 3 of the License. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
module minimac3( | ||
input sys_clk, | ||
input sys_rst, | ||
|
||
/* Control */ | ||
input rx_ready_0, | ||
output rx_done_0, | ||
output [10:0] rx_count_0, | ||
input rx_ready_1, | ||
output rx_done_1, | ||
output [10:0] rx_count_1, | ||
|
||
input tx_start, | ||
output tx_done, | ||
input [10:0] tx_count, | ||
|
||
/* WISHBONE to access RAM */ | ||
input [29:0] wb_adr_i, | ||
output [31:0] wb_dat_o, | ||
input [31:0] wb_dat_i, | ||
input [3:0] wb_sel_i, | ||
input wb_stb_i, | ||
input wb_cyc_i, | ||
output wb_ack_o, | ||
input wb_we_i, | ||
|
||
/* To PHY */ | ||
input phy_tx_clk, | ||
output [3:0] phy_tx_data, | ||
output phy_tx_en, | ||
output phy_tx_er, | ||
input phy_rx_clk, | ||
input [3:0] phy_rx_data, | ||
input phy_dv, | ||
input phy_rx_er, | ||
input phy_col, | ||
input phy_crs | ||
); | ||
|
||
wire [1:0] phy_rx_ready; | ||
wire [1:0] phy_rx_done; | ||
wire [10:0] phy_rx_count_0; | ||
wire [10:0] phy_rx_count_1; | ||
wire phy_tx_start; | ||
wire phy_tx_done; | ||
wire [10:0] phy_tx_count; | ||
|
||
minimac3_sync sync( | ||
.sys_clk(sys_clk), | ||
.phy_rx_clk(phy_rx_clk), | ||
.phy_tx_clk(phy_tx_clk), | ||
|
||
.sys_rx_ready({rx_ready_1, rx_ready_0}), | ||
.sys_rx_done({rx_done_1, rx_done_0}), | ||
.sys_rx_count_0(rx_count_0), | ||
.sys_rx_count_1(rx_count_1), | ||
.sys_tx_start(tx_start), | ||
.sys_tx_done(tx_done), | ||
.sys_tx_count(tx_count), | ||
|
||
.phy_rx_ready(phy_rx_ready), | ||
.phy_rx_done(phy_rx_done), | ||
.phy_rx_count_0(phy_rx_count_0), | ||
.phy_rx_count_1(phy_rx_count_1), | ||
.phy_tx_start(phy_tx_start), | ||
.phy_tx_done(phy_tx_done), | ||
.phy_tx_count(phy_tx_count) | ||
); | ||
|
||
wire [7:0] rxb0_dat; | ||
wire [10:0] rxb0_adr; | ||
wire rxb0_we; | ||
wire [7:0] rxb1_dat; | ||
wire [10:0] rxb1_adr; | ||
wire rxb1_we; | ||
wire [7:0] txb_dat; | ||
wire [10:0] txb_adr; | ||
minimac3_memory memory( | ||
.sys_clk(sys_clk), | ||
.sys_rst(sys_rst), | ||
.phy_rx_clk(phy_rx_clk), | ||
.phy_tx_clk(phy_tx_clk), | ||
|
||
.wb_adr_i(wb_adr_i), | ||
.wb_dat_o(wb_dat_o), | ||
.wb_dat_i(wb_dat_i), | ||
.wb_sel_i(wb_sel_i), | ||
.wb_stb_i(wb_stb_i), | ||
.wb_cyc_i(wb_cyc_i), | ||
.wb_ack_o(wb_ack_o), | ||
.wb_we_i(wb_we_i), | ||
|
||
.rxb0_dat(rxb0_dat), | ||
.rxb0_adr(rxb0_adr), | ||
.rxb0_we(rxb0_we), | ||
.rxb1_dat(rxb1_dat), | ||
.rxb1_adr(rxb1_adr), | ||
.rxb1_we(rxb1_we), | ||
|
||
.txb_dat(txb_dat), | ||
.txb_adr(txb_adr) | ||
); | ||
|
||
minimac3_tx tx( | ||
.phy_tx_clk(phy_tx_clk), | ||
|
||
.tx_start(phy_tx_start), | ||
.tx_done(phy_tx_done), | ||
.tx_count(phy_tx_count), | ||
.txb_dat(txb_dat), | ||
.txb_adr(txb_adr), | ||
|
||
.phy_tx_en(phy_tx_en), | ||
.phy_tx_data(phy_tx_data) | ||
); | ||
assign phy_tx_er = 1'b0; | ||
|
||
minimac3_rx rx( | ||
.phy_rx_clk(phy_rx_clk), | ||
|
||
.rx_ready(phy_rx_ready), | ||
.rx_done(phy_rx_done), | ||
.rx_count_0(phy_rx_count_0), | ||
.rx_count_1(phy_rx_count_1), | ||
|
||
.rxb0_dat(rxb0_dat), | ||
.rxb0_adr(rxb0_adr), | ||
.rxb0_we(rxb0_we), | ||
.rxb1_dat(rxb1_dat), | ||
.rxb1_adr(rxb1_adr), | ||
.rxb1_we(rxb1_we), | ||
|
||
.phy_dv(phy_dv), | ||
.phy_rx_data(phy_rx_data), | ||
.phy_rx_er(phy_rx_er) | ||
); | ||
|
||
endmodule |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
/* | ||
* Milkymist SoC | ||
* Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Sebastien Bourdeauducq | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation, version 3 of the License. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
/* TODO: use behavioral BRAM models (Xst can extract byte WE) */ | ||
|
||
module minimac3_memory( | ||
input sys_clk, | ||
input sys_rst, | ||
input phy_rx_clk, | ||
input phy_tx_clk, | ||
|
||
input [29:0] wb_adr_i, | ||
output [31:0] wb_dat_o, | ||
input [31:0] wb_dat_i, | ||
input [3:0] wb_sel_i, | ||
input wb_stb_i, | ||
input wb_cyc_i, | ||
output reg wb_ack_o, | ||
input wb_we_i, | ||
|
||
input [7:0] rxb0_dat, | ||
input [10:0] rxb0_adr, | ||
input rxb0_we, | ||
input [7:0] rxb1_dat, | ||
input [10:0] rxb1_adr, | ||
input rxb1_we, | ||
|
||
output [7:0] txb_dat, | ||
input [10:0] txb_adr | ||
|
||
); | ||
|
||
wire wb_en = wb_cyc_i & wb_stb_i; | ||
wire [1:0] wb_buf = wb_adr_i[10:9]; | ||
wire [31:0] wb_dat_i_le = {wb_dat_i[7:0], wb_dat_i[15:8], wb_dat_i[23:16], wb_dat_i[31:24]}; | ||
wire [3:0] wb_sel_i_le = {wb_sel_i[0], wb_sel_i[1], wb_sel_i[2], wb_sel_i[3]}; | ||
|
||
wire [31:0] rxb0_wbdat; | ||
RAMB16BWER #( | ||
.DATA_WIDTH_A(36), | ||
.DATA_WIDTH_B(9), | ||
.DOA_REG(0), | ||
.DOB_REG(0), | ||
.EN_RSTRAM_A("FALSE"), | ||
.EN_RSTRAM_B("FALSE"), | ||
.SIM_DEVICE("SPARTAN6"), | ||
.WRITE_MODE_A("WRITE_FIRST"), | ||
.WRITE_MODE_B("WRITE_FIRST") | ||
) rxb0 ( | ||
.DIA(wb_dat_i_le), | ||
.DIPA(4'd0), | ||
.DOA(rxb0_wbdat), | ||
.ADDRA({wb_adr_i[8:0], 5'd0}), | ||
.WEA({4{wb_en & wb_we_i & (wb_buf == 2'b00)}} & wb_sel_i_le), | ||
.ENA(1'b1), | ||
.RSTA(1'b0), | ||
.CLKA(sys_clk), | ||
|
||
.DIB(rxb0_dat), | ||
.DIPB(1'd0), | ||
.DOB(), | ||
.ADDRB({rxb0_adr, 3'd0}), | ||
.WEB({4{rxb0_we}}), | ||
.ENB(1'b1), | ||
.RSTB(1'b0), | ||
.CLKB(phy_rx_clk) | ||
); | ||
|
||
wire [31:0] rxb1_wbdat; | ||
RAMB16BWER #( | ||
.DATA_WIDTH_A(36), | ||
.DATA_WIDTH_B(9), | ||
.DOA_REG(0), | ||
.DOB_REG(0), | ||
.EN_RSTRAM_A("FALSE"), | ||
.EN_RSTRAM_B("FALSE"), | ||
.SIM_DEVICE("SPARTAN6"), | ||
.WRITE_MODE_A("WRITE_FIRST"), | ||
.WRITE_MODE_B("WRITE_FIRST") | ||
) rxb1 ( | ||
.DIA(wb_dat_i_le), | ||
.DIPA(4'd0), | ||
.DOA(rxb1_wbdat), | ||
.ADDRA({wb_adr_i[8:0], 5'd0}), | ||
.WEA({4{wb_en & wb_we_i & (wb_buf == 2'b01)}} & wb_sel_i_le), | ||
.ENA(1'b1), | ||
.RSTA(1'b0), | ||
.CLKA(sys_clk), | ||
|
||
.DIB(rxb1_dat), | ||
.DIPB(1'd0), | ||
.DOB(), | ||
.ADDRB({rxb1_adr, 3'd0}), | ||
.WEB({4{rxb1_we}}), | ||
.ENB(1'b1), | ||
.RSTB(1'b0), | ||
.CLKB(phy_rx_clk) | ||
); | ||
|
||
wire [31:0] txb_wbdat; | ||
RAMB16BWER #( | ||
.DATA_WIDTH_A(36), | ||
.DATA_WIDTH_B(9), | ||
.DOA_REG(0), | ||
.DOB_REG(0), | ||
.EN_RSTRAM_A("FALSE"), | ||
.EN_RSTRAM_B("FALSE"), | ||
.SIM_DEVICE("SPARTAN6"), | ||
.WRITE_MODE_A("WRITE_FIRST"), | ||
.WRITE_MODE_B("WRITE_FIRST") | ||
) txb ( | ||
.DIA(wb_dat_i_le), | ||
.DIPA(4'd0), | ||
.DOA(txb_wbdat), | ||
.ADDRA({wb_adr_i[8:0], 5'd0}), | ||
.WEA({4{wb_en & wb_we_i & (wb_buf == 2'b10)}} & wb_sel_i_le), | ||
.ENA(1'b1), | ||
.RSTA(1'b0), | ||
.CLKA(sys_clk), | ||
|
||
.DIB(8'd0), | ||
.DIPB(1'd0), | ||
.DOB(txb_dat), | ||
.ADDRB({txb_adr, 3'd0}), | ||
.WEB(4'd0), | ||
.ENB(1'b1), | ||
.RSTB(1'b0), | ||
.CLKB(phy_tx_clk) | ||
); | ||
|
||
always @(posedge sys_clk) begin | ||
if(sys_rst) | ||
wb_ack_o <= 1'b0; | ||
else begin | ||
wb_ack_o <= 1'b0; | ||
if(wb_en & ~wb_ack_o) | ||
wb_ack_o <= 1'b1; | ||
end | ||
end | ||
|
||
reg [1:0] wb_buf_r; | ||
always @(posedge sys_clk) | ||
wb_buf_r <= wb_buf; | ||
|
||
reg [31:0] wb_dat_o_le; | ||
always @(*) begin | ||
case(wb_buf_r) | ||
2'b00: wb_dat_o_le = rxb0_wbdat; | ||
2'b01: wb_dat_o_le = rxb1_wbdat; | ||
default: wb_dat_o_le = txb_wbdat; | ||
endcase | ||
end | ||
assign wb_dat_o = {wb_dat_o_le[7:0], wb_dat_o_le[15:8], wb_dat_o_le[23:16], wb_dat_o_le[31:24]}; | ||
|
||
endmodule |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
/* | ||
* Milkymist SoC | ||
* Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Sebastien Bourdeauducq | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation, version 3 of the License. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
module minimac3_rx( | ||
input phy_rx_clk, | ||
|
||
input [1:0] rx_ready, | ||
output [1:0] rx_done, | ||
output reg [10:0] rx_count_0, | ||
output reg [10:0] rx_count_1, | ||
|
||
output [7:0] rxb0_dat, | ||
output [10:0] rxb0_adr, | ||
output rxb0_we, | ||
output [7:0] rxb1_dat, | ||
output [10:0] rxb1_adr, | ||
output rxb1_we, | ||
|
||
input phy_dv, | ||
input [3:0] phy_rx_data, | ||
input phy_rx_er | ||
); | ||
|
||
reg [1:0] available_slots; | ||
always @(posedge phy_rx_clk) | ||
available_slots <= (available_slots & ~rx_done) | rx_ready; | ||
initial available_slots <= 2'd0; | ||
|
||
reg [1:0] used_slot; | ||
reg used_slot_update; | ||
always @(posedge phy_rx_clk) begin | ||
if(used_slot_update) begin | ||
used_slot[0] <= available_slots[0]; | ||
used_slot[1] <= available_slots[1] & ~available_slots[0]; | ||
end | ||
end | ||
|
||
reg rx_done_ctl; | ||
assign rx_done = {2{rx_done_ctl}} & used_slot; | ||
|
||
reg rx_count_reset_ctl; | ||
reg rx_count_inc_ctl; | ||
wire [1:0] rx_count_reset = {2{rx_count_reset_ctl}} & used_slot; | ||
wire [1:0] rx_count_inc = {2{rx_count_inc_ctl}} & used_slot; | ||
always @(posedge phy_rx_clk) begin | ||
if(rx_count_reset[0]) | ||
rx_count_0 <= 11'd0; | ||
else if(rx_count_inc[0]) | ||
rx_count_0 <= rx_count_0 + 11'd1; | ||
if(rx_count_reset[1]) | ||
rx_count_1 <= 11'd0; | ||
else if(rx_count_inc[1]) | ||
rx_count_1 <= rx_count_1 + 11'd1; | ||
end | ||
|
||
assign rxb0_adr = rx_count_0; | ||
assign rxb1_adr = rx_count_1; | ||
reg rxb_we_ctl; | ||
assign rxb0_we = rxb_we_ctl & used_slot[0]; | ||
assign rxb1_we = rxb_we_ctl & used_slot[1]; | ||
|
||
reg [3:0] lo; | ||
reg [3:0] hi; | ||
reg [1:0] load_nibble; | ||
always @(posedge phy_rx_clk) begin | ||
if(load_nibble[0]) | ||
lo <= phy_rx_data; | ||
if(load_nibble[1]) | ||
hi <= phy_rx_data; | ||
end | ||
assign rxb0_dat = {hi, lo}; | ||
assign rxb1_dat = {hi, lo}; | ||
|
||
reg [1:0] state; | ||
reg [1:0] next_state; | ||
|
||
parameter IDLE = 2'd0; | ||
parameter LOAD_LO = 2'd1; | ||
parameter LOAD_HI = 2'd2; | ||
parameter TERMINATE = 2'd3; | ||
|
||
initial state <= IDLE; | ||
always @(posedge phy_rx_clk) | ||
state <= next_state; | ||
|
||
always @(*) begin | ||
used_slot_update = 1'b0; | ||
rx_done_ctl = 1'b0; | ||
rx_count_reset_ctl = 1'b0; | ||
rx_count_inc_ctl = 1'b0; | ||
rxb_we_ctl = 1'b0; | ||
load_nibble = 2'b00; | ||
|
||
next_state = state; | ||
case(state) | ||
IDLE: begin | ||
used_slot_update = 1'b1; | ||
if(phy_dv) begin | ||
rx_count_reset_ctl = 1'b1; | ||
used_slot_update = 1'b0; | ||
load_nibble = 2'b01; | ||
next_state = LOAD_HI; | ||
end | ||
end | ||
LOAD_LO: begin | ||
rxb_we_ctl = 1'b1; | ||
rx_count_inc_ctl = 1'b1; | ||
if(phy_dv) begin | ||
load_nibble = 2'b01; | ||
next_state = LOAD_HI; | ||
end else begin | ||
rx_done_ctl = 1'b1; | ||
next_state = TERMINATE; | ||
end | ||
end | ||
LOAD_HI: begin | ||
if(phy_dv) begin | ||
load_nibble = 2'b10; | ||
next_state = LOAD_LO; | ||
end else begin | ||
rx_done_ctl = 1'b1; | ||
next_state = TERMINATE; | ||
end | ||
end | ||
TERMINATE: begin | ||
used_slot_update = 1'b1; | ||
next_state = IDLE; | ||
end | ||
endcase | ||
end | ||
|
||
endmodule |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
/* | ||
* Milkymist SoC | ||
* Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Sebastien Bourdeauducq | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation, version 3 of the License. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
module minimac3_sync( | ||
input sys_clk, | ||
input phy_rx_clk, | ||
input phy_tx_clk, | ||
|
||
input [1:0] sys_rx_ready, | ||
output [1:0] sys_rx_done, | ||
output reg [10:0] sys_rx_count_0, | ||
output reg [10:0] sys_rx_count_1, | ||
|
||
input sys_tx_start, | ||
output sys_tx_done, | ||
input [10:0] sys_tx_count, | ||
|
||
output [1:0] phy_rx_ready, | ||
input [1:0] phy_rx_done, | ||
input [10:0] phy_rx_count_0, | ||
input [10:0] phy_rx_count_1, | ||
|
||
output phy_tx_start, | ||
input phy_tx_done, | ||
output reg [10:0] phy_tx_count | ||
); | ||
|
||
psync rx_ready_0( | ||
.clk1(sys_clk), | ||
.i(sys_rx_ready[0]), | ||
.clk2(phy_rx_clk), | ||
.o(phy_rx_ready[0]) | ||
); | ||
psync rx_ready_1( | ||
.clk1(sys_clk), | ||
.i(sys_rx_ready[1]), | ||
.clk2(phy_rx_clk), | ||
.o(phy_rx_ready[1]) | ||
); | ||
psync rx_done_0( | ||
.clk1(phy_rx_clk), | ||
.i(phy_rx_done[0]), | ||
.clk2(sys_clk), | ||
.o(sys_rx_done[0]) | ||
); | ||
psync rx_done_1( | ||
.clk1(phy_rx_clk), | ||
.i(phy_rx_done[1]), | ||
.clk2(sys_clk), | ||
.o(sys_rx_done[1]) | ||
); | ||
reg [10:0] sys_rx_count_0_r; | ||
reg [10:0] sys_rx_count_1_r; | ||
always @(posedge sys_clk) begin | ||
sys_rx_count_0_r <= phy_rx_count_0; | ||
sys_rx_count_0 <= sys_rx_count_0_r; | ||
sys_rx_count_1_r <= phy_rx_count_1; | ||
sys_rx_count_1 <= sys_rx_count_1_r; | ||
end | ||
|
||
psync tx_start( | ||
.clk1(sys_clk), | ||
.i(sys_tx_start), | ||
.clk2(phy_tx_clk), | ||
.o(phy_tx_start) | ||
); | ||
psync tx_done( | ||
.clk1(phy_tx_clk), | ||
.i(phy_tx_done), | ||
.clk2(sys_clk), | ||
.o(sys_tx_done) | ||
); | ||
reg [10:0] phy_tx_count_r; | ||
always @(posedge phy_tx_clk) begin | ||
phy_tx_count_r <= sys_tx_count; | ||
phy_tx_count <= phy_tx_count_r; | ||
end | ||
|
||
endmodule |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
/* | ||
* Milkymist SoC | ||
* Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Sebastien Bourdeauducq | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation, version 3 of the License. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
module minimac3_tx( | ||
input phy_tx_clk, | ||
|
||
input tx_start, | ||
output reg tx_done, | ||
input [10:0] tx_count, | ||
input [7:0] txb_dat, | ||
output [10:0] txb_adr, | ||
|
||
output reg phy_tx_en, | ||
output reg [3:0] phy_tx_data | ||
); | ||
|
||
reg phy_tx_en_r; | ||
reg phy_tx_data_sel; | ||
wire [3:0] phy_tx_data_r = phy_tx_data_sel ? txb_dat[7:4] : txb_dat[3:0]; | ||
always @(posedge phy_tx_clk) begin | ||
phy_tx_en <= phy_tx_en_r; | ||
phy_tx_data <= phy_tx_data_r; | ||
end | ||
|
||
reg [10:0] byte_count; | ||
reg byte_count_reset; | ||
reg byte_count_inc; | ||
always @(posedge phy_tx_clk) begin | ||
if(byte_count_reset) | ||
byte_count <= 11'd0; | ||
else if(byte_count_inc) | ||
byte_count <= byte_count + 11'd1; | ||
end | ||
assign txb_adr = byte_count; | ||
wire byte_count_max = byte_count == tx_count; | ||
|
||
parameter IDLE = 2'd0; | ||
parameter SEND_LO = 2'd1; | ||
parameter SEND_HI = 2'd2; | ||
parameter TERMINATE = 2'd3; | ||
|
||
reg [1:0] state; | ||
reg [1:0] next_state; | ||
|
||
initial state <= IDLE; | ||
always @(posedge phy_tx_clk) | ||
state <= next_state; | ||
|
||
always @(*) begin | ||
phy_tx_en_r = 1'b0; | ||
phy_tx_data_sel = 1'b0; | ||
byte_count_reset = 1'b0; | ||
byte_count_inc = 1'b0; | ||
tx_done = 1'b0; | ||
|
||
next_state = state; | ||
|
||
case(state) | ||
IDLE: begin | ||
byte_count_reset = 1'b1; | ||
if(tx_start) | ||
next_state = SEND_LO; | ||
end | ||
SEND_LO: begin | ||
byte_count_inc = 1'b1; | ||
phy_tx_en_r = 1'b1; | ||
phy_tx_data_sel = 1'b0; | ||
next_state = SEND_HI; | ||
end | ||
SEND_HI: begin | ||
phy_tx_en_r = 1'b1; | ||
phy_tx_data_sel = 1'b1; | ||
if(byte_count_max) | ||
next_state = TERMINATE; | ||
else | ||
next_state = SEND_LO; | ||
end | ||
TERMINATE: begin | ||
byte_count_reset = 1'b1; | ||
tx_done = 1'b1; | ||
next_state = IDLE; | ||
end | ||
endcase | ||
end | ||
|
||
endmodule |