NVC code coverage report

File:  ../../Sources/Xilinx/openjls_axis_regs.vhd

     0:   ------------------------------------------------------------------------------------------------------------- 
     1:   -- Engineer:    Vitor Mendes Camilo 
     2:   -- 
     3:   -- Module Name: openjls_axis_regs - rtl 
     4:   -- Description: AXI4-Stream + AXI4-Lite wrapper around openjls_top (flavor B). 
     5:   -- 
     6:   --          Instantiates openjls_axis (flavor A) and adds an AXI4-Lite register 
     7:   --          bank plus a reset controller. The core samples iImageWidth/ 
     8:   --          iImageHeight only while its synchronous reset is high, so 
     9:   --          reconfiguration is expressed as: write WIDTH/HEIGHT, set CTRL.APPLY. 
    10:   --          APPLY pulses the core reset for one clock while the 
    11:   --          registers are held stable; the AXI-Lite endpoint itself stays on 
    12:   --          aresetn only, so the bus never disappears mid-reconfigure. 
    13:   --          Back-to-back images of unchanged dimensions need no APPLY. 
    14:   -- 
    15:   --          While the pulse is active STATUS.BUSY reads 1 and the core holds 
    16:   --          s_axis_pixel_tready low, so a stream started too early stalls 
    17:   --          instead of losing pixels. Writes to WIDTH/HEIGHT/CTRL while BUSY 
    18:   --          are dropped (responded OKAY, not applied). 
    19:   -- 
    20:   --          WIDTH/HEIGHT writes are clamped to the core's rule (out-of-range 
    21:   --          values become the MAX generic), so a readback always returns the 
    22:   --          value the core will actually use. 
    23:   -- 
    24:   -------------------------------------------------------------------------------------------- 
    25:   -- REGISTER MAP (word-aligned offsets, 32-bit) 
    26:   -------------------------------------------------------------------------------------------- 
    27:   -- 
    28:   --   0x00  ID       RO  ASCII "OJLS" (0x4F4A4C53) 
    29:   --   0x04  VERSION  RO  0x00MMmmpp (major/minor/patch) 
    30:   --   0x08  CAPS     RO  [7:0] BITNESS, [15:8] output bytes per beat (OUT_WIDTH/8) 
    31:   --   0x0C  MAXDIM   RO  [15:0] MAX_IMAGE_WIDTH, [31:16] MAX_IMAGE_HEIGHT 
    32:   --   0x10  WIDTH    RW  [15:0] image width  (clamped on write) 
    33:   --   0x14  HEIGHT   RW  [15:0] image height (clamped on write) 
    34:   --   0x18  CTRL     WO  [0] APPLY — self-clearing, pulses the core reset 
    35:   --   0x1C  STATUS   RO  [0] BUSY (reset pulse active), [1] s_axis_pixel TREADY mirror 
    36:   -- 
    37:   ------------------------------------------------------------------------------------------------------------- 
    38:    
    39:   library ieee; 
    40:     use ieee.std_logic_1164.all; 
    41:     use ieee.numeric_std.all; 
    42:     use work.openjls_pkg.all; 
    43:    
    44:   -- AXI port names must keep the <prefix>_* suffix convention (lowercase, 
    45:   -- underscores) for Vivado IP integrator interface inference; the prefix 
    46:   -- becomes the interface name in the block diagram. 
    47:   -- vsg_off port_010 port_map_002 
    48:    
    49:   entity openjls_axis_regs is 
    50:     generic ( 
    51:       BITNESS             : positive range 8 to 16    := 12; 
    52:       MAX_IMAGE_WIDTH     : positive range 4 to 65535 := 4096; 
    53:       MAX_IMAGE_HEIGHT    : positive range 1 to 65535 := 4096; 
    54:       OUT_WIDTH           : positive range 48 to 1024 := CO_OUT_WIDTH_STD 
    55:     ); 
    56:     port ( 
    57:       aclk                : in    std_logic; 
    58:       aresetn             : in    std_logic; 
    59:       -- AXI4-Lite slave — configuration and status 
    60:       s_axi_ctrl_awaddr   : in    std_logic_vector(7 downto 0); 
    61:       s_axi_ctrl_awprot   : in    std_logic_vector(2 downto 0); 
    62:       s_axi_ctrl_awvalid  : in    std_logic; 
    63:       s_axi_ctrl_awready  : out   std_logic; 
    64:       s_axi_ctrl_wdata    : in    std_logic_vector(31 downto 0); 
    65:       s_axi_ctrl_wstrb    : in    std_logic_vector(3 downto 0); 
    66:       s_axi_ctrl_wvalid   : in    std_logic; 
    67:       s_axi_ctrl_wready   : out   std_logic; 
    68:       s_axi_ctrl_bresp    : out   std_logic_vector(1 downto 0); 
    69:       s_axi_ctrl_bvalid   : out   std_logic; 
    70:       s_axi_ctrl_bready   : in    std_logic; 
    71:       s_axi_ctrl_araddr   : in    std_logic_vector(7 downto 0); 
    72:       s_axi_ctrl_arprot   : in    std_logic_vector(2 downto 0); 
    73:       s_axi_ctrl_arvalid  : in    std_logic; 
    74:       s_axi_ctrl_arready  : out   std_logic; 
    75:       s_axi_ctrl_rdata    : out   std_logic_vector(31 downto 0); 
    76:       s_axi_ctrl_rresp    : out   std_logic_vector(1 downto 0); 
    77:       s_axi_ctrl_rvalid   : out   std_logic; 
    78:       s_axi_ctrl_rready   : in    std_logic; 
    79:       -- AXI4-Stream slave — one pixel per beat, right-justified 
    80:       s_axis_pixel_tdata  : in    std_logic_vector(8 * ((BITNESS + 7) / 8) - 1 downto 0); 
    81:       s_axis_pixel_tvalid : in    std_logic; 
    82:       s_axis_pixel_tlast  : in    std_logic; 
    83:       s_axis_pixel_tready : out   std_logic; 
    84:       -- AXI4-Stream master — encoded .jls byte stream 
    85:       m_axis_jls_tdata    : out   std_logic_vector(OUT_WIDTH - 1 downto 0); 
    86:       m_axis_jls_tkeep    : out   std_logic_vector(OUT_WIDTH / 8 - 1 downto 0); 
    87:       m_axis_jls_tvalid   : out   std_logic; 
    88:       m_axis_jls_tlast    : out   std_logic; 
    89:       m_axis_jls_tready   : in    std_logic 
    90:     ); 
    91:    
    92:     -- Vivado IP integrator interface inference 
    93:     attribute x_interface_info                   : string; 
    94:     attribute x_interface_parameter              : string; 
    95:     attribute x_interface_info of aclk           : signal is "xilinx.com:signal:clock:1.0 aclk CLK"; 
    96:     -- aresetn is auto-associated with aclk by Vivado (standard name/polarity) 
    97:     attribute x_interface_parameter of aclk      : signal is "ASSOCIATED_BUSIF s_axi_ctrl:s_axis_pixel:m_axis_jls"; 
    98:     attribute x_interface_info of aresetn        : signal is "xilinx.com:signal:reset:1.0 aresetn RST"; 
    99:     attribute x_interface_parameter of aresetn   : signal is "POLARITY ACTIVE_LOW"; 
   100:   end entity openjls_axis_regs; 
   101:    
   102:   architecture rtl of openjls_axis_regs is 
   103:    
   104:     constant VERSION     : std_logic_vector(31 downto 0) := x"00010000"; -- 1.0.0 
   105:    
   106:     -- Word-address decode (byte offset / 4) 
   107:     constant REG_ID      : natural := 0; 
   108:     constant REG_VERSION : natural := 1; 
   109:     constant REG_CAPS    : natural := 2; 
   110:     constant REG_MAXDIM  : natural := 3; 
   111:     constant REG_WIDTH   : natural := 4; 
   112:     constant REG_HEIGHT  : natural := 5; 
   113:     constant REG_CTRL    : natural := 6; 
   114:     constant REG_STATUS  : natural := 7; 
   115:    
   116:     -- Configuration registers 
   117:     signal sWidth        : unsigned(15 downto 0); 
   118:     signal sHeight       : unsigned(15 downto 0); 
   119:    
   120:     -- Reset controller 
   121:     signal sSoftRst      : std_logic; 
   122:     signal sCoreRst      : std_logic; 
   123:    
   124:     -- AXI-Lite handshake state (single outstanding transaction per channel) 
   125:     signal sWrHandshake  : std_logic; 
   126:     signal sRdHandshake  : std_logic; 
   127:     signal sBValid       : std_logic; 
   128:     signal sRValid       : std_logic; 
   129:     signal sRData        : std_logic_vector(31 downto 0); 
   130:    
   131:     signal sReadyMirror  : std_logic; 
   132:    
   133:     -- Merge an AXI-Lite write into the low 16 bits of a register, honoring 
   134:     -- WSTRB, then clamp to the core's sample-time rule (out-of-range -> MAX) 
   135:     -- so readback always reports the value the core will actually use. 
   136:    
   137:     function merge_clamp_dim ( 
   138:       vcur   : unsigned(15 downto 0); 
   139:       vwdata : std_logic_vector(31 downto 0); 
   140:       vwstrb : std_logic_vector(3 downto 0); 
   141:       vmindim : natural; 
   142:       vmaxdim : natural 
   143:     ) return unsigned is 
   144:    
   145:       variable vNew : unsigned(15 downto 0); 
   146:    
   147:     begin 
   148:    
   149:       vNew := vcur; 
   150:    
   151:       if (vwstrb(0) = '1') then 
   152:         vNew(7 downto 0) := unsigned(vwdata(7 downto 0)); 
   153:       end if; 
   154:    
   155:       if (vwstrb(1) = '1') then 
   156:         vNew(15 downto 8) := unsigned(vwdata(15 downto 8)); 
   157:       end if; 
   158:    
   159:       if (vNew < vmindim or vNew > vmaxdim) then 
   160:         vNew := to_unsigned(vmaxdim, vNew'length); 
   161:       end if; 
   162:    
   163:       return vNew; 
   164:    
   165:     end function merge_clamp_dim; 
   166:    
   167:   begin 
   168:    
   169:     ------------------------------------------------------------------------------------------------------------- 
   170:     -- AXI4-Lite WRITE CHANNEL 
   171:     ------------------------------------------------------------------------------------------------------------- 
   172:     -- Address and data are accepted in the same cycle (ready waits for both 
   173:     -- valids — legal: ready may depend on valid, not vice versa). Single 
   174:     -- outstanding transaction; next one is accepted after BREADY. 
   175:    
   176:     sWrHandshake <= '1' when s_axi_ctrl_awvalid = '1' and s_axi_ctrl_wvalid = '1' and sBValid = '0' else 
   177:                     '0'; 
   178:    
   179:     s_axi_ctrl_awready <= sWrHandshake; 
   180:     s_axi_ctrl_wready  <= sWrHandshake; 
   181:     s_axi_ctrl_bresp   <= "00"; -- OKAY; RO/unmapped writes are silently dropped 
   182:     s_axi_ctrl_bvalid  <= sBValid; 
   183:    
   184:     p_axi_write : process (aclk) is 
   185:    
   186:       variable vAddrWord : natural; 
   187:    
   188:     begin 
   189:    
   190:       if rising_edge(aclk) then 
   191:         if (aresetn = '0') then 
   192:           sBValid  <= '0'; 
   193:           sWidth   <= to_unsigned(MAX_IMAGE_WIDTH, sWidth'length); 
   194:           sHeight  <= to_unsigned(MAX_IMAGE_HEIGHT, sHeight'length); 
   195:           sSoftRst <= '0'; 
   196:         else 
   197:           -- Soft-reset pulse is a single clock: every synchronous element in 
   198:           -- the core resets in one cycle (see openjls_top). Default-clear here, 
   199:           -- set on an APPLY write below (last assignment wins). 
   200:           sSoftRst <= '0'; 
   201:    
   202:           if (sBValid = '1' and s_axi_ctrl_bready = '1') then 
   203:             sBValid <= '0'; 
   204:           end if; 
   205:    
   206:           if (sWrHandshake = '1') then 
   207:             sBValid   <= '1'; 
   208:             vAddrWord := to_integer(unsigned(s_axi_ctrl_awaddr(7 downto 2))); 
   209:    
   210:             -- Configuration writes are dropped while the reset pulse is live: 
   211:             -- the core is sampling these registers right now. 
   212:             if (sSoftRst = '0') then 
   213:    
   214:               case vAddrWord is 
   215:    
   216:                 when REG_WIDTH => 
   217:    
   218:                   sWidth <= merge_clamp_dim(sWidth, s_axi_ctrl_wdata, s_axi_ctrl_wstrb, CO_MIN_IMAGE_WIDTH, MAX_IMAGE_WIDTH); 
   219:    
   220:                 when REG_HEIGHT => 
   221:    
   222:                   sHeight <= merge_clamp_dim(sHeight, s_axi_ctrl_wdata, s_axi_ctrl_wstrb, CO_MIN_IMAGE_HEIGHT, MAX_IMAGE_HEIGHT); 
   223:    
   224:                 when REG_CTRL => 
   225:    
   226:                   if (s_axi_ctrl_wstrb(0) = '1' and s_axi_ctrl_wdata(0) = '1') then 
   227:                     sSoftRst <= '1'; 
   228:                   end if; 
   229:    
   230:                 when others => 
   231:    
   232:                   null; -- RO / unmapped: dropped 
   233:    
   234:               end case; 
   235:    
   236:             end if; 
   237:           end if; 
   238:         end if; 
   239:       end if; 
   240:    
   241:     end process p_axi_write; 
   242:    
   243:     ------------------------------------------------------------------------------------------------------------- 
   244:     -- AXI4-Lite READ CHANNEL 
   245:     ------------------------------------------------------------------------------------------------------------- 
   246:    
   247:     sRdHandshake <= '1' when s_axi_ctrl_arvalid = '1' and sRValid = '0' else 
   248:                     '0'; 
   249:    
   250:     s_axi_ctrl_arready <= sRdHandshake; 
   251:     s_axi_ctrl_rresp   <= "00"; -- OKAY; unmapped reads return zero 
   252:     s_axi_ctrl_rvalid  <= sRValid; 
   253:     s_axi_ctrl_rdata   <= sRData; 
   254:    
   255:     p_axi_read : process (aclk) is 
   256:    
   257:       variable vAddrWord : natural; 
   258:    
   259:     begin 
   260:    
   261:       if rising_edge(aclk) then 
   262:         if (aresetn = '0') then 
   263:           sRValid <= '0'; 
   264:           sRData  <= (others => '0'); 
   265:         else 
   266:           if (sRValid = '1' and s_axi_ctrl_rready = '1') then 
   267:             sRValid <= '0'; 
   268:           elsif (sRdHandshake = '1') then 
   269:             sRValid   <= '1'; 
   270:             vAddrWord := to_integer(unsigned(s_axi_ctrl_araddr(7 downto 2))); 
   271:             sRData    <= (others => '0'); 
   272:    
   273:             case vAddrWord is 
   274:    
   275:               when REG_ID => 
   276:    
   277:                 sRData <= x"4F4A4C53";                                                       -- "OJLS" 
   278:    
   279:               when REG_VERSION => 
   280:    
   281:                 sRData <= VERSION; 
   282:    
   283:               when REG_CAPS => 
   284:    
   285:                 sRData(7 downto 0)  <= std_logic_vector(to_unsigned(BITNESS, 8)); 
   286:                 sRData(15 downto 8) <= std_logic_vector(to_unsigned(OUT_WIDTH / 8, 8)); 
   287:    
   288:               when REG_MAXDIM => 
   289:    
   290:                 sRData(15 downto 0)  <= std_logic_vector(to_unsigned(MAX_IMAGE_WIDTH, 16)); 
   291:                 sRData(31 downto 16) <= std_logic_vector(to_unsigned(MAX_IMAGE_HEIGHT, 16)); 
   292:    
   293:               when REG_WIDTH => 
   294:    
   295:                 sRData(15 downto 0) <= std_logic_vector(sWidth); 
   296:    
   297:               when REG_HEIGHT => 
   298:    
   299:                 sRData(15 downto 0) <= std_logic_vector(sHeight); 
   300:    
   301:               when REG_STATUS => 
   302:    
   303:                 sRData(0) <= sSoftRst; 
   304:                 sRData(1) <= sReadyMirror; 
   305:    
   306:               when others => 
   307:    
   308:                 -- REG_CTRL reads as zero (write-only), unmapped reads zero 
   309:                 null; 
   310:    
   311:             end case; 
   312:    
   313:           end if; 
   314:         end if; 
   315:       end if; 
   316:    
   317:     end process p_axi_read; 
   318:    
   319:     ------------------------------------------------------------------------------------------------------------- 
   320:     -- RESET CONTROLLER + CORE 
   321:     ------------------------------------------------------------------------------------------------------------- 
   322:    
   323:     sCoreRst <= (not aresetn) or sSoftRst; 
   324:    
   325:     s_axis_pixel_tready <= sReadyMirror; 
   326:    
   327:     u_openjls_axis : entity work.openjls_axis(rtl) 
   328:       generic map ( 
   329:         BITNESS             => BITNESS, 
   330:         MAX_IMAGE_WIDTH     => MAX_IMAGE_WIDTH, 
   331:         MAX_IMAGE_HEIGHT    => MAX_IMAGE_HEIGHT, 
   332:         OUT_WIDTH           => OUT_WIDTH 
   333:       ) 
   334:       port map ( 
   335:         iClk                => aclk, 
   336:         iRst                => sCoreRst, 
   337:         iImageWidth         => std_logic_vector(sWidth), 
   338:         iImageHeight        => std_logic_vector(sHeight), 
   339:         s_axis_pixel_tdata  => s_axis_pixel_tdata, 
   340:         s_axis_pixel_tvalid => s_axis_pixel_tvalid, 
   341:         s_axis_pixel_tlast  => s_axis_pixel_tlast, 
   342:         s_axis_pixel_tready => sReadyMirror, 
   343:         m_axis_jls_tdata    => m_axis_jls_tdata, 
   344:         m_axis_jls_tkeep    => m_axis_jls_tkeep, 
   345:         m_axis_jls_tvalid   => m_axis_jls_tvalid, 
   346:         m_axis_jls_tlast    => m_axis_jls_tlast, 
   347:         m_axis_jls_tready   => m_axis_jls_tready 
   348:       ); 
   349:    
   350:   end architecture rtl;