From 4487a342c43ba47c132c1e32a48e9ffd4aeefcff Mon Sep 17 00:00:00 2001 From: "amit.b" Date: Fri, 30 Apr 2021 10:00:06 +0530 Subject: [PATCH] PBCH_ENCODER --- AXI4_Master_Stream.sv | 234 ++++++++++++++++++++++++++ AXI4_Slave_Stream.sv | 159 +++++++++++++++++ PBCH_Defines.vh | 10 ++ PBCH_POLAR_ENCODER_IP.sv | 105 ++++++++++++ Register.sv | 45 +++++ encoder_bit_selection_rtl.sv | 61 +++++++ encoder_core_rtl.sv | 55 ++++++ encoder_crc_attachment_rtl.sv | 86 ++++++++++ encoder_crc_interleaving_rtl.sv | 77 +++++++++ encoder_frozen_bit_insertion_rtl1.sv | 168 ++++++++++++++++++ encoder_sub_block_interleaving_rtl.sv | 78 +++++++++ encoder_top_rtl.sv | 127 ++++++++++++++ generic_fifo.v | 226 +++++++++++++++++++++++++ simple_dual_port_ram.v | 28 +++ 14 files changed, 1459 insertions(+) create mode 100644 AXI4_Master_Stream.sv create mode 100644 AXI4_Slave_Stream.sv create mode 100644 PBCH_Defines.vh create mode 100644 PBCH_POLAR_ENCODER_IP.sv create mode 100644 Register.sv create mode 100644 encoder_bit_selection_rtl.sv create mode 100644 encoder_core_rtl.sv create mode 100644 encoder_crc_attachment_rtl.sv create mode 100644 encoder_crc_interleaving_rtl.sv create mode 100644 encoder_frozen_bit_insertion_rtl1.sv create mode 100644 encoder_sub_block_interleaving_rtl.sv create mode 100644 encoder_top_rtl.sv create mode 100644 generic_fifo.v create mode 100644 simple_dual_port_ram.v diff --git a/AXI4_Master_Stream.sv b/AXI4_Master_Stream.sv new file mode 100644 index 0000000..e8dfaac --- /dev/null +++ b/AXI4_Master_Stream.sv @@ -0,0 +1,234 @@ + +`timescale 1 ns / 1 ps +////////////////////////////////////////////////////////////////////////////////// +// Company: BITSILICA PRIVATE LIMITED +// Design Name: AXI4_STREAM_MASTER_INTERFACE +// Module Name: DOUT_M_AXIS +// Project Name: POLAR ENCODER-DECODER +// Target Devices: Zynq UltraScale+ ZCU111 Evaluation Platform (xczu28dr-ffvg1517-2-e) +// Tool Versions: VIVADO 2020.1 +// Description: AXI4 Stream Master Interface is used to stream out output data from +// the polar Encoder. +// +//////////////////////////////////////////////////////////////////////////////////// + + module DOUT_M_AXIS # + ( + // Width of S_AXIS address bus. The slave accepts the read and write addresses of width C_M_AXIS_TDATA_WIDTH. + parameter integer C_M_AXIS_TDATA_WIDTH = 32, + parameter integer C_S_AXIS_TDATA_WIDTH = 512, + parameter integer DEPTH = 16, + // Start count is the numeber of clock cycles the master will wait before initiating/issuing any transaction. + parameter integer C_M_START_COUNT = 2 + ) + ( + // Global ports + input logic M_AXIS_ACLK, + // + input logic M_AXIS_ARESETN, + // Master Stream Ports. TVALID indicates that the master is driving a valid transfer, A transfer takes place when both TVALID and TREADY are asserted. + output logic M_AXIS_TVALID, + // TDATA is the primary payload that is used to provide the data that is passing across the interface from the master. + output logic [C_M_AXIS_TDATA_WIDTH-1 : 0] M_AXIS_TDATA, + // TLAST indicates the boundary of a packet. + output logic M_AXIS_TLAST, + // TREADY indicates that the slave can accept a transfer in the current cycle. + input logic M_AXIS_TREADY, + // Input from PBCH Encoder Core of Width 864 bits + input logic [C_S_AXIS_TDATA_WIDTH-1:0]S_AXIS_TDATA, + // Input from PBCH Encoder Core + input logic DONE + ); + //Total number of output data. + // Total number of output data + localparam NUMBER_OF_OUTPUT_WORDS = 27; + + // function called clogb2 that returns an integer which has the + // value of the ceiling of the log base 2. + function integer clogb2 (input integer bit_depth); + begin + for(clogb2=0; bit_depth>0; clogb2=clogb2+1) + bit_depth = bit_depth >> 1; + end + endfunction + + // WAIT_COUNT_BITS is the width of the wait counter. + localparam integer WAIT_COUNT_BITS = clogb2(C_M_START_COUNT-1); + + // bit_num gives the minimum number of bits needed to address 'depth' size of FIFO. + localparam bit_num = clogb2(NUMBER_OF_OUTPUT_WORDS); + + // Define the states of state machine + // The control state machine oversees the writing of input streaming data to the FIFO, + // and outputs the streaming data from the FIFO + parameter [1:0] IDLE = 2'b00, // This is the initial/idle state + + INIT_COUNTER = 2'b01, // This state initializes the counter, ones + // the counter reaches C_M_START_COUNT count, + // the state machine changes state to INIT_WRITE + SEND_STREAM = 2'b10; // In this state the + // stream data is output through M_AXIS_TDATA + // State variable + logic [1:0] mst_exec_state; + // FIFO read pointer + logic [bit_num-1:0] read_pointer; + + // AXI Stream internal signals + //wait counter. The master waits for the user defined number of clock cycles before initiating a transfer. + logic [WAIT_COUNT_BITS-1 : 0] count; + //streaming data valid + logic axis_tvalid; + //streaming data valid delayed by one clock cycle + logic axis_tvalid_delay; + //Last of the streaming data + logic axis_tlast; + //Last of the streaming data delayed by one clock cycle + logic axis_tlast_delay; + //FIFO implementation signals + logic [C_M_AXIS_TDATA_WIDTH-1 : 0] stream_data_out; + logic tx_en; + //The master has issued all the streaming data stored in FIFO + logic tx_done; + + (* ram_style="register" *) + logic [C_M_AXIS_TDATA_WIDTH-1:0] slv_reg0 [0:DEPTH-1]; + + + // I/O Connections assignments + assign M_AXIS_TVALID = axis_tvalid_delay; + assign M_AXIS_TDATA = stream_data_out; + assign M_AXIS_TLAST = axis_tlast_delay; + + integer i; + integer byte_index; + + always_ff @( posedge M_AXIS_ACLK ) + begin + if (!M_AXIS_ARESETN ) + begin + stream_data_out <= 0; + for(i = 0; i <= DEPTH - 1 ; i = i+1) + slv_reg0[i] <= 0; + end + else + begin + if (DONE) + for ( byte_index = 0; byte_index <= DEPTH - 1; byte_index = byte_index+1 ) + slv_reg0[byte_index] <= S_AXIS_TDATA[(byte_index*C_M_AXIS_TDATA_WIDTH) +: C_M_AXIS_TDATA_WIDTH]; + else if (tx_en) + begin + stream_data_out <= slv_reg0[read_pointer]; + end + end + end + + + // Control state machine implementation + always_ff @(posedge M_AXIS_ACLK) + begin + // Synchronous reset (active low) + if (!M_AXIS_ARESETN) + begin + mst_exec_state <= IDLE; + count <= 0; + end + else + case (mst_exec_state) + IDLE: + // The slave starts accepting tdata when + // there tvalid is asserted to mark the + // presence of valid streaming data + mst_exec_state <= INIT_COUNTER; + + INIT_COUNTER: + // The slave starts accepting tdata when + // there tvalid is asserted to mark the + // presence of valid streaming data + if ( count == C_M_START_COUNT - 1 ) + begin + mst_exec_state <= SEND_STREAM; + end + else + begin + count <= count + 1; + mst_exec_state <= INIT_COUNTER; + end + + SEND_STREAM: + // The example design streaming master functionality starts + // when the master drives output tdata from the FIFO and the slave + // has finished storing the S_AXIS_TDATA + if (tx_done) + begin + mst_exec_state <= IDLE; + end + else + begin + mst_exec_state <= SEND_STREAM; + end + endcase + end + + + //tvalid generation + //axis_tvalid is asserted when the control state machine's state is SEND_STREAM and + //number of output streaming data is less than the NUMBER_OF_OUTPUT_WORDS. + assign axis_tvalid = ((mst_exec_state == SEND_STREAM) && (read_pointer < NUMBER_OF_OUTPUT_WORDS)); + + // AXI tlast generation + // axis_tlast is asserted number of output streaming data is NUMBER_OF_OUTPUT_WORDS-1 + // (0 to NUMBER_OF_OUTPUT_WORDS-1) + assign axis_tlast = (read_pointer == NUMBER_OF_OUTPUT_WORDS-1); + + + // Delay the axis_tvalid and axis_tlast signal by one clock cycle + // to match the latency of M_AXIS_TDATA + always_ff @(posedge M_AXIS_ACLK) + begin + if (!M_AXIS_ARESETN) + begin + axis_tvalid_delay <= 1'b0; + axis_tlast_delay <= 1'b0; + end + else + begin + axis_tvalid_delay <= axis_tvalid; + axis_tlast_delay <= axis_tlast; + end + end + + + //read_pointer pointer + + always_ff@(posedge M_AXIS_ACLK) + begin + if(!M_AXIS_ARESETN) + begin + read_pointer <= 0; + tx_done <= 1'b0; + end + else + if (read_pointer <= NUMBER_OF_OUTPUT_WORDS-1) + begin + if (tx_en) + // read pointer is incremented after every read from the FIFO + // when FIFO read signal is enabled. + begin + read_pointer <= read_pointer + 1; + tx_done <= 1'b0; + end + end + else if (read_pointer == NUMBER_OF_OUTPUT_WORDS) + begin + // tx_done is asserted when NUMBER_OF_OUTPUT_WORDS numbers of streaming data + // has been out. + tx_done <= 1'b1; + if(DONE)read_pointer <= 0; + end + end + + + //FIFO read enable generation + assign tx_en = M_AXIS_TREADY && axis_tvalid; + + endmodule diff --git a/AXI4_Slave_Stream.sv b/AXI4_Slave_Stream.sv new file mode 100644 index 0000000..e65aa55 --- /dev/null +++ b/AXI4_Slave_Stream.sv @@ -0,0 +1,159 @@ + +`timescale 1 ns / 1 ps +////////////////////////////////////////////////////////////////////////////////// +// Company: BITSILICA PRIVATE LIMITED +// Design Name: AXI4_STREAM_SLAVE_INTERFACE +// Module Name: S_AXIS +// Project Name: POLAR ENCODER-DECODER +// Target Devices: Zynq UltraScale+ ZCU111 Evaluation Platform (xczu28dr-ffvg1517-2-e) +// Tool Versions: VIVADO 2020.1 +// Description: AXI4 Stream Slave Interface is used to stream input data to the +// polar Encoder. +// +//////////////////////////////////////////////////////////////////////////////////// + + +module S_AXIS # + ( // AXI4Stream sink: Data Width + parameter integer C_S_AXIS_TDATA_WIDTH = 32 + ) + ( // AXI4Stream sink: Clock + input wire S_AXIS_ACLK, + // AXI4Stream sink: Reset + input wire S_AXIS_ARESETN, + // Ready to accept data in + output wire S_AXIS_TREADY, + // Data out + output [C_S_AXIS_TDATA_WIDTH-1 : 0] M_AXIS_TDATA, + // Data in + input wire [C_S_AXIS_TDATA_WIDTH-1 : 0] S_AXIS_TDATA, + // Indicates boundary of last packet + input wire S_AXIS_TLAST, + // Data is in valid + input wire S_AXIS_TVALID, + + input wire tready_in, + output logic read_en + + ); + // function called clogb2 that returns an integer which has the + // value of the ceiling of the log base 2. + function integer clogb2 (input integer bit_depth); + begin + for(clogb2=0; bit_depth>0; clogb2=clogb2+1) + bit_depth = bit_depth >> 1; + end + endfunction + + // Total number of input data. + localparam NUMBER_OF_INPUT_WORDS = 8; + localparam NUMBER_OF_OUTPUT_WORDS = 8; + + // bit_num gives the minimum number of bits needed to address 'NUMBER_OF_INPUT_WORDS' size of FIFO. + localparam bit_num = clogb2(NUMBER_OF_INPUT_WORDS-1); + localparam aw = clogb2(C_S_AXIS_TDATA_WIDTH); + + // The control state machine oversees the writing of input streaming data to the FIFO, + // and outputs the streaming data from the FIFO + localparam [1:0] IDLE = 2'b00, // This is the initial/idle state + + WRITE_FIFO = 2'b01, // In this state FIFO is written with the + // input stream data S_AXIS_TDATA + FIRST_READ = 2'b10, // Read first from FIFO as soon as it writes + READ_FIFO = 2'b11; // Read State + + + logic axis_tready; + logic [1:0] mst_exec_state; // State variable + logic fifo_wren; // FIFO write enable + logic fifo_full_flag; // FIFO full flag + logic fifo_empty; // FIFO Empty + logic full_n; // FIFO is being written + logic first_read_en; // First Read Enable + logic [5:0] count; + logic tx_en; + + // I/O Connections assignments + + assign read_en = (tready_in || first_read_en); + assign S_AXIS_TREADY = axis_tready; + + // Control state machine implementation + always @(posedge S_AXIS_ACLK) + begin + if (!S_AXIS_ARESETN) + // Synchronous reset (active low) + begin + mst_exec_state <= IDLE; + first_read_en <= 0; + end + else + case (mst_exec_state) + IDLE: begin + // The sink starts accepting tdata when + // there tvalid is asserted to mark the + // presence of valid streaming data + first_read_en <= 0; + if (S_AXIS_TVALID) + begin + mst_exec_state <= WRITE_FIFO; + end + else + begin + mst_exec_state <= IDLE; + end + end + WRITE_FIFO: begin + // When the sink has accepted all the streaming input data, + // the interface swiches functionality to a streaming master +// if (writes_done) + first_read_en <= 0; + if(full_n && count == 1) + mst_exec_state <= FIRST_READ; + else if (fifo_full_flag) + begin + mst_exec_state <= READ_FIFO; + end + else + begin + // The sink accepts and stores tdata + // into FIFO + mst_exec_state <= WRITE_FIFO; + end + end + FIRST_READ: begin + first_read_en <= 1'b1; + if(!fifo_full_flag) + mst_exec_state <= WRITE_FIFO; + else + mst_exec_state <= READ_FIFO; + end + READ_FIFO : begin + first_read_en <= 0; + if(fifo_empty) + mst_exec_state <= IDLE; + else if(!fifo_full_flag) + mst_exec_state <= WRITE_FIFO; + else + mst_exec_state <= READ_FIFO; + end + endcase + end + // AXI Streaming Sink + // + // design sink is always ready to accept the S_AXIS_TDATA until + // the FIFO is not filled with NUMBER_OF_INPUT_WORDS number of input words. + assign axis_tready = ((mst_exec_state == WRITE_FIFO) || (mst_exec_state == READ_FIFO)) && !fifo_full_flag && !S_AXIS_TLAST; + + + // FIFO write enable generation + assign fifo_wren = S_AXIS_TVALID && axis_tready && !fifo_full_flag && !S_AXIS_TLAST; + + + fifo #(.dw(C_S_AXIS_TDATA_WIDTH),.aw(aw-1),.n(C_S_AXIS_TDATA_WIDTH))FIFO(.clk(S_AXIS_ACLK),.rst(S_AXIS_ARESETN),.din(S_AXIS_TDATA),.we(fifo_wren),.dout(M_AXIS_TDATA),.re(read_en), + .full(),.empty(),.full_r(fifo_full_flag),.empty_r(fifo_empty),.full_n(full_n), .empty_n(), .full_n_r(), .empty_n_r(),.level(),.count(count)); + + //FIFO read enable generation + assign tx_en = axis_tready && S_AXIS_TVALID && tready_in; + + endmodule diff --git a/PBCH_Defines.vh b/PBCH_Defines.vh new file mode 100644 index 0000000..c201f5c --- /dev/null +++ b/PBCH_Defines.vh @@ -0,0 +1,10 @@ + + +// For PBCH A = 32 +// For PBCH G = 864 + + + +`define A 32 +`define G 864 +`define PBCH 1 \ No newline at end of file diff --git a/PBCH_POLAR_ENCODER_IP.sv b/PBCH_POLAR_ENCODER_IP.sv new file mode 100644 index 0000000..2da7b90 --- /dev/null +++ b/PBCH_POLAR_ENCODER_IP.sv @@ -0,0 +1,105 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: BITSILICA PVT LTD +// Design Name:PBCH_POLAR_ENCODER_IP +// Module Name: PBCH_POLAR_ENCODER_IP +// Project Name: POLAR IP +// Description: The PBCH_POLAR_ENCODER IP is interfaced with AXI4 Stream DIN +// Slave and DOUT Master interfaces. +////////////////////////////////////////////////////////////////////////////////// +`include "PBCH_Defines.vh" + +`define Dx_WIDTH 32 // Dx_WIDTH => DIN_WIDTH / DOUT_WIDTH => AXI4-Stream Interface +`define PDCCH 0 + + +module PBCH_POLAR_ENCODER_IP( + +/**************************************************************/ +// Global Signals + input logic reset_n, // Active Low Reset + input logic core_clk, // Core Clock + +/**************************************************************/ +// AXI4 DIN Stream Interface + input logic [`Dx_WIDTH - 1 : 0] s_axis_din_tdata, + input logic s_axis_din_tvalid, + input logic s_axis_din_tlast, + output logic DIN_TREADY, + +/**************************************************************/ +// AXI4 DOUT Stream Interface + input logic s_axis_dout_tready, + output logic [`Dx_WIDTH - 1 : 0] DOUT_TDATA, + output logic DOUT_TVALID, + output logic DOUT_TLAST + + +); + + logic [`Dx_WIDTH - 1 : 0] m_axis_din_tdata; + logic [`G - 1 : 0] msg_o; + logic [9:0] global_count; + logic done; + +S_AXIS # + (.C_S_AXIS_TDATA_WIDTH(`Dx_WIDTH) + ) DIN_STREAM + (.S_AXIS_ACLK(core_clk), + .S_AXIS_ARESETN(reset_n), + .S_AXIS_TREADY(DIN_TREADY), + .M_AXIS_TDATA(m_axis_din_tdata), // Output from Stream + .S_AXIS_TDATA(s_axis_din_tdata), // Input from Stream + .S_AXIS_TLAST(s_axis_din_tlast), + .S_AXIS_TVALID(s_axis_din_tvalid), + .tready_in(done) + ); + + POLAR_ENCODER + #(.PBCH(`PBCH), // Broadcast Channel enable + .A(`A), // Message width A if no segmentation needed, A'=A/2 if segmentation is needed. + .G(`G) // Length of output + ) PBCH + (.clock_i(core_clk), // input clock signal + .reset_ni(reset_n), // input reset + .msg_i(m_axis_din_tdata), // input message bits + .msg_o(msg_o) // output bits + ); + + always_ff@(posedge core_clk) + if(!reset_n) + global_count <= 0; + else if(global_count <= 'd525) + global_count <= global_count + 1'b1; + else + global_count <= 0; + + + assign done = (reset_n == 0)||(global_count =='d524) ? 1'b1 : 1'b0; + +DOUT_M_AXIS # + ( + // Width of S_AXIS address bus. The slave accepts the read and write addresses of width C_M_AXIS_TDATA_WIDTH. + .C_M_AXIS_TDATA_WIDTH(`Dx_WIDTH), + .C_S_AXIS_TDATA_WIDTH(`G), + .DEPTH(27), + .C_M_START_COUNT(2)) DOUT_STREAM + ( + // Global ports + .M_AXIS_ACLK(core_clk), + .M_AXIS_ARESETN(reset_n), + // Master Stream Ports. TVALID indicates that the master is driving a valid transfer, A transfer takes place when both TVALID and TREADY are asserted. + .M_AXIS_TVALID(DOUT_TVALID), + // TDATA is the primary payload that is used to provide the data that is passing across the interface from the master. + .M_AXIS_TDATA(DOUT_TDATA), + // TLAST indicates the boundary of a packet. + .M_AXIS_TLAST(DOUT_TLAST), + // TREADY indicates that the slave can accept a transfer in the current cycle. + .M_AXIS_TREADY(s_axis_dout_tready), + // Input from PBCH Encoder Core of Width 864 bits + .S_AXIS_TDATA(msg_o), + // Input from PBCH Encoder Core + .DONE(done) + ); + +endmodule diff --git a/Register.sv b/Register.sv new file mode 100644 index 0000000..cd52c20 --- /dev/null +++ b/Register.sv @@ -0,0 +1,45 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: BITSILICA PRIVATE LIMITED +// +// Design Name: Register +// Module Name: register +// Project Name: POLAR ENCODER-DECODER +// Tool Versions: VIVADO 2020.1 +////////////////////////////////////////////////////////////////////////////////// + +// register is written to synchronize a combiational logic w.r.t clock and reset signals +module register #( + parameter int WIDTH = 1, // width of the input and output of the register + parameter logic [1:0] SR = 2'b00, // SET and RESET inputs of the register + parameter logic [WIDTH-1:0] RST_VAL = {WIDTH{1'b0}} // reset value to be provided at the output when reset signal is active +) ( + input logic clk, // clock signal for register + input logic rstb, // active low, synchronous reset + input logic [WIDTH-1:0] din, // input to be registered + output logic [WIDTH-1:0] dout // registered outputs +); + + generate + if(SR==2'b00) begin : NON_RESET_FLOP // if SR==00, irrespective of other signals the input needs to be registered + always_ff @ (posedge clk) begin + dout <= din; // registering input w.r.t posedge of clock signal + end + end : NON_RESET_FLOP + else begin: RESET_FLOP // if SR!==00, input needs to be registered according to other signals w.r.t posedge of clock signal + always_ff @ (posedge clk ) begin + if (~rstb) // if reset is active + if (SR == 2'b01) + dout <= {WIDTH{1'b0}}; // if SR==01, reset the output + else if (SR == 2'b10) + dout <= {WIDTH{1'b1}}; // if SR==10, set the output + else + dout <= RST_VAL; // if SR==11, reset the output according the reset value provided + else + dout <= din; // if reset is inactive, register the input + end + end: RESET_FLOP + endgenerate + +endmodule + diff --git a/encoder_bit_selection_rtl.sv b/encoder_bit_selection_rtl.sv new file mode 100644 index 0000000..891c734 --- /dev/null +++ b/encoder_bit_selection_rtl.sv @@ -0,0 +1,61 @@ +`timescale 1ns / 1ps + +////////////////////////////////////////////////////////////////////////////////// +// Company: BITSILICA PRIVATE LIMITED +// Design Name: ENCODER BIT SELECTION +// Module Name: encoder_bit_selection_rtl +// Project Name: POLAR ENCODER-DECODER +// Target Devices: Zynq UltraScale+ ZCU111 Evaluation Platform (xczu28dr-ffvg1517-2-e) +// Tool Versions: VIVADO 2020.1 +// Description: RTL code for bit selection, in order to change the length of a sequence from N to E, +// also known as rate matching. +// +// +////////////////////////////////////////////////////////////////////////////////// +module encoder_bit_selection_rtl +#( + parameter K = 164, + parameter G = 1728, + parameter C = 1, + parameter E = G/C, + parameter N=512 + ) + ( + input wire clock_i, // system clock + input wire reset_ni, // active low synchronous reset + input wire [N-1:0] msg_i, // input message for bit selection + output reg [E-1:0] msg_o // output message bit selection + ); + + localparam Y = E/N; + localparam Z = E%N; + + integer i; + + generate + always@(posedge clock_i) begin + if(!reset_ni )begin + msg_o <= 0; + end + else begin + if(E>=N) + begin + for(i = 1;i <= Y;i = i+1) // Repitition // + msg_o[((i*N)-1) -: N]<=msg_i[N-1:0]; // Assigning same N bits to output reg for E/N times + if(Z != 0)begin + msg_o[E-1:N*(Y)] <= msg_i[Z-1:0]; // Assingning remaining E%N bits + end + end + else + begin + if((10000*(K/E)) <= (70000/16)) // Puncturing // + msg_o[E-1:0] <= msg_i[N-1:N-E]; // Assigning last E bits to output register + else // Shortening // + msg_o[E-1:0] <= msg_i[E-1:0]; // Assigning first E bits to output register + end + end + end + endgenerate + +endmodule + diff --git a/encoder_core_rtl.sv b/encoder_core_rtl.sv new file mode 100644 index 0000000..ee3d713 --- /dev/null +++ b/encoder_core_rtl.sv @@ -0,0 +1,55 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: BITSILICA PRIVATE LIMITED +// Design Name: ENCODER CORE +// Module Name: encoder_core_rtl +// Project Name: POLAR ENCODER-DECODER +// Target Devices: Zynq UltraScale+ ZCU111 Evaluation Platform (xczu28dr-ffvg1517-2-e) +// Tool Versions: VIVADO 2020.1 +// Description: RTL code for polar encoder core operation. +// +// encoder_core_rtl is written to encode an N-bit input message and produce an N-bit +// encoded codeword as an output +// +////////////////////////////////////////////////////////////////////////////////// + +module encoder_core_rtl +#( + parameter N = 512, // length of input and output messages for encoder_core_rtl + localparam DEPTH = $clog2(N) // to derive depth of binary tree to carry out the operation of polar encoder core + ) + ( + input wire clock_i, // system clock + input wire reset_ni, // active low, synchronous reset + input wire [N-1:0] msg_i, // input message to be encoded + output reg [N-1:0] msg_o // output encoded codeword +); + + reg [N-1:0] msg_1; // internal register to hold the encoded codeword throughout the operation + integer i,j,k; // looping variables + + // instantiating a register(group of FF's) to hold the output and synchronize the module w.r.t clock and reset signals + register #( + .WIDTH(N), // overriding the width of register with the length of output to be registered + .SR(2'b00), // overriding SR inputs of the register + .RST_VAL({N{1'b0}}) // overriding the reset value with expected value in the output when reset is applied + ) REG ( + .clk(clock_i), // connecting clock ports + .rstb(reset_ni), // connecting reset ports + .din(msg_1), // connecting input of register with the value that needs to be registered + .dout(msg_o) // connecting the registered output with the output port of current module + ); + + // combinational always block for performing encoder operation + always_comb begin + msg_1 = msg_i; // temporary register is fed with input message + for (i = 0; i <= DEPTH; i = i+1) begin : depth // to loop through the depth of binary tree + for (j = 0; j <= (N-(2 ** i)); j = j+(2 ** i)) begin : limit // to find the boundaries of bits in different depths + for (k = j; k < (j+(2 ** (i-1))); k = k+1) begin : count // to find the number of xor operations required to encode the message + msg_1[k] = msg_1[k] ^ msg_1[k + (2 ** (i-1))]; // xor between two particular bits to be stored in another bit, based on the index calculated + end : count + end : limit + end : depth + end + +endmodule diff --git a/encoder_crc_attachment_rtl.sv b/encoder_crc_attachment_rtl.sv new file mode 100644 index 0000000..bb7e06b --- /dev/null +++ b/encoder_crc_attachment_rtl.sv @@ -0,0 +1,86 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: BITSILICA PRIVATE LIMITED +// Design Name: ENCODER CRC ATTACHMENT +// Module Name: encoder_crc_attachment_rtl +// Project Name: POLAR ENCODER-DECODER +// Target Devices: Zynq UltraScale+ ZCU111 Evaluation Platform (xczu28dr-ffvg1517-2-e) +// Tool Versions: VIVADO 2020.1 +// Description: RTL code for calculation and attachment of CRC to a given message, according to selected polynomial. +// +//~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~// +// If the CRC width i.e., P = X, // +// it means that we are going to use a X degree polynomial of length X+1 bits, // +// the crc_out is of X bits. // +// CRC POLYNOMIALS used in Polar IP // +// CRC6 =0x21 == 010_0001 // +// CRC11 =0x621 == 0110_0010_0001 // +// CRC16 =0x1021 == 0_0001_0000_0010_0001 // +// CRC24C =0xB2B117 == 0_1011_0010_1011_0001_0001_0111 // +//~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~// +// +// encoder_crc_attachment_rtl is written to calculate and attach CRC for a given message input. +// +////////////////////////////////////////////////////////////////////////////////// + +module encoder_crc_attachment_rtl + #( + parameter PUCCH = 0, // Uplink Channel enable + parameter PBCH = 0, // Broadcast Channel enable + parameter N = 512, + parameter A = 140, // Message width A if no segmentation needed, A'=A/2 if segmentation is needed. + parameter P=24, + parameter K = A+P // Message width after CRC is appended + ) + ( + input wire clock_i, // System clock + input wire reset_ni, // System reset,active low synchronous + input wire [A-1:0] msg_i, // Input message bits + output reg [K-1:0] msg_o // total message = message input + CRC bits +); + + integer i; // looping variable + wire [P:0] polynomial; // polynomial using which CRC needs to be calculated + reg [K-1:0] polynomial_1='d0; // polynomial_1 is to store the right shifted polynomial in each step + reg [K-1:0] msg_1='d0; // msg_1 is to hold the modified message in between the XOR operations + reg [P-1:0] crc_out='d0; // Calculated CRC output for given msg_i + reg [K-1:0] msg_2; // msg_2 is to hold the output msg after msg_i is appended with crc_out + + + generate + if (P == 'd6) //CRC-6 + assign polynomial = 'h21; + else if (P == 'd11) //CRC-11 + assign polynomial = 'h621; + else if (P == 'd24) //CRC-24C + assign polynomial = 'h1d11a9b; + else //CRC-16 + assign polynomial = 'h1021; + endgenerate + + // Procedural block to calculate CRC for input message bits. + always@(*) begin + polynomial_1 = { {(A-1){1'b0}}, polynomial[P:0] }; // initialization of polynomial_1 + msg_1 = { {P{1'b0}}, msg_i[A-1:0] }; // initialization of msg_1 + for (i = 0; i < A; i = i+1) begin // calculating CRC and storing in temporary internal register(A number of times) + msg_1 = ( msg_1[i] )? ( msg_1 ^ polynomial_1 ) : ( msg_1 ^ {K{1'b0}} ); // exor with polynomial if message bit is 1, else exor with 0's. + polynomial_1 = polynomial_1 << 1'b1; // left shifting the polynomial for each message bit + end + crc_out = msg_1[K-1 : A]; // assigning the internal register to CRC output + msg_2 = { crc_out[P-1 : 0], msg_i[A-1 : 0] }; // the final message output + end + + // instantiating a register(group of FF's) to hold the output and synchronize the module w.r.t clock and reset signals + register #( + .WIDTH(K), // overriding the width of register with the length of output to be registered + .SR(2'b01), // overriding SR inputs of the register + .RST_VAL({N{1'b0}}) // overriding the reset value with expected value in the output when reset is applied + ) REG ( + .clk(clock_i), // connecting clock ports + .rstb(reset_ni), // connecting reset ports + .din(msg_2), // connecting input of register with the value that needs to be registered + .dout(msg_o) // connecting the registered output with the output port of current module + ); + +endmodule + diff --git a/encoder_crc_interleaving_rtl.sv b/encoder_crc_interleaving_rtl.sv new file mode 100644 index 0000000..8360e5b --- /dev/null +++ b/encoder_crc_interleaving_rtl.sv @@ -0,0 +1,77 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: BITSILICA PRIVATE LIMITED +// Design Name: ENCODER CRC INTERLEAVING +// Module Name: encoder_crc_interleaving_rtl +// Project Name: POLAR ENCODER-DECODER +// Target Devices: Zynq UltraScale+ ZCU111 Evaluation Platform (xczu28dr-ffvg1517-2-e) +// Tool Versions: VIVADO 2020.1 +// Description: RTL code for interleaving the message attached with CRC, according to a CRC interleaver pattern. +// +// +////////////////////////////////////////////////////////////////////////////////// + +module encoder_crc_interleaving_rtl +#( + parameter K = 164, + parameter ITLV = 0, + parameter KMAX = 164 + ) + ( + input wire clock_i, // system clock + input wire reset_ni, // active low, synchronous reset + input wire [K-1:0] msg_i, // input message to be interleaved + output reg [K-1:0] msg_o // output crc interleaved message +); + + integer k = 1'd0; + integer j = 1'd0; + integer i = 1'd0; + integer m = 1'd0; + reg [K-1:0] msg_1; // internal register to hold the interleaved message throughout the operation + reg [7:0] pi [K-1:0]; //internal register for interleaving logic + + //interleaving pattern for interleaving the given message + reg [7:0] pimax [163:0] = '{8'd163,8'd162,8'd161,8'd160,8'd159,8'd158,8'd157,8'd156,8'd155,8'd154,8'd153,8'd152,8'd151,8'd150,8'd149,8'd148,8'd147,8'd41,8'd146, + 8'd40,8'd145,8'd39,8'd144,8'd38,8'd18,8'd13,8'd143,8'd137,8'd86,8'd80,8'd75,8'd48,8'd37,8'd23,8'd17,8'd12,8'd142,8'd136,8'd131,8'd125, + 8'd117,8'd103,8'd100,8'd97,8'd85,8'd79,8'd74,8'd64,8'd47,8'd44,8'd36,8'd33,8'd30,8'd22,8'd16,8'd11,8'd6,8'd141,8'd135,8'd133,8'd130, + 8'd128,8'd124,8'd121,8'd116,8'd114,8'd112,8'd109,8'd107,8'd105,8'd102,8'd99,8'd96,8'd94,8'd92,8'd90,8'd84,8'd78,8'd73,8'd68,8'd63,8'd60, + 8'd57,8'd55,8'd52,8'd46,8'd43,8'd35,8'd32,8'd29,8'd27,8'd21,8'd15,8'd10,8'd8,8'd5,8'd3,8'd1,8'd140,8'd139,8'd138,8'd134,8'd132,8'd129, + 8'd127,8'd126,8'd123,8'd122,8'd120,8'd119,8'd118,8'd115,8'd113,8'd111,8'd110,8'd108,8'd106,8'd104,8'd101,8'd98,8'd95,8'd93,8'd91,8'd89, + 8'd88,8'd87,8'd83,8'd82,8'd81,8'd77,8'd76,8'd72,8'd71,8'd70,8'd69,8'd67,8'd66,8'd65,8'd62,8'd61,8'd59,8'd58,8'd56,8'd54,8'd53,8'd51, + 8'd50,8'd49,8'd45,8'd42,8'd34,8'd31,8'd28,8'd26,8'd25,8'd24,8'd20,8'd19,8'd14,8'd9,8'd7,8'd4,8'd2,8'd0}; + + // instantiating a register(group of FF's) to hold the output and synchronize the module w.r.t clock and reset signals + register #( + .WIDTH(K), // overriding the width of register with the length of output to be registered + .SR(2'b00), // overriding SR inputs of the register + .RST_VAL({K{1'b0}}) // overriding the reset value with expected value in the output when reset is applied + ) REG ( + .clk(clock_i), // connecting clock ports + .rstb(reset_ni), // connecting reset ports + .din(msg_1), // connecting input of register with the value that needs to be registered + .dout(msg_o) // connecting the registered output with the output port of current module + ); + + // combinational always block for performing crc interleaving operation + always_comb begin + if(ITLV == 0) begin + for(i = 0 ; i < K ; i = i+1) + pi[i] = i; + end + else begin + k = 0; begin + for( m = 0 ; (m < KMAX) ; m = m+1) + if(pimax[m] >= (KMAX-K)) begin + pi[k] = (pimax[m]-(KMAX-K)); + k = k+1'b1; + end + end + begin + for( j = 'd0 ; j < K ; j = j+1) + msg_1[j] = msg_i[pi[j]]; + end + end + end + +endmodule diff --git a/encoder_frozen_bit_insertion_rtl1.sv b/encoder_frozen_bit_insertion_rtl1.sv new file mode 100644 index 0000000..0296795 --- /dev/null +++ b/encoder_frozen_bit_insertion_rtl1.sv @@ -0,0 +1,168 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: BITSILICA PRIVATE LIMITED +// Design Name: ENCODER FROZEN BIT INSERTION +// Module Name: encoder_frozen_bit_insertion_rtl +// Project Name: POLAR ENCODER-DECODER +// Target Devices: Zynq UltraScale+ ZCU111 Evaluation Platform (xczu28dr-ffvg1517-2-e) +// Tool Versions: VIVADO 2020.1 +// Description: RTL code for inserting frozen bits into information, according to given reliability sequence. +// +// encoder_frozen_bit_insertion_rtl is written to insert frozen bits in between information bits, according to reliability sequence +// +////////////////////////////////////////////////////////////////////////////////// + + +module encoder_frozen_bit_insertion_rtl1 +#( + parameter N = 512, // length of information+CRC+Frozen bits + parameter K = 164 // length of information+CRC bits + ) + ( + input wire clock_i, // system clock + input wire reset_ni, // active low synchronous reset + input wire [K-1:0] msg_i, // input information+CRC bits + output reg [N-1:0] msg_o // information+CRC+frozen bits +); + + reg [N-1:0] msg_1; // internal register to hold the output of frozen bit insertion + + reg [K-1:0] msg_2; + + int i,j,k='d0,p='d0,x='d0; // looping variables + int q='d0; + + + // storing the frozen locations in rel_seq array (reliability in ascending order) + + reg [9:0]rel_seq_512[511:0] = + '{10'd511, 10'd510, 10'd509, 10'd507, 10'd503, 10'd495, 10'd508, 10'd479, 10'd506, 10'd505, 10'd447, 10'd501, 10'd494, + 10'd502, 10'd499, 10'd493, 10'd383, 10'd478, 10'd491, 10'd477, 10'd255, 10'd504, 10'd487, 10'd475, 10'd446, 10'd500, + 10'd471, 10'd445, 10'd498, 10'd382, 10'd443, 10'd492, 10'd497, 10'd381, 10'd463, 10'd490, 10'd439, 10'd476, 10'd486, + 10'd489, 10'd431, 10'd379, 10'd254, 10'd474, 10'd473, 10'd485, 10'd415, 10'd483, 10'd470, 10'd444, 10'd375, 10'd253, + 10'd367, 10'd247, 10'd469, 10'd441, 10'd442, 10'd462, 10'd251, 10'd438, 10'd467, 10'd351, 10'd496, 10'd461, 10'd380, + 10'd437, 10'd459, 10'd378, 10'd239, 10'd488, 10'd430, 10'd484, 10'd319, 10'd435, 10'd377, 10'd455, 10'd472, 10'd223, + 10'd414, 10'd427, 10'd482, 10'd373, 10'd252, 10'd429, 10'd468, 10'd366, 10'd413, 10'd481, 10'd371, 10'd250, 10'd466, + 10'd423, 10'd374, 10'd440, 10'd365, 10'd411, 10'd249, 10'd460, 10'd350, 10'd246, 10'd465, 10'd436, 10'd407, 10'd191, + 10'd127, 10'd363, 10'd458, 10'd245, 10'd349, 10'd434, 10'd399, 10'd457, 10'd359, 10'd238, 10'd428, 10'd376, 10'd318, + 10'd454, 10'd243, 10'd347, 10'd433, 10'd237, 10'd453, 10'd426, 10'd222, 10'd317, 10'd372, 10'd343, 10'd412, 10'd235, + 10'd451, 10'd425, 10'd422, 10'd370, 10'd221, 10'd315, 10'd480, 10'd335, 10'd364, 10'd190, 10'd369, 10'd248, 10'd231, + 10'd410, 10'd421, 10'd311, 10'd219, 10'd409, 10'd362, 10'd464, 10'd406, 10'd419, 10'd348, 10'd215, 10'd361, 10'd189, + 10'd244, 10'd303, 10'd405, 10'd358, 10'd456, 10'd346, 10'd398, 10'd242, 10'd126, 10'd236, 10'd187, 10'd357, 10'd432, + 10'd207, 10'd403, 10'd397, 10'd452, 10'd345, 10'd241, 10'd316, 10'd342, 10'd125, 10'd234, 10'd183, 10'd287, 10'd355, + 10'd395, 10'd424, 10'd314, 10'd220, 10'd341, 10'd123, 10'd175, 10'd233, 10'd334, 10'd450, 10'd313, 10'd391, 10'd230, + 10'd368, 10'd218, 10'd339, 10'd119, 10'd333, 10'd310, 10'd420, 10'd159, 10'd229, 10'd408, 10'd217, 10'd449, 10'd188, + 10'd309, 10'd214, 10'd331, 10'd111, 10'd360, 10'd302, 10'd418, 10'd227, 10'd404, 10'd186, 10'd213, 10'd417, 10'd301, + 10'd307, 10'd356, 10'd402, 10'd327, 10'd95, 10'd206, 10'd240, 10'd344, 10'd396, 10'd185, 10'd401, 10'd211, 10'd354, + 10'd299, 10'd286, 10'd182, 10'd205, 10'd124, 10'd232, 10'd285, 10'd295, 10'd181, 10'd394, 10'd340, 10'd63, 10'd203, + 10'd353, 10'd448, 10'd122, 10'd283, 10'd393, 10'd174, 10'd390, 10'd312, 10'd338, 10'd228, 10'd179, 10'd199, 10'd121, + 10'd173, 10'd389, 10'd332, 10'd118, 10'd337, 10'd158, 10'd279, 10'd271, 10'd416, 10'd216, 10'd308, 10'd387, 10'd226, + 10'd330, 10'd171, 10'd212, 10'd117, 10'd110, 10'd329, 10'd157, 10'd306, 10'd326, 10'd225, 10'd167, 10'd115, 10'd184, + 10'd109, 10'd300, 10'd305, 10'd210, 10'd155, 10'd325, 10'd352, 10'd400, 10'd298, 10'd204, 10'd94, 10'd284, 10'd209, + 10'd151, 10'd180, 10'd107, 10'd297, 10'd392, 10'd323, 10'd202, 10'd93, 10'd294, 10'd178, 10'd103, 10'd143, 10'd282, + 10'd62, 10'd336, 10'd201, 10'd120, 10'd172, 10'd198, 10'd91, 10'd388, 10'd293, 10'd177, 10'd278, 10'd281, 10'd61, + 10'd170, 10'd116, 10'd197, 10'd87, 10'd156, 10'd277, 10'd114, 10'd169, 10'd59, 10'd291, 10'd275, 10'd270, 10'd195, + 10'd166, 10'd224, 10'd108, 10'd269, 10'd79, 10'd154, 10'd113, 10'd328, 10'd55, 10'd106, 10'd165, 10'd153, 10'd150, + 10'd386, 10'd208, 10'd324, 10'd385, 10'd267, 10'd47, 10'd92, 10'd163, 10'd296, 10'd304, 10'd105, 10'd102, 10'd149, + 10'd263, 10'd322, 10'd292, 10'd90, 10'd200, 10'd31, 10'd321, 10'd142, 10'd176, 10'd147, 10'd101, 10'd141, 10'd196, + 10'd290, 10'd89, 10'd280, 10'd60, 10'd86, 10'd99, 10'd139, 10'd168, 10'd58, 10'd276, 10'd85, 10'd194, 10'd289, + 10'd78, 10'd135, 10'd112, 10'd57, 10'd83, 10'd54, 10'd274, 10'd268, 10'd164, 10'd77, 10'd152, 10'd193, 10'd53, + 10'd162, 10'd104, 10'd273, 10'd266, 10'd75, 10'd46, 10'd148, 10'd51, 10'd100, 10'd45, 10'd161, 10'd265, 10'd262, + 10'd71, 10'd146, 10'd30, 10'd140, 10'd88, 10'd98, 10'd43, 10'd29, 10'd261, 10'd145, 10'd138, 10'd84, 10'd259, 10'd39, + 10'd97, 10'd27, 10'd56, 10'd82, 10'd137, 10'd76, 10'd384, 10'd134, 10'd23, 10'd52, 10'd133, 10'd320, 10'd15, 10'd73, + 10'd50, 10'd81, 10'd131, 10'd44, 10'd70, 10'd192, 10'd288, 10'd160, 10'd272, 10'd74, 10'd49, 10'd42, 10'd69, 10'd28, + 10'd144, 10'd41, 10'd67, 10'd96, 10'd38, 10'd264, 10'd260, 10'd136, 10'd22, 10'd25, 10'd37, 10'd80, 10'd26, 10'd258, + 10'd35, 10'd132, 10'd21, 10'd257, 10'd72, 10'd14, 10'd48, 10'd13, 10'd19, 10'd130, 10'd68, 10'd40, 10'd11, 10'd66, + 10'd129, 10'd7, 10'd36, 10'd24, 10'd34, 10'd256, 10'd20, 10'd65, 10'd33, 10'd12, 10'd128, 10'd18, 10'd10, 10'd17, + 10'd6, 10'd9, 10'd64, 10'd5, 10'd3, 10'd32, 10'd16, 10'd8, 10'd4, 10'd2, 10'd1, 10'd0} ; + + reg [9:0]rel_seq_256[255:0] = + '{10'd255, 10'd254, 10'd253, 10'd247, 10'd251, 10'd239, 10'd223, 10'd252, 10'd250, 10'd249, 10'd246, 10'd191, 10'd127, + 10'd245, 10'd238, 10'd243, 10'd237, 10'd222, 10'd235, 10'd221, 10'd190, 10'd248, 10'd231, 10'd219, 10'd215, 10'd189, + 10'd244, 10'd242, 10'd126, 10'd236, 10'd187, 10'd207, 10'd241, 10'd125, 10'd234, 10'd183, 10'd220, 10'd123, 10'd175, + 10'd233, 10'd230, 10'd218, 10'd119, 10'd159, 10'd229, 10'd217, 10'd188, 10'd214, 10'd111, 10'd227, 10'd186, 10'd213, + 10'd95, 10'd206, 10'd240, 10'd185, 10'd211, 10'd182, 10'd205, 10'd124, 10'd232, 10'd181, 10'd63, 10'd203, 10'd122, + 10'd174, 10'd228, 10'd179, 10'd199, 10'd121, 10'd173, 10'd118, 10'd158, 10'd216, 10'd226, 10'd171, 10'd212, 10'd117, + 10'd110, 10'd157, 10'd225, 10'd167, 10'd115, 10'd184, 10'd109, 10'd210, 10'd155, 10'd204, 10'd94, 10'd209, 10'd151, + 10'd180, 10'd107, 10'd202, 10'd93, 10'd178, 10'd103, 10'd143, 10'd62, 10'd201, 10'd120, 10'd172, 10'd198, 10'd91, + 10'd177, 10'd61, 10'd170, 10'd116, 10'd197, 10'd87, 10'd156, 10'd114, 10'd169, 10'd59, 10'd195, 10'd166, 10'd224, + 10'd108, 10'd79, 10'd154, 10'd113, 10'd55, 10'd106, 10'd165, 10'd153, 10'd150, 10'd208, 10'd47, 10'd92, 10'd163, + 10'd105, 10'd102, 10'd149, 10'd90, 10'd200, 10'd31, 10'd142, 10'd176, 10'd147, 10'd101, 10'd141, 10'd196, 10'd89, + 10'd60, 10'd86, 10'd99, 10'd139, 10'd168, 10'd58, 10'd85, 10'd194, 10'd78, 10'd135, 10'd112, 10'd57, 10'd83, 10'd54, + 10'd164, 10'd77, 10'd152, 10'd193, 10'd53, 10'd162, 10'd104, 10'd75, 10'd46, 10'd148, 10'd51, 10'd100, 10'd45, 10'd161, + 10'd71, 10'd146, 10'd30, 10'd140, 10'd88, 10'd98, 10'd43, 10'd29, 10'd145, 10'd138, 10'd84, 10'd39, 10'd97, 10'd27, + 10'd56, 10'd82, 10'd137, 10'd76, 10'd134, 10'd23, 10'd52, 10'd133, 10'd15, 10'd73, 10'd50, 10'd81, 10'd131, 10'd44, + 10'd70, 10'd192, 10'd160, 10'd74, 10'd49, 10'd42, 10'd69, 10'd28, 10'd144, 10'd41, 10'd67, 10'd96, 10'd38, 10'd136, + 10'd22, 10'd25, 10'd37, 10'd80, 10'd26, 10'd35, 10'd132, 10'd21, 10'd72, 10'd14, 10'd48, 10'd13, 10'd19, 10'd130, + 10'd68, 10'd40, 10'd11, 10'd66, 10'd129, 10'd7, 10'd36, 10'd24, 10'd34, 10'd20, 10'd65, 10'd33, 10'd12, 10'd128, + 10'd18, 10'd10, 10'd17, 10'd6, 10'd9, 10'd64, 10'd5, 10'd3, 10'd32, 10'd16, 10'd8, 10'd4, 10'd2, 10'd1, 10'd0}; + + reg [9:0]rel_seq_128[127:0] = + '{10'd127, 10'd126, 10'd125, 10'd123, 10'd119, 10'd111, 10'd95, 10'd124, 10'd63, 10'd122, 10'd121, 10'd118, 10'd117, 10'd110, + 10'd115, 10'd109, 10'd94, 10'd107, 10'd93, 10'd103, 10'd62, 10'd120, 10'd91, 10'd61, 10'd116, 10'd87, 10'd114, 10'd59, 10'd108, + 10'd79, 10'd113, 10'd55, 10'd106, 10'd47, 10'd92, 10'd105, 10'd102, 10'd90, 10'd31, 10'd101, 10'd89, 10'd60, 10'd86, 10'd99, + 10'd58, 10'd85, 10'd78, 10'd112, 10'd57, 10'd83, 10'd54, 10'd77, 10'd53, 10'd104, 10'd75, 10'd46, 10'd51, 10'd100, 10'd45, + 10'd71, 10'd30, 10'd88, 10'd98, 10'd43, 10'd29, 10'd84, 10'd39, 10'd97, 10'd27, 10'd56, 10'd82, 10'd76, 10'd23, 10'd52, 10'd15, + 10'd73, 10'd50, 10'd81, 10'd44, 10'd70, 10'd74, 10'd49, 10'd42, 10'd69, 10'd28, 10'd41, 10'd67, 10'd96, 10'd38, 10'd22, 10'd25, + 10'd37, 10'd80, 10'd26, 10'd35, 10'd21, 10'd72, 10'd14, 10'd48, 10'd13, 10'd19, 10'd68, 10'd40, 10'd11, 10'd66, 10'd7, 10'd36, + 10'd24, 10'd34, 10'd20, 10'd65, 10'd33, 10'd12, 10'd18, 10'd10, 10'd17, 10'd6, 10'd9, 10'd64, 10'd5, 10'd3, 10'd32, 10'd16, + 10'd8, 10'd4, 10'd2, 10'd1, 10'd0}; + + reg [9:0]rel_seq_64[63:0] = + '{10'd63, 10'd62, 10'd61, 10'd59, 10'd55, 10'd47, 10'd31, 10'd60, 10'd58, 10'd57, 10'd54, 10'd53, 10'd46, 10'd51, 10'd45, 10'd30, + 10'd43, 10'd29, 10'd39, 10'd27, 10'd56, 10'd23, 10'd52, 10'd15, 10'd50, 10'd44, 10'd49, 10'd42, 10'd28, 10'd41, 10'd38, 10'd22, + 10'd25, 10'd37, 10'd26, 10'd35, 10'd21, 10'd14, 10'd48, 10'd13, 10'd19, 10'd40, 10'd11, 10'd7, 10'd36, 10'd24, 10'd34, 10'd20, 10'd33, + 10'd12, 10'd18, 10'd10, 10'd17, 10'd6, 10'd9, 10'd5, 10'd3, 10'd32, 10'd16, 10'd8, 10'd4, 10'd2, 10'd1, 10'd0}; + + reg [9:0]rel_seq_32[31:0] = + '{10'd31, 10'd30, 10'd29, 10'd27, 10'd23, 10'd15, 10'd28, 10'd22, 10'd25, 10'd26, 10'd21, 10'd14, 10'd13, 10'd19, 10'd11, 10'd7, 10'd24, + 10'd20, 10'd12, 10'd18, 10'd10, 10'd17, 10'd6, 10'd9, 10'd5, 10'd3, 10'd16, 10'd8, 10'd4, 10'd2, 10'd1, 10'd0}; + + + always@(posedge clock_i) + begin : insert_frz_zeroes + if(q == 0) + msg_2 <= msg_i; + + if(q >= (N-K) ) begin : insert_msg_crc + case(N) + 32 : msg_1[rel_seq_32[q]] <= msg_2[x]; // filling remaining most reliable K positions with information+CRC bits + 64 : msg_1[rel_seq_64[q]] <= msg_2[x]; + 128 : msg_1[rel_seq_128[q]] <= msg_2[x]; + 256 : msg_1[rel_seq_256[q]] <= msg_2[x]; + 512 : msg_1[rel_seq_512[q]] <= msg_2[x]; + default:msg_1 <= 'b0; + endcase + if(x < K) + x ++; + else + x <= 0; + end : insert_msg_crc // N - K bits need to be frozen + else begin + case(N) + 32 : msg_1[rel_seq_32[q]] <= 1'b0; // filling the least reliable frozen positions with 0's + 64 : msg_1[rel_seq_64[q]] <= 1'b0; + 128 : msg_1[rel_seq_128[q]] <= 1'b0; + 256 : msg_1[rel_seq_256[q]] <= 1'b0; + 512 : msg_1[rel_seq_512[q]] <= 1'b0; + default:msg_1 <= 'b0; + endcase + end + if(msg_2 == msg_i && q> 3'd5); // parameter to break down the input message into 32- sub blocks of euqal length, S=N/32 + + reg [4:0] sbi_pat [31:0] = '{5'd31, 5'd30, 5'd29, 5'd27, + 5'd28, 5'd26,5'd25, 5'd24, + 5'd23,5'd15,5'd22, 5'd14, + 5'd21, 5'd13, 5'd20, 5'd12, + 5'd19, 5'd11, 5'd18, 5'd10, + 5'd17, 5'd9, 5'd16, 5'd8, + 5'd7, 5'd6, 5'd5, 5'd3, + 5'd4, 5'd2, 5'd1, 5'd0}; + logic [N-1:0] msg_1; + logic sub_blocks [31:0] [S-1:0]; //register to store the sub divided blocks + logic temp [31:0] [S-1:0]; //register to store the interleaved sub blocks + + integer i,j,k,p,q,r; //looping variables + + // instantiating a register(group of FF's) to hold the output and synchronize the module w.r.t clock and reset signals + register #( + .WIDTH(N), // overriding the width of register with the length of output to be registered + .SR(2'b00), // overriding SR inputs of the register + .RST_VAL({N{1'b0}}) // overriding the reset value with expected value in the output when reset is applied + ) REG ( + .clk(clock_i), // connecting clock ports + .rstb(reset_ni), // connecting reset ports + .din(msg_1), // connecting input of register with the value that needs to be registered + .dout(msg_o) // connecting the registered output with the output port of current module + ); + + always_comb begin + //breaking down the message into 32 bit sub blocks of width N/32 + begin + for(j = 0 ; j < 32 ; j=j+1) begin + for (i = 0 ; i < S ; i = i+1) begin + sub_blocks[j][i] = msg_i[(j*S)+i]; + end + end + end + + //interleaving the subblocks according to the interleaving pattern + begin + for(p = 0 ; p < 32 ; p = p+1) begin + temp[p] = sub_blocks[sbi_pat[p]]; + end + end + + //assigning interleaved bits to the output + begin + for(q = 0 ; q < 32 ; q = q+1) begin + for (r = 0 ; r < S ; r = r+1) begin + msg_1[(q*S)+r] = temp[q][r]; + end + end + end + end + +endmodule diff --git a/encoder_top_rtl.sv b/encoder_top_rtl.sv new file mode 100644 index 0000000..273620b --- /dev/null +++ b/encoder_top_rtl.sv @@ -0,0 +1,127 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: BITSILICA PRIVATE LIMITED +// +// Design Name: POLAE_ENCODER +// Module Name: POLAR_ENCODER +// Project Name: POLAR ENCODER-DECODER +// Target Devices: Zynq UltraScale+ ZCU111 Evaluation Platform (xczu28dr-ffvg1517-2-e) +// Tool Versions: VIVADO 2020.1 +// Description: RTL code for integration of all sub blocks of polar encoder +////////////////////////////////////////////////////////////////////////////////// + +module POLAR_ENCODER +#( + parameter PUCCH=0, // Uplink Channel enable + parameter PBCH=1, // Broadcast Channel enable + parameter A=32, // Message width A if no segmentation needed, A'=A/2 if segmentation is needed. + parameter P=24, + parameter G=864, // Length of output + parameter C=1, // Value of C=2 if segmentation need to be done otherwise C=1 + + parameter E=G/C, // Value of E based on G and C + parameter K=A+P, // Length of information+CRC width + parameter n_min=5, + parameter n_max=9, + parameter n_1= ((E<=((9/8)*(2**(($clog2(E))-1))))&&((K/E)<(9/16)))? ($clog2(E)-1) : $clog2(E), + parameter n_2= $clog2(8*K), + parameter min_n1_n2= (n_1 >= n_2)? n_2 : n_1, + parameter min_n1_n2_nmax = (min_n1_n2 >= n_max) ? n_max : min_n1_n2 , + parameter n=(min_n1_n2_nmax >= n_min)? min_n1_n2_nmax : n_min, + parameter N=2**n, + + parameter ITLV=1, // Interleave flag for CRC interleaving process + parameter KMAX=164 // Maximum value of K for CRC interleaving + ) + ( + input clock_i, // input clock signal + input reset_ni, // input reset + input wire [A-1:0] msg_i, // input message bits + output reg [G-1:0] msg_o // output bits + ); + + wire [K-1:0] msg_1; // output of CRC attachment + wire [K-1:0] msg_2; // output of CRC scrambling + wire [K-1:0] msg_x; // output of CRC interleaving + wire [N-1:0] msg_3; // output of frozen insertion + wire [N-1:0] msg_4; // output of encoder core + wire [N-1:0] msg_5; // output of sub block interleaving + wire [G-1:0] msg_6; // output of bit selection + + + if(PBCH) begin + encoder_crc_attachment_rtl #( + .PUCCH( PUCCH ), // Uplink Channel enable + .PBCH( PBCH ), // Broadcast Channel enable + .A(A), // Message width A if no segmentation needed, A'=A/2 if segmentation is needed. + .N(N) + ) ENCODER_PBCH_CRC_ATTACHMENT ( + .clock_i(clock_i), // System clock + .reset_ni(reset_ni), // System reset,active low synchronous + .msg_i( msg_i), // Input message bits + .msg_o( msg_1) // total message = message input + CRC bits + ); + + encoder_crc_interleaving_rtl#( + .K(K), + .ITLV(ITLV), + .KMAX(KMAX) + ) ENCODER_PBCH_CRC_INTERLEAVING ( + .clock_i(clock_i), // system clock + .reset_ni(reset_ni), // active low, synchronous reset + .msg_i( msg_1), // input message to be interleaved + .msg_o( msg_2) // output crc interleaved message + ); + + encoder_frozen_bit_insertion_rtl1 #( + .N(N), // length of information+CRC+Frozen bits + .K(K) // length of information+CRC bits + ) ENCODER_PBCH_FROZEN_INSERTION ( + .clock_i(clock_i), // system clock + .reset_ni(reset_ni), // active low synchronous reset + .msg_i( msg_2), // input information+CRC bits + .msg_o(msg_3) // information+CRC+frozen bits + ); + + encoder_core_rtl #( + .N(N) // length of input and output messages for encoder_core_rtl + ) ENCODER_PBCH_CORE ( + .clock_i(clock_i), // system clock + .reset_ni(reset_ni), // active low, synchronous reset + .msg_i( msg_3), // input message to be encoded + .msg_o(msg_4) // output encoded codeword + ); + + + encoder_sub_block_interleaving_rtl #( + .N( N) // input and output sequence length + ) ENCODER_PBCH_SUB_BLOCK_INTERLEAVING ( + .clock_i(clock_i), + .reset_ni(reset_ni), + .msg_i(msg_4), // input message for sub block interleaver + .msg_o(msg_5) // output message after sub block interleaving + ); + + encoder_bit_selection_rtl #( + .K(K), + .G(G), + .C(C), + .E(E), + .N(N) + ) ENCODER_PBCH_BIT_SELECTION ( + .clock_i(clock_i), // system clock + .reset_ni(reset_ni), // active low, synchronous reset + .msg_i(msg_5), // input message for bit selection + .msg_o(msg_6) // output message after bit selection + ); + end + +always@(posedge clock_i) // registering output with respect to clock + if(!reset_ni) + msg_o <=0; + else + begin + msg_o <=msg_6; + end +endmodule + diff --git a/generic_fifo.v b/generic_fifo.v new file mode 100644 index 0000000..e71f238 --- /dev/null +++ b/generic_fifo.v @@ -0,0 +1,226 @@ +`timescale 1ns / 1ps + + +////////////////////////////////////////////////////////////////////////////////// +// Company: BITSILICA PVT LTD +// Design Name: +// Module Name: FIFO +// Project Name: +////////////////////////////////////////////////////////////////////////////////// + +/* + +Description +=========== + +I/Os +---- +rst low active, either sync. or async. master reset (see below how to select) +clr synchronous clear (just like reset but always synchronous), high active +re read enable, synchronous, high active +we read enable, synchronous, high active +din Data Input +dout Data Output + +full Indicates the FIFO is full (combinatorial output) +full_r same as above, but registered output (see note below) +empty Indicates the FIFO is empty +empty_r same as above, but registered output (see note below) + +full_n Indicates if the FIFO has space for N entries (combinatorial output) +full_n_r same as above, but registered output (see note below) +empty_n Indicates the FIFO has at least N entries (combinatorial output) +empty_n_r same as above, but registered output (see note below) + +level indicates the FIFO level: +2'b00 0-25% full +2'b01 25-50% full +2'b10 50-75% full +2'b11 %75-100% full + +combinatorial vs. registered status outputs +------------------------------------------- +Both the combinatorial and registered status outputs have exactly the same +synchronous timing. Meaning they are being asserted immediately at the clock +edge after the last read or write. The combinatorial outputs however, pass +through several levels of logic before they are output. The registered status +outputs are direct outputs of a flip-flop. The reason both are provided, is +that the registered outputs require quite a bit of additional logic inside +the FIFO. If you can meet timing of your device with the combinatorial +outputs, use them ! The FIFO will be smaller. If the status signals are +in the critical pass, use the registered outputs, they have a much smaller +output delay (actually only Tcq). + +Parameters +---------- +The FIFO takes 3 parameters: +dw Data bus width +aw Address bus width (Determines the FIFO size by evaluating 2^aw) +n N is a second status threshold constant for full_n and empty_n + +*/ + +// Selecting Sync. or Async Reset +// ------------------------------ +// Uncomment one of the two lines below. The first line for +// synchronous reset, the second for asynchronous reset + +`define SC_FIFO_ASYNC_RESET //Uncomment for Syncr. reset +//`define SC_FIFO_ASYNC_RESET or negedge rst // Uncomment for Async. reset + + +module fifo#(parameter dw=32,aw=5,n=32)(clk, rst, din, we, dout, re, + full, empty, full_r, empty_r, + full_n, empty_n, full_n_r, empty_n_r, + level,count); + + +parameter max_size = 1<= (n-1) ) & !re) empty_n_r <= #1 1'b0; + else + if(re & (cnt <= n ) & !we) empty_n_r <= #1 1'b1; + +always @(posedge clk `SC_FIFO_ASYNC_RESET) + if(!rst) full_n_r <= #1 1'b0; + else + if(we & (cnt >= (max_size-n) ) & !re) full_n_r <= #1 1'b1; + else + if(re & (cnt <= (max_size-n+1)) & !we) full_n_r <= #1 1'b0; + +//////////////////////////////////////////////////////////////////// +// Sanity Check +always @(posedge clk) + if(we & full) + $display("%m WARNING: Writing while fifo is FULL (%t)",$time); + +always @(posedge clk) + if(re & empty) + $display("%m WARNING: Reading while fifo is EMPTY (%t)",$time); + +endmodule + diff --git a/simple_dual_port_ram.v b/simple_dual_port_ram.v new file mode 100644 index 0000000..11f76e2 --- /dev/null +++ b/simple_dual_port_ram.v @@ -0,0 +1,28 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: BITSILICA PVT LTD +// Design Name: +// Module Name: simple_dual_port_ram +// Project Name: +////////////////////////////////////////////////////////////////////////////////// + + +module simple_dual_port_ram#(parameter WIDTH = 32, DEPTH = 16,AW = 4)(clk,enb,wea,addra,addrb,dia,dob); + + input clk,wea,enb; + input [AW -1:0] addra,addrb; + input [WIDTH -1:0] dia; + output [WIDTH -1:0] dob; + reg [WIDTH -1:0] dob; + + reg [WIDTH -1:0] ram [DEPTH -1:0]; + + always @(posedge clk) begin + if (wea) + ram[addra] <= dia; + end + always @(posedge clk) begin + if (enb) + dob <= ram[addrb]; + end + endmodule