/********************************************** _ _ Cook Darwin __
_ descript: author : Cook.Darwin Version: VERA.0.0 creaded: 2017/4/20 madified: ***********************************************/ `timescale 1ns/1ps module odd_width_convert #(
parameter ISIZE = 12, parameter OSIZE = 16
)(
input clock, input rst_n, input [ISIZE-1:0] wr_data, input wr_vld, output logic wr_ready, input wr_last, // input wr_align_last, //can be leave 1'b0 output logic[OSIZE-1:0] rd_data, output logic rd_vld, input rd_ready, output logic rd_last
);
assign wr_ready = rd_ready;
initial begin
assert(ISIZE < OSIZE) else begin $error("ISIZE MUST BE MORE SMALLER THAN OSIZE\n"); $stop; end
end
logic [OSIZE*2-1:0] cache; logic [$clog2(OSIZE*2)-1:0] cache_point; // logic [$clog2(OSIZE*2)-1:0] cache_rev_point; logic [1:0] cache_vld;
logic [OSIZE*2-1:0] cache_rev; logic [1:0] cache_last;
// assign cache_rev = {cache,cache};
always@(posedge clock,negedge rst_n)
if(~rst_n) cache_point <= '0; else begin if(wr_vld && wr_ready)begin if(wr_last) cache_point <= '0; else if(cache_point+ISIZE < OSIZE*2) cache_point <= cache_point + ISIZE; else cache_point <= (cache_point + ISIZE)-OSIZE*2; end else begin /* if(rd_vld && rd_ready && rd_last) cache_point <= '0; else */ cache_point <= cache_point; end end
// always@(posedge clock,negedge rst_n) // if(~rst_n) cache_rev_point <= OSIZE; // else begin // if(wr_vld && wr_ready)begin // if(cache_rev+ISIZE+OSIZE< OSIZE*2) // cache_rev_point <= cache_point + ISIZE + OSIZE; // else cache_rev_point <= (cache_point + ISIZE + OSIZE)-OSIZE*2; // end else begin // cache_rev_point <= cache_rev_point; // end // end
// logic [OSIZE*2-1:0] tmp_cache;
always_comb begin
cache_rev[OSIZE*2-1-(cache_point+ISIZE - OSIZE*2)-:ISIZE] = wr_data;
end
logic [ISIZE-1:0] rev_wr_data;
always_comb begin
foreach(wr_data[i]) rev_wr_data[ISIZE-1-i] = wr_data[i];
end
logic flag; always@(posedge clock,negedge rst_n)
if(~rst_n) cache <= '0; else begin if(wr_vld && wr_ready)begin if(cache_point+ISIZE < OSIZE*2)begin cache[OSIZE*2-1-cache_point-:ISIZE] <= wr_data; flag <= 0; // else cache <= {cache_rev[OSIZE-1:0],cache_rev[2*OSIZE-1:OSIZE]}; end else begin flag <= 1; // {cache[OSIZE-1:0],cache[2*OSIZE-1:OSIZE]}[OSIZE*2-1-(cache_point+ISIZE - OSIZE*2)-:ISIZE] <= wr_data; foreach(rev_wr_data[i])begin if(cache_point+i<OSIZE*2) cache[OSIZE*2-1-(cache_point+i)] <= rev_wr_data[i]; else cache[OSIZE*2-1-(cache_point+i-2*OSIZE)] <= rev_wr_data[i]; end end end else cache <= cache; end
// logic last_record; // // always@(posedge clock,negedge rst_n) // if(~rst_n) last_record <= 1'b0; // else begin // if(wr_vld && wr_ready && wr_last) // last_record <= 1'b1; // else if(last_record && wr_ready) // last_record <= 1'b0; // else last_record <= last_record; // end
always@(posedge clock,negedge rst_n)
if(~rst_n) cache_vld[0] <= 1'b0; else begin if(wr_vld && wr_ready)begin if(cache_point+ISIZE >= OSIZE && cache_point<OSIZE) cache_vld[0] <= 1'b1; else if(wr_last && (cache_point+ISIZE>2*OSIZE || cache_point+ISIZE <= OSIZE)) cache_vld[0] <= 1'b1; else begin cache_vld[0] <= 1'b0; end end else if(cache_vld[0] && rd_ready && (!(cache_vld[1]&&cache_last[0]))) cache_vld[0] <= 1'b0; else cache_vld[0] <= cache_vld[0]; end
always@(posedge clock,negedge rst_n)
if(~rst_n) cache_vld[1] <= 1'b0; else begin if(wr_vld && wr_ready)begin if(cache_point+ISIZE >= 2*OSIZE && cache_point>=OSIZE) cache_vld[1] <= 1'b1; else if(wr_last && cache_point+ISIZE > OSIZE) cache_vld[1] <= 1'b1; else cache_vld[1] <= 1'b0; end else if(cache_vld[1] && rd_ready && (!(cache_vld[0]&&cache_last[1])) ) cache_vld[1] <= 1'b0; else cache_vld[1] <= cache_vld[1]; end
always@(posedge clock,negedge rst_n)
if(~rst_n) cache_last[0] <= 1'b0; else begin if(wr_vld && wr_ready)begin if(wr_last && (cache_point+ISIZE>2*OSIZE || cache_point+ISIZE <= OSIZE)) cache_last[0] <= 1'b1; else cache_last[0] <= 1'b0; end else if(cache_vld[0] && rd_ready && cache_last[0] && !cache_vld[1]) cache_last[0] <= 1'b0; else if(cache_last == 2'b11) cache_last[0] <= 1'b0; else cache_last[0] <= cache_last[0]; end
always@(posedge clock,negedge rst_n)
if(~rst_n) cache_last[1] <= 1'b0; else begin if(wr_vld && wr_ready)begin if(wr_last && cache_point+ISIZE>OSIZE) cache_last[1] <= 1'b1; else cache_last[1] <= 1'b0; end else if(cache_vld[1] && rd_ready && cache_last[1] && !cache_vld[0]) cache_last[1] <= 1'b0; else cache_last[1] <= cache_last[1]; end
//—>> MEDUIM LEVEL <<———————————- logic in_m_vld; logic [OSIZE-1:0] in_m_data; logic in_m_last;
assign in_m_vld = |cache_vld; assign in_m_last = |cache_last && ^cache_vld;
always_comb begin
if(&cache_vld)begin if(cache_last[0]) in_m_data = cache[OSIZE-1:0]; else in_m_data = cache[2*OSIZE-1:OSIZE]; end else begin if(cache_vld[1]) in_m_data = cache[OSIZE-1:0]; else in_m_data = cache[2*OSIZE-1:OSIZE]; end
end
//—<< MEDUIM LEVEL >>———————————- always@(posedge clock,negedge rst_n)
if(~rst_n) rd_vld <= 1'b0; else begin if(in_m_vld && rd_ready) rd_vld <= 1'b1; else if(rd_vld && rd_ready) rd_vld <= 1'b0; else rd_vld <= rd_vld; end
always@(posedge clock,negedge rst_n)
if(~rst_n) rd_data <= '0; else begin if(in_m_vld && rd_ready) rd_data <= in_m_data; else rd_data <= rd_data; end
always@(posedge clock,negedge rst_n)
if(~rst_n) rd_last <= 1'b0; else begin if(in_m_vld && rd_ready && in_m_last) rd_last <= 1'b1; else if(rd_vld && rd_ready && rd_last) rd_last <= 1'b0; else rd_last <= rd_last; end
endmodule