Init repo
This commit is contained in:
@@ -0,0 +1,341 @@
|
||||
`timescale 1ns / 1ns
|
||||
|
||||
// *******************************************************
|
||||
// * ███████╗ ██████╗ ██████╗ ██████╗ ██████╗ ██╗ ██╗ *
|
||||
// * ╚══███╔╝██╔═══██╗██╔══██╗██╔═══██╗██╔════╝ ██║ ██║ *
|
||||
// * ███╔╝ ██║ ██║██████╔╝██║ ██║██║ ███╗███████║ *
|
||||
// * ███╔╝ ██║ ██║██╔══██╗██║ ██║██║ ██║██╔══██║ *
|
||||
// * ███████╗╚██████╔╝██║ ██║╚██████╔╝╚██████╔╝██║ ██║ *
|
||||
// * ╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ *
|
||||
// *******************************************************
|
||||
// * this module get data from the ps ( a axis-fifo in fact)
|
||||
// * and then use the ldpc algorithm to encode the data, which
|
||||
// * is 16 bit parallel, then it dose a width convert to
|
||||
// * 2 bit (i and q) , add a prefix which is 8 sym len. finally,
|
||||
// * send the data with prefix to a fifo (2 bit width, ditributed ram),
|
||||
// * waiting the transmitter to fetch
|
||||
// *
|
||||
// * later update (2024/5/14):
|
||||
// * we find the 16bit parallel cost too much resource, so we change it
|
||||
// * to 1bit serial module,
|
||||
// * 该模块首先将输入的数据32bit数据进行位宽转换为1bit数据,输入到ldpc模块中进行编码
|
||||
// * 然后将ldpc模块通过fifo进行位宽转换成2bit数据(Q,I),然后添加循环前缀(8个符号)
|
||||
// * 送入到fifo_enc_out中,并结束。
|
||||
// *
|
||||
// * Q : 何时开始编码?
|
||||
// * A : 前端有数据下发,且该模块是输出fifo模块中数据不足(<200syms)才进行编码。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
module enc_control #(
|
||||
parameter ENC_IN_LEN = 1024,
|
||||
parameter ENC_OUT_LEN = 2048,
|
||||
parameter INPUT_DATA_WIDTH = 32
|
||||
) (
|
||||
input clk,
|
||||
input rst,
|
||||
//from ps axis-fifo
|
||||
input s_axis_fifo_tvalid,
|
||||
output reg s_axis_fifo_tready,
|
||||
input [INPUT_DATA_WIDTH - 1:0] s_axis_fifo_tdata,
|
||||
input [ 31:0] data_src_count,
|
||||
// fifo signal
|
||||
input wire fifo_enc_out_rd_clk,
|
||||
input wire fifo_enc_out_rd_en,
|
||||
output wire [ 31:0] fifo_enc_out_dout_map,
|
||||
output wire fifo_enc_out_empty
|
||||
);
|
||||
|
||||
|
||||
// ******** Wire & Reg ********
|
||||
|
||||
localparam CNT_IN_MAX = ENC_IN_LEN / INPUT_DATA_WIDTH;
|
||||
localparam CNT_IN_WIDTH = $clog2(CNT_IN_MAX);
|
||||
localparam CNT_OUT_MAX = ENC_OUT_LEN;
|
||||
localparam CNT_OUT_WIDTH = $clog2(CNT_OUT_MAX); // 多留1bit
|
||||
|
||||
// status
|
||||
localparam [3:0] S_IDLE = 4'd0;
|
||||
localparam [3:0] S_START = 4'd1;
|
||||
localparam [3:0] S_WAIT_LDPC_OUT = 4'd2;
|
||||
localparam [3:0] S_WAIT_ADD_PREFIX_DONE = 4'd3;
|
||||
|
||||
reg [ 3:0] cs;
|
||||
reg [ 3:0] ns;
|
||||
|
||||
// input data width convert
|
||||
reg wc_data_in_valid;
|
||||
wire wc_data_in_ready;
|
||||
wire [ 31:0] wc_data_in;
|
||||
wire wc_data_out_valid;
|
||||
wire wc_data_out;
|
||||
|
||||
// ldpc io signal
|
||||
reg ldpc_in_start;
|
||||
reg ldpc_in_valid;
|
||||
wire ldpc_out_start;
|
||||
wire ldpc_out_valid;
|
||||
wire ldpc_dout;
|
||||
|
||||
// ldpc io cnt
|
||||
reg [ CNT_IN_WIDTH : 0] cnt_in; // 多留1bit
|
||||
reg [CNT_OUT_WIDTH : 0] cnt_out; // 多留1bit
|
||||
|
||||
// map
|
||||
wire [ 1:0] fifo_enc_out_dout;
|
||||
wire [ 15:0] fifo_enc_out_dout_i;
|
||||
wire [ 15:0] fifo_enc_out_dout_q;
|
||||
wire fifo_enc_out_almost_empty;
|
||||
wire fifo_enc_out_prog_empty_1x; // 20 sym
|
||||
wire fifo_enc_out_prog_empty; // 20 sym
|
||||
|
||||
// control the fifo width convert read channel
|
||||
wire fifo_wc_prog_full;
|
||||
reg fifo_wc_prog_full_d1;
|
||||
wire fifo_wc_empty;
|
||||
reg add_prefix_start;
|
||||
|
||||
// signal for add_prefix
|
||||
reg [ 2:0] cnt_add_prefix_in;
|
||||
wire add_prefix_in_ready;
|
||||
wire [ 1:0] data_add_prefix_in;
|
||||
wire data_add_prefix_in_ready;
|
||||
wire [ 1:0] data_add_prefix_out;
|
||||
wire data_add_prefix_out_valid;
|
||||
|
||||
// ******** Assingment ********
|
||||
|
||||
assign fifo_enc_out_dout_i = (fifo_enc_out_dout[0] == 1'b0) ? 16'h7FFF : 16'h8001;
|
||||
assign fifo_enc_out_dout_q = (fifo_enc_out_dout[1] == 1'b0) ? 16'h7FFF : 16'h8001;
|
||||
assign fifo_enc_out_dout_map = {fifo_enc_out_dout_q, fifo_enc_out_dout_i};
|
||||
assign wc_data_in = s_axis_fifo_tdata;
|
||||
|
||||
// ******** Logic Block ********
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst == 1'b1) begin
|
||||
cs <= S_IDLE;
|
||||
end
|
||||
else begin
|
||||
cs <= ns;
|
||||
end
|
||||
end
|
||||
|
||||
// fsm
|
||||
always @(*) begin
|
||||
// NOTE: S_IDLE --> START (width convert --> encoding module) --> wait output done --> IDLE
|
||||
case (cs)
|
||||
S_IDLE: begin
|
||||
// ! attention
|
||||
// if source is valid which means there are data waiting for encoding
|
||||
// and the pre-stage fifo counts not equal 0
|
||||
// and the width convert fifo is empty
|
||||
// and the finally stage fifo is almost empty
|
||||
// TODO:check the conditions, done 2024年5月27日
|
||||
if (s_axis_fifo_tvalid && data_src_count != 0 && fifo_enc_out_prog_empty && ~data_add_prefix_in_ready && ~data_add_prefix_out_valid) begin
|
||||
ns = S_START;
|
||||
end
|
||||
else begin
|
||||
ns = S_IDLE;
|
||||
end
|
||||
end
|
||||
|
||||
S_START: begin
|
||||
ns = S_WAIT_LDPC_OUT;
|
||||
end
|
||||
|
||||
S_WAIT_LDPC_OUT: begin
|
||||
if (cnt_out == CNT_OUT_MAX) begin
|
||||
ns = S_WAIT_ADD_PREFIX_DONE;
|
||||
end
|
||||
else begin
|
||||
ns = S_WAIT_LDPC_OUT;
|
||||
end
|
||||
end
|
||||
|
||||
S_WAIT_ADD_PREFIX_DONE: begin
|
||||
if (fifo_wc_empty && add_prefix_in_ready) begin
|
||||
ns = S_IDLE;
|
||||
end
|
||||
else begin
|
||||
ns = S_WAIT_ADD_PREFIX_DONE;
|
||||
end
|
||||
end
|
||||
default: begin
|
||||
ns = S_IDLE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
wc_data_in_valid <= 0;
|
||||
end
|
||||
else if (ns == S_START || cnt_in < CNT_IN_MAX && cs != S_IDLE) begin
|
||||
wc_data_in_valid <= s_axis_fifo_tvalid;
|
||||
end
|
||||
else begin
|
||||
wc_data_in_valid <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
always @(*) begin
|
||||
if (rst) begin
|
||||
s_axis_fifo_tready = 0;
|
||||
end
|
||||
else begin
|
||||
if (cs != S_IDLE && cnt_in < CNT_IN_MAX) begin
|
||||
s_axis_fifo_tready = wc_data_in_ready;
|
||||
end
|
||||
else begin
|
||||
s_axis_fifo_tready = 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(*) begin
|
||||
ldpc_in_start = (cs == S_START);
|
||||
ldpc_in_valid = wc_data_out_valid;
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (cs == S_IDLE) begin
|
||||
cnt_in <= 0;
|
||||
end
|
||||
else if (wc_data_in_ready && wc_data_in_valid) begin
|
||||
cnt_in <= cnt_in + 1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (ldpc_out_start || cnt_out > 0 && cnt_out <= CNT_OUT_MAX) begin
|
||||
cnt_out <= cnt_out + 1;
|
||||
end
|
||||
else begin
|
||||
cnt_out <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
// get the rising edge
|
||||
always @(posedge clk) begin
|
||||
fifo_wc_prog_full_d1 <= fifo_wc_prog_full;
|
||||
end
|
||||
|
||||
// shit code, no modify timing is in a mess
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
cnt_add_prefix_in <= 0;
|
||||
end
|
||||
else if (fifo_wc_prog_full & ~fifo_wc_prog_full_d1) begin
|
||||
cnt_add_prefix_in <= cnt_add_prefix_in + 1;
|
||||
end
|
||||
else if (add_prefix_start) begin
|
||||
if (cnt_add_prefix_in < 4) begin
|
||||
cnt_add_prefix_in <= cnt_add_prefix_in + 1;
|
||||
end
|
||||
else begin
|
||||
cnt_add_prefix_in <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
add_prefix_start <= 0;
|
||||
end
|
||||
else if (fifo_wc_prog_full & ~fifo_wc_prog_full_d1 || cnt_add_prefix_in > 0 && add_prefix_in_ready && ~add_prefix_start) begin
|
||||
add_prefix_start <= 1'b1;
|
||||
end
|
||||
else begin
|
||||
add_prefix_start <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// ******** Inst ********
|
||||
|
||||
width_convert #(
|
||||
.INPUT_WIDTH (32),
|
||||
.OUTPUT_WIDTH(1)
|
||||
) u_width_convert (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.data_in_valid (wc_data_in_valid),
|
||||
.data_in_ready (wc_data_in_ready),
|
||||
.data_in (wc_data_in),
|
||||
.data_out_valid(wc_data_out_valid),
|
||||
.data_out (wc_data_out)
|
||||
);
|
||||
|
||||
|
||||
// encoding module
|
||||
CCSDS_LDPC_ENC_R12 u_CCSDS_LDPC_ENC_R12 (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.Encoder_SyncIn (ldpc_in_start),
|
||||
.Encoder_Nd (ldpc_in_valid),
|
||||
.Encoder_Din (wc_data_out),
|
||||
.Encode_Dout (ldpc_dout),
|
||||
.Encode_Sync_Dout(ldpc_out_start),
|
||||
.Encode_Rdy (ldpc_out_valid)
|
||||
);
|
||||
|
||||
fifo_width_convert_1_2 u_fifo_width_convert_1_2 (
|
||||
.clk (clk), // input wire clk
|
||||
.srst (rst), // input wire srst
|
||||
.din (ldpc_dout), // input wire [0 : 0] din
|
||||
.wr_en (ldpc_out_valid), // input wire wr_en
|
||||
.rd_en (data_add_prefix_in_ready), // input wire rd_en
|
||||
.dout (data_add_prefix_in), // output wire [1 : 0] dout
|
||||
.full (), // output wire full
|
||||
.empty (fifo_wc_empty), // output wire empty
|
||||
.prog_full(fifo_wc_prog_full)
|
||||
);
|
||||
|
||||
|
||||
add_prefix #(
|
||||
.WIDTH (2), // ! if this parameter is changed, make sure the shift IP inside is also changed
|
||||
.DATA_LEN (256),
|
||||
.PREFIX_LEN(8)
|
||||
) u_add_prefix (
|
||||
.clk (clk),
|
||||
.start (add_prefix_start),
|
||||
.ready (add_prefix_in_ready),
|
||||
.data_in (data_add_prefix_in),
|
||||
.data_in_ready (data_add_prefix_in_ready),
|
||||
.data_out (data_add_prefix_out),
|
||||
.data_out_valid(data_add_prefix_out_valid)
|
||||
);
|
||||
|
||||
fifo_enc_out u_fifo_enc_out (
|
||||
.rst (rst), // input wire rst
|
||||
.wr_clk (clk), // input wire wr_clk
|
||||
.rd_clk (fifo_enc_out_rd_clk), // input wire rd_clk
|
||||
.din (data_add_prefix_out), // input wire [1 : 0] din
|
||||
.wr_en (data_add_prefix_out_valid), // input wire wr_en
|
||||
.rd_en (fifo_enc_out_rd_en), // input wire rd_en
|
||||
.dout (fifo_enc_out_dout), // output wire [1 : 0] dout
|
||||
.full (), // output wire full
|
||||
.empty (fifo_enc_out_empty), // output wire empty
|
||||
.almost_empty(fifo_enc_out_almost_empty), // output wire almost_empty
|
||||
.prog_empty (fifo_enc_out_prog_empty_1x) // output wire prog_empty
|
||||
);
|
||||
|
||||
xpm_cdc_single #(
|
||||
.DEST_SYNC_FF (4), // DECIMAL; range: 2-10
|
||||
.INIT_SYNC_FF (0), // DECIMAL; 0=disable simulation init values, 1=enable simulation init values
|
||||
.SIM_ASSERT_CHK(0), // DECIMAL; 0=disable simulation messages, 1=enable simulation messages
|
||||
.SRC_INPUT_REG (1) // DECIMAL; 0=do not register input, 1=register input
|
||||
) xpm_cdc_single_inst (
|
||||
.dest_out(fifo_enc_out_prog_empty), // 1-bit output: src_in synchronized to the destination clock domain. This output is registered.
|
||||
.dest_clk(clk), // 1-bit input: Clock signal for the destination clock domain.
|
||||
.src_clk (fifo_enc_out_rd_clk), // 1-bit input: optional; required when SRC_INPUT_REG = 1
|
||||
.src_in (fifo_enc_out_prog_empty_1x) // 1-bit input: Input signal to be synchronized to dest_clk domain.
|
||||
);
|
||||
|
||||
|
||||
// ******** Debug ********
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user