diff options
author | matt <matt@221aa14e-8319-0410-a670-987f0aec2ac5> | 2009-01-31 23:43:37 +0000 |
---|---|---|
committer | matt <matt@221aa14e-8319-0410-a670-987f0aec2ac5> | 2009-01-31 23:43:37 +0000 |
commit | db3a21e18e2409eca0e90247b189f411ab7d7a86 (patch) | |
tree | 1ed15f81cae4a3b3ef16b9d55aabefdeafa6a872 /control_lib | |
parent | fd9343dd434b52e0194c547b12324a9c3dbe6ce7 (diff) | |
download | uhd-db3a21e18e2409eca0e90247b189f411ab7d7a86.tar.gz uhd-db3a21e18e2409eca0e90247b189f411ab7d7a86.tar.bz2 uhd-db3a21e18e2409eca0e90247b189f411ab7d7a86.zip |
work in progress
git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@10358 221aa14e-8319-0410-a670-987f0aec2ac5
Diffstat (limited to 'control_lib')
-rw-r--r-- | control_lib/giantfifo.v | 209 | ||||
-rw-r--r-- | control_lib/giantfifo_tb.v | 173 |
2 files changed, 382 insertions, 0 deletions
diff --git a/control_lib/giantfifo.v b/control_lib/giantfifo.v new file mode 100644 index 000000000..dba330b8a --- /dev/null +++ b/control_lib/giantfifo.v @@ -0,0 +1,209 @@ + + + +module giantfifo + #(parameter WIDTH=36) + (input clk, input rst, + input [WIDTH-1:0] datain, + output [WIDTH-1:0] dataout, + input read, + input write, + input clear, + output full, + output empty, + output [15:0] space, + output [15:0] occupied, + + // External RAM + inout [17:0] RAM_D, + output reg [18:0] RAM_A, + output RAM_CE1n, + output RAM_CENn, + output reg RAM_CLK, + output reg RAM_WEn, + output RAM_OEn, + output RAM_LDn + ); + + wire [4:0] path1_occ, path2_space; + wire [35:0] path1_dat, path2_dat; + + shortfifo #(.WIDTH(WIDTH)) sf1 + (.clk(clk),.rst(rst),.clear(clear), + .datain(datain),.write(write),.full(full), + .dataout(path1_dat),.read(path1_read),.empty(path1_empty), + .space(),.occupied(path1_occ) ); + wire path1_almost_empty = (path1_occ == 5'd1); + + shortfifo #(.WIDTH(WIDTH)) sf2 + (.clk(clk),.rst(rst),.clear(clear), + .datain(path2_dat),.write(path2_write),.full(path2_full), + .dataout(dataout),.read(read),.empty(empty), + .space(path2_space),.occupied() ); + wire path2_almost_full = (path2_space == 5'd1); + + assign RAM_CE1n = 1'b0; + assign RAM_CENn = 1'b0; + always @(clk) + RAM_CLK <= #2 clk; + assign RAM_LDn = 1'b0; + + // State machine + wire write_now, read_now, idle, phase; + reg ram_full, ram_empty; + + reg [17:0] read_ptr, write_ptr; + reg [2:0] zbt_state; + + localparam ZBT_IDLE = 0; + localparam ZBT_WRITE_UPPER = 2; + localparam ZBT_WRITE_LOWER = 3; + localparam ZBT_READ_UPPER = 4; + localparam ZBT_READ_LOWER = 5; + + wire can_write = ~ram_full & ~path1_empty; + wire can_write_chain = can_write & ~path1_almost_empty; + + wire can_read = ~ram_empty & ~path2_full; + wire can_read_chain = can_read & ~path2_almost_full; + + assign phase = zbt_state[0]; + + reg [17:0] ram_occupied; + wire ram_almost_empty = (write_ptr == (read_ptr+1'b1)); + wire ram_almost_full = ((write_ptr+1'b1) == read_ptr); + + always @(posedge clk) + if(rst | clear) + begin + zbt_state <= ZBT_IDLE; + write_ptr <= 0; + read_ptr <= 0; + ram_full <= 0; + ram_empty <= 1; + ram_occupied <= 0; + end + else + case(zbt_state) + ZBT_IDLE : + if(can_read) + zbt_state <= ZBT_READ_UPPER; + else if(can_write) + zbt_state <= ZBT_WRITE_UPPER; + + ZBT_WRITE_UPPER : + begin + zbt_state <= ZBT_WRITE_LOWER; + ram_occupied <= ram_occupied + 1; + ram_empty <= 0; + if(ram_occupied == 18'd10) + ram_full <= 1; + end + ZBT_WRITE_LOWER : + begin + write_ptr <= write_ptr + 1; + if(can_read_chain) + zbt_state <= ZBT_READ_UPPER; + else if(can_write_chain) + zbt_state <= ZBT_WRITE_UPPER; + else + zbt_state <= ZBT_IDLE; + end + ZBT_READ_UPPER : + begin + zbt_state <= ZBT_READ_LOWER; + ram_occupied <= ram_occupied - 1; + ram_full <= 0; + if(ram_occupied == 18'd1) + ram_empty <= 1; + end + ZBT_READ_LOWER : + begin + read_ptr <= read_ptr + 1; + if(can_read_chain) + zbt_state <= ZBT_READ_UPPER; + else if(can_write_chain) + zbt_state <= ZBT_WRITE_UPPER; + else + zbt_state <= ZBT_IDLE; + end + default : + zbt_state <= ZBT_IDLE; + endcase // case(zbt_state) + + // Need to generate RAM_WEn, RAM_OEn, RAM_D, RAM_A; + assign path1_read = (zbt_state == ZBT_WRITE_LOWER); + reg path2_write, delayed_read_upper, delayed_read_lower, delayed_write; + + always @(posedge clk) + if(delayed_read_upper) + path2_dat[35:18] <= RAM_D; + always @(posedge clk) + if(delayed_read_lower) + path2_dat[17:0] <= RAM_D; + + always @(posedge clk) + if(rst) + begin + delayed_read_upper <= 0; + delayed_read_lower <= 0; + path2_write <= 0; + end + else + begin + delayed_read_upper <= (zbt_state == ZBT_READ_LOWER); + delayed_read_lower <= delayed_read_upper; + path2_write <= delayed_read_lower; + end + + reg [17:0] RAM_D_pre2, RAM_D_pre1, RAM_D_out; + + always @(posedge clk) + RAM_D_pre2 <= phase ? path1_dat[17:0] : path1_dat[35:18]; + + always @(posedge clk) RAM_D_pre1 <= RAM_D_pre2; + always @(posedge clk) RAM_D_out <= RAM_D_pre1; + reg wr_del_1, wr_del_2; + always @(posedge clk) + if(rst) + begin + wr_del_1 <= 0; + wr_del_2 <= 0; + delayed_write <= 0; + end + else + begin + delayed_write <= wr_del_2; + wr_del_2 <= wr_del_1; + wr_del_1 <= write_now; + end + + reg delayed_read, rd_del_1, rd_del_2; + always @(posedge clk) + if(rst) + begin + rd_del_1 <= 0; + rd_del_2 <= 0; + delayed_read <= 0; + end + else + begin + delayed_read <= rd_del_2; + rd_del_2 <= rd_del_1; + rd_del_1 <= read_now; + end + + assign RAM_D = delayed_write ? RAM_D_out : 18'bzzzzzzzzzzzzzzzzzz; + assign write_now = (zbt_state == ZBT_WRITE_UPPER) || (zbt_state == ZBT_WRITE_LOWER); + assign read_now = (zbt_state == ZBT_READ_UPPER) || (zbt_state == ZBT_READ_LOWER); + + always @(posedge clk) + RAM_A <= write_now ? {write_ptr,phase} : {read_ptr,phase}; + + always @(posedge clk) + RAM_WEn <= ~write_now; + + assign RAM_OEn = ~delayed_read; + assign RAM_OEn = 0; + +endmodule // giantfifo diff --git a/control_lib/giantfifo_tb.v b/control_lib/giantfifo_tb.v new file mode 100644 index 000000000..87ecd97ae --- /dev/null +++ b/control_lib/giantfifo_tb.v @@ -0,0 +1,173 @@ +module fifo_tb(); + + localparam WIDTH = 36; + reg clk, rst; + wire short_full, short_empty, long_full, long_empty, giant_full, giant_empty; + wire casc_full, casc_empty, casc2_full, casc2_empty; + reg read, write; + + wire [WIDTH-1:0] short_do, long_do, casc_do, casc2_do, giant_do; + reg [WIDTH-1:0] di; + + reg clear = 0; + + shortfifo #(.WIDTH(WIDTH)) shortfifo + (.clk(clk),.rst(rst),.datain(di),.dataout(short_do),.clear(clear), + .read(read),.write(write),.full(short_full),.empty(short_empty)); + + longfifo #(.WIDTH(WIDTH), .SIZE(4)) longfifo + (.clk(clk),.rst(rst),.datain(di),.dataout(long_do),.clear(clear), + .read(read),.write(write),.full(long_full),.empty(long_empty)); + + cascadefifo #(.WIDTH(WIDTH), .SIZE(4)) cascadefifo + (.clk(clk),.rst(rst),.datain(di),.dataout(casc_do),.clear(clear), + .read(read),.write(write),.full(casc_full),.empty(casc_empty)); + + cascadefifo2 #(.WIDTH(WIDTH), .SIZE(4)) cascadefifo2 + (.clk(clk),.rst(rst),.datain(di),.dataout(casc2_do),.clear(clear), + .read(read),.write(write),.full(casc2_full),.empty(casc2_empty)); + + wire [17:0] RAM_D; + wire [18:0] RAM_A; + wire RAM_CLK, RAM_WEn, RAM_LDn, RAM_CE1n, RAM_OEn, RAM_CENn; + + giantfifo #(.WIDTH(WIDTH)) giantfifo + (.clk(clk),.rst(rst),.datain(di),.dataout(giant_do),.clear(clear), + .read(read),.write(write),.full(giant_full),.empty(giant_empty), + .RAM_D(RAM_D),.RAM_A(RAM_A),.RAM_CE1n(RAM_CE1n),.RAM_CENn(RAM_CENn), + .RAM_CLK(RAM_CLK),.RAM_WEn(RAM_WEn),.RAM_OEn(RAM_OEn),.RAM_LDn(RAM_LDn) + ); + + wire MODE = 1'b0; + cy1356 ram_model(.d(RAM_D),.clk(RAM_CLK),.a(RAM_A), + .bws(2'b00),.we_b(RAM_WEn),.adv_lb(RAM_LDn), + .ce1b(RAM_CE1n),.ce2(1'b1),.ce3b(1'b0), + .oeb(RAM_OEn),.cenb(RAM_CENn),.mode(MODE) + ); + + initial rst = 1; + initial #1000 rst = 0; + initial clk = 0; + always #50 clk = ~clk; + + initial di = 36'h300AE; + initial read = 0; + initial write = 0; + + always @(posedge clk) + if(write) + di <= di + 1; + + always @(posedge clk) + begin + if(short_full != long_full) + $display("Error: FULL mismatch"); + if(short_empty != long_empty) + $display("Note: EMPTY mismatch, usually not a problem (longfifo has 2 cycle latency)"); + if(read & (short_do != long_do)) + $display("Error: DATA mismatch"); + end + + initial $dumpfile("giantfifo_tb.vcd"); + initial $dumpvars(0,fifo_tb); + + initial + begin + @(negedge rst); + @(posedge clk); + repeat (10) + @(posedge clk); + write <= 1; + @(posedge clk); + write <= 0; + @(posedge clk); + @(posedge clk); + @(posedge clk); + @(posedge clk); + @(posedge clk); + @(posedge clk); + @(posedge clk); + @(posedge clk); + read <= 1; + @(posedge clk); + read <= 0; + @(posedge clk); + @(posedge clk); + @(posedge clk); + @(posedge clk); + @(posedge clk); + + repeat(10) + begin + write <= 1; + @(posedge clk); + write <= 0; + @(posedge clk); + @(posedge clk); + @(posedge clk); + read <= 1; + @(posedge clk); + read <= 0; + @(posedge clk); + @(posedge clk); + @(posedge clk); + @(posedge clk); + @(posedge clk); + end // repeat (10) + + write <= 1; + repeat (4) + @(posedge clk); + write <= 0; + @(posedge clk); + read <= 1; + repeat (4) + @(posedge clk); + read <= 0; + @(posedge clk); + + + write <= 1; + repeat (4) + @(posedge clk); + write <= 0; + @(posedge clk); + repeat (4) + begin + read <= 1; + @(posedge clk); + read <= 0; + @(posedge clk); + end + + write <= 1; + @(posedge clk); + @(posedge clk); + @(posedge clk); + @(posedge clk); + read <= 1; + repeat (5) + @(posedge clk); + write <= 0; + @(posedge clk); + @(posedge clk); + read <= 0; + @(posedge clk); + + write <= 1; + repeat (16) + @(posedge clk); + write <= 0; + @(posedge clk); + + read <= 1; + repeat (16) + @(posedge clk); + read <= 0; + @(posedge clk); + + repeat (10) + @(posedge clk); + $finish; + end +endmodule // longfifo_tb |