Ver a proveniência

PBCH_ENCODER

master
amit.b há 3 anos
cometimento
4487a342c4
14 ficheiros alterados com 1459 adições e 0 eliminações
  1. +234
    -0
      AXI4_Master_Stream.sv
  2. +159
    -0
      AXI4_Slave_Stream.sv
  3. +10
    -0
      PBCH_Defines.vh
  4. +105
    -0
      PBCH_POLAR_ENCODER_IP.sv
  5. +45
    -0
      Register.sv
  6. +61
    -0
      encoder_bit_selection_rtl.sv
  7. +55
    -0
      encoder_core_rtl.sv
  8. +86
    -0
      encoder_crc_attachment_rtl.sv
  9. +77
    -0
      encoder_crc_interleaving_rtl.sv
  10. +168
    -0
      encoder_frozen_bit_insertion_rtl1.sv
  11. +78
    -0
      encoder_sub_block_interleaving_rtl.sv
  12. +127
    -0
      encoder_top_rtl.sv
  13. +226
    -0
      generic_fifo.v
  14. +28
    -0
      simple_dual_port_ram.v

+ 234
- 0
AXI4_Master_Stream.sv Ver ficheiro

@@ -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

+ 159
- 0
AXI4_Slave_Stream.sv Ver ficheiro

@@ -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

+ 10
- 0
PBCH_Defines.vh Ver ficheiro

@@ -0,0 +1,10 @@


// For PBCH A = 32
// For PBCH G = 864



`define A 32
`define G 864
`define PBCH 1

+ 105
- 0
PBCH_POLAR_ENCODER_IP.sv Ver ficheiro

@@ -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

+ 45
- 0
Register.sv Ver ficheiro

@@ -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


+ 61
- 0
encoder_bit_selection_rtl.sv Ver ficheiro

@@ -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


+ 55
- 0
encoder_core_rtl.sv Ver ficheiro

@@ -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

+ 86
- 0
encoder_crc_attachment_rtl.sv Ver ficheiro

@@ -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


+ 77
- 0
encoder_crc_interleaving_rtl.sv Ver ficheiro

@@ -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

+ 168
- 0
encoder_frozen_bit_insertion_rtl1.sv Ver ficheiro

@@ -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<N )
q <= q+1;
else
q <= 0;
end : insert_frz_zeroes



always@(posedge clock_i)
if(!reset_ni)
msg_o <= 0;
else if(q==N)
msg_o <= msg_1;
else
msg_o <= msg_o;

endmodule

+ 78
- 0
encoder_sub_block_interleaving_rtl.sv Ver ficheiro

@@ -0,0 +1,78 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: BITSILICA PRIVATE LIMITED
// Design Name: ENCODER SUB-BLOCK INTERLEAVING
// Module Name: encoder_sub_block_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 sub block interleaving, in order to interleave the sub blocks of encoded codeword.
//
//////////////////////////////////////////////////////////////////////////////////

module encoder_sub_block_interleaving_rtl#(
parameter N=512 // input and output sequence length
// parameter to break down the input message into 32- sub blocks of euqal length, S=N/32
) (
input wire clock_i,
input wire reset_ni,
input wire [N-1:0] msg_i, // input message for sub block interleaver
output reg [N-1:0] msg_o // output message after sub block interleaving
);
localparam S=(N >> 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

+ 127
- 0
encoder_top_rtl.sv Ver ficheiro

@@ -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


+ 226
- 0
generic_fifo.v Ver ficheiro

@@ -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<<aw;

input clk, rst;
input [dw-1:0] din;
input we;
output [dw-1:0] dout;
input re;
output full, full_r;
output empty, empty_r;
output full_n, full_n_r;
output empty_n, empty_n_r;
output [1:0] level;
output [aw:0] count;


////////////////////////////////////////////////////////////////////
//
// Local Wires
//
wire wen; // Write Enable
wire ren; // Read Enable
reg [aw-1:0] wp;
wire [aw-1:0] wp_pl1;
wire [aw-1:0] wp_pl2;
reg [aw-1:0] rp;
wire [aw-1:0] rp_pl1;
reg full_r;
reg empty_r;
reg gb;
reg gb2;
reg [aw:0] cnt;
wire full_n, empty_n;
reg full_n_r, empty_n_r;



// Write Only when FIFO isn't full & write enable is there
assign wen = (!full && we) ? 1'b1 : 1'b0;
assign ren = (!empty && re) ? 1'b1 : 1'b0;
assign count = cnt;

////////////////////////////////////////////////////////////////////
// Memory Block
////////////////////////////////////////////////////////////////////
simple_dual_port_ram #(.WIDTH(dw),.DEPTH(n),.AW(aw))u0(.clk(clk),.wea(wen),.enb(ren),.addra(wp),.addrb(rp),.dia(din),.dob(dout));

////////////////////////////////////////////////////////////////////
// Misc Logic

always @(posedge clk `SC_FIFO_ASYNC_RESET)
if(!rst) wp <= #1 {aw{1'b0}};
else
if(we) wp <= #1 wp_pl1;

assign wp_pl1 = wp + { {aw-1{1'b0}}, 1'b1};
assign wp_pl2 = wp + { {aw-2{1'b0}}, 2'b10};

always @(posedge clk `SC_FIFO_ASYNC_RESET)
if(!rst) rp <= #1 {aw{1'b0}};
else
if(re) rp <= #1 rp_pl1;

assign rp_pl1 = rp + { {aw-1{1'b0}}, 1'b1};

////////////////////////////////////////////////////////////////////
// Combinatorial Full & Empty Flags
//

assign empty = ((wp == rp) & !gb);
assign full = ((wp == rp) & gb);

// Guard Bit ...
always @(posedge clk `SC_FIFO_ASYNC_RESET)
if(!rst) gb <= #1 1'b0;
else
if((wp_pl1 == rp) & we) gb <= #1 1'b1;
else
if(re) gb <= #1 1'b0;

////////////////////////////////////////////////////////////////////
// Registered Full & Empty Flags
//

// Guard Bit ...
always @(posedge clk `SC_FIFO_ASYNC_RESET)
if(!rst) gb2 <= #1 1'b0;
else
if((wp_pl2 == rp) & we) gb2 <= #1 1'b1;
else
if((wp != rp) & re) gb2 <= #1 1'b0;

always @(posedge clk `SC_FIFO_ASYNC_RESET)
if(!rst) full_r <= #1 1'b0;
else
if(we & ((wp_pl1 == rp) & gb2) & !re) full_r <= #1 1'b1;
else
if(re & ((wp_pl1 != rp) | !gb2) & !we) full_r <= #1 1'b0;

always @(posedge clk `SC_FIFO_ASYNC_RESET)
if(!rst) empty_r <= #1 1'b1;
else
if(we & ((wp != rp_pl1) | gb2) & !re) empty_r <= #1 1'b0;
else
if(re & ((wp == rp_pl1) & !gb2) & !we) empty_r <= #1 1'b1;

////////////////////////////////////////////////////////////////////
// Combinatorial Full_n & Empty_n Flags

assign empty_n = cnt < n;
assign full_n = !(cnt < (max_size-n+1));
assign level = {2{cnt[aw]}} | cnt[aw-1:aw-2];

// N entries status
always @(posedge clk `SC_FIFO_ASYNC_RESET)
if(!rst) cnt <= #1 {aw+1{1'b0}};
else
if( re & !we) cnt <= #1 cnt + { {aw{1'b1}}, 1'b1};
else
if(!re & we) cnt <= #1 cnt + { {aw{1'b0}}, 1'b1};

////////////////////////////////////////////////////////////////////
// Registered Full_n & Empty_n Flags

always @(posedge clk `SC_FIFO_ASYNC_RESET)
if(!rst) empty_n_r <= #1 1'b1;
else
if(we & (cnt >= (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


+ 28
- 0
simple_dual_port_ram.v Ver ficheiro

@@ -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

Carregando…
Cancelar
Guardar